Search code examples
javascripthashicorp-vaulthash-vault-js

access property of an object using hash-vault-js


following the documentation of the hash-vault-js node package I am trying to use I should be able to get the token from the response using:

const token = await vault.loginWithAppRole(RoleId, SecretId).client_token;

but

console.log(token);

returns undefined. The full response is:

{
    client_token: 'hvs.CAESIBbqO37msc9GKEMnYLm0B40tSeA1VuOQtkOqzx4q47BTGh4KHGh2cy50MUZra3V4UFYwSXZNdkhaYjJPTEtMY2M',
    accessor: 'L321k60IkDv7QDJPS8yBurBM',
    policies: [ 'default' ],
    token_policies: [ 'default' ],
    metadata: { role_name: 'liveslowsailfast' },
    lease_duration: 1200,
    renewable: true,
    entity_id: '079a8b50-8177-f044-c99d-690ef269db9d',
    token_type: 'service',
    orphan: true,
    mfa_requirement: null,
    num_uses: 0
}

So the question now is: what is the correct way to retrieve the client_token value?


Solution

  • My guess is that the documentation isn't tested and provides a faulty example.

    Looking at the source of loginWithAppRole() we can see that it is defined as an async method. Meaning that it will return a promise when called.

      async loginWithAppRole(roleId, secretId, mount) {
        …
    
        try {
          const response = await this.instance(Options);
          return parseAxiosResponse(response);
        } catch(err) {
          throw parseAxiosError(err);
        }
      }
    

    Coming back to the line:

    const token = await vault.loginWithAppRole(RoleId, SecretId).client_token;
    

    The operator precedence will evaluate the code like:

    const token = await ((vault.loginWithAppRole(RoleId, SecretId)).client_token);
    

    Meaning that we access the client_token property of the returned promise, which results in undefined since promises don't have that property. Then we await undefined, which resolves into undefined similar to how await 42 resolves into just 42.


    To solve the issue you want to await the result of vault.loginWithAppRole(RoleId, SecretId), then access client_token on the resolved value.

    We can do this by adding a single pair of parentheses to the example like this:

    const token = (await vault.loginWithAppRole(RoleId, SecretId)).client_token;
    

    Alternatively you could store the response in a variable first, which also fixes the precedence issue:

    const response = await vault.loginWithAppRole(RoleId, SecretId);
    const token = response.client_token;