Accessing Key Vault with @azure/identity and get error 'Request is missing a Bearer or PoP token Error 401'

Viewed 7288

I'm trying to retrieve some secrets from Azure's keyvault but I cannot seem to authenticate using @azure/identity module.

Versions:

"@azure/identity": "^1.0.0-preview.6",
"@azure/keyvault-secrets": "^4.0.0-preview.9",

I have an azure functions app and I have configured the app both in production and locally using the local.settings.json having filled in the proper values for:

{
    "IsEncrypted": false,
    "Values": {
        "AZURE_CLIENT_ID": "REDACTED",
        "AZURE_CLIENT_SECRET": "REDACTED",
        "AZIRE_TENANT_ID": "REDACTED"
    },
    "ConnectionStrings": {}
}

  • App Registered via Azure Active Directory => App Registrations.
  • Disabled login
  • Created App Secret

Then, I have added the app to the keyvault with the role 'reader' giving it the ability to 'get' secrets but nothing else, not even list:

Role Assignment screenshot

Now when I try to retreive the secrets:

import { KeyVaultSecret, SecretClient } from '@azure/keyvault-secrets';
import { EnvironmentCredential } from '@azure/identity';

export const GetSecret = async (key: string): Promise<string> => {
    try {
        const credential: EnvironmentCredential = new EnvironmentCredential();

        console.log('CREDENTIAL: ', credential);
        console.log('CLIENT SECRET', process.env.AZURE_CLIENT_SECRET);
        console.log('CLIENT ID', process.env.AZURE_CLIENT_ID);

        const url = 'https://tlabs-vault.vault.azure.net';
        const client = new SecretClient(url, credential);
        let secret: KeyVaultSecret = await client.getSecret(key);
        return secret.value;
    } catch (err) {
        console.error('Error getting secret from Azure Vault', err);
    }
};

But this is not working, on the console I see the result of credentials as:

EnvironmentCredential { _credential: undefined }

And the full request that throws the error:

request:
[10/28/2019 1:14:16 PM]    WebResource {
[10/28/2019 1:14:16 PM]      streamResponseBody: false,
[10/28/2019 1:14:16 PM]      url:
[10/28/2019 1:14:16 PM]       'https://REDACTED_VAULT_NAME.vault.azure.net/secrets/REDACTED_SECRET_NAME/?api-version=7.0',
[10/28/2019 1:14:16 PM]      method: 'GET',
[10/28/2019 1:14:16 PM]      headers: HttpHeaders { _headersMap: [Object] },
[10/28/2019 1:14:16 PM]      body: undefined,
[10/28/2019 1:14:16 PM]      query: undefined,
[10/28/2019 1:14:16 PM]      formData: undefined,
[10/28/2019 1:14:16 PM]      withCredentials: false,
[10/28/2019 1:14:16 PM]      abortSignal: undefined,
[10/28/2019 1:14:16 PM]      timeout: 0,
[10/28/2019 1:14:16 PM]      onUploadProgress: undefined,
[10/28/2019 1:14:16 PM]      onDownloadProgress: undefined,
[10/28/2019 1:14:16 PM]      proxySettings: undefined,
[10/28/2019 1:14:16 PM]      keepAlive: true,
[10/28/2019 1:14:16 PM]      operationSpec:
[10/28/2019 1:14:16 PM]       { httpMethod: 'GET',
[10/28/2019 1:14:16 PM]         path: 'secrets/{secret-name}/{secret-version}',
[10/28/2019 1:14:16 PM]         urlParameters: [Array],
[10/28/2019 1:14:16 PM]         queryParameters: [Array],
[10/28/2019 1:14:16 PM]         responses: [Object],
[10/28/2019 1:14:16 PM]         serializer: [Serializer] } },
[10/28/2019 1:14:16 PM]   response:
[10/28/2019 1:14:16 PM]    { body:
[10/28/2019 1:14:16 PM]       '{"error":{"code":"Unauthorized","message":"Request is missing a Bearer or PoP token."}}',
[10/28/2019 1:14:16 PM]      headers: HttpHeaders { _headersMap: [Object] },
[10/28/2019 1:14:16 PM]      status: 401,
[10/28/2019 1:14:16 PM]      parsedBody: { error: [Object] } },
[10/28/2019 1:14:16 PM]   details:
[10/28/2019 1:14:16 PM]    { error:
[10/28/2019 1:14:16 PM]       { code: 'Unauthorized',
[10/28/2019 1:14:16 PM]         message: 'Request is missing a Bearer or PoP token.' } } }
1 Answers

Please follow this blog about how to Integrate Key Vault Secrets With Azure Functions.

The main steps are Enable system-asigned managed identity for the Function App and Add Key Vault access policy for the Function App.

enter image description here

After these don't forget to add Key Vault secrets reference in the Function App configuration with @Microsoft.KeyVault(SecretUri={copied identifier for the username secret}). If you set it correctly, after configuration it will display the below pic.

enter image description here

And below is my test result, I use os.environ[name] to get the secret.

enter image description here

Related