azure-sdk-for-js: "Request is missing a Bearer or PoP token." with Client token

  • Package Name: @azure/keyvault-secrets
  • Package Version: “^4.1.0”
  • Operating system: Windows 10
  • nodejs
    • version: 14.8.0
  • browser
    • name/version: Chrome/84.0.4147.135
  • typescript
    • version: “^3.9.6”
  • Is the bug related to documentation in

Describe the bug Access Azure Key Vault from Gatsby/React app Initiate access with

        this.keyVaultUri = `https://${keyVaultName}.vault.azure.net`;
        const credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
        this.keyVaultClient = new SecretClient(this.keyVaultUri, credential);

Get a specific secret lke

    get GoogleMapApiKey() {
        return (async () => await this.keyVaultClient.getSecret('GoogleMapApiKey'));
    }

Get the secret value like:

        const mapsKey:KeyVaultSecret = await keyVault.GoogleMapApiKey();
        setGoogleMapsApiKey(mapsKey.value ?? '' );

To Reproduce Steps to reproduce the behavior: Illustrated in the description

Expected behavior Should retrieve the secret from the Azure Key Vault.

Additional context This seems related to #9005. This is a Gatsby React app. I am using TypeScript.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 29 (16 by maintainers)

Most upvoted comments

One more thought for which I have NO experience is to add Azure function to the app. Since it is already being deployed to static web site on Azure this seems like a natural place to put a function?

Again thank you for the help.

Kevin

On Wed, Aug 26, 2020 at 1:05 PM Daniel Rodríguez notifications@github.com wrote:

@KevinBurton https://github.com/KevinBurton that’s a good spot to be in! So many things to learn! Alright, good luck with that study!

If you happen to find the solution before me, please report back.

I’ll put some time over the weekend trying to deploy a Gatsby App using Azure App Service and our KeyVault clients to see if I can come up with something else.

I’m also asking internally in case somebody else knows more than me about this.

In case none of us has a better answer soon, see you in some days! good luck!

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/Azure/azure-sdk-for-js/issues/10828#issuecomment-681037320, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAUFM3XCCTFI5CIADUNDFS3SCVFFZANCNFSM4QKQB2IA .

It would. If you have time. Thank you.

Kevin

On Wed, Aug 26, 2020 at 1:01 PM Daniel Rodríguez notifications@github.com wrote:

@KevinBurton https://github.com/KevinBurton I might be able to dig deeper and try to deploy a Gatsby app myself later this week or next week, if that helps.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/Azure/azure-sdk-for-js/issues/10828#issuecomment-681035623, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAUFM3R75THFO4ADVLSCMB3SCVEZDANCNFSM4QKQB2IA .

I am too new to Gatsby to understand how this all works but I will look into it. The big hurdle for me right now is the comment “and you could invoke that and await inside your plugin”, which indicates to me that I need to develop and use a plugin which right now I don’t know how to do.

On Wed, Aug 26, 2020 at 12:57 PM Daniel Rodríguez notifications@github.com wrote:

@KevinBurton https://github.com/KevinBurton some Gatsby users seem to be using plugins in the configuration object to provide an asynchronous way of retrieving configuration, as shown here: gatsbyjs/gatsby#11128 (comment) https://github.com/gatsbyjs/gatsby/issues/11128#issuecomment-458609530 would that approach be viable for you?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/Azure/azure-sdk-for-js/issues/10828#issuecomment-681033189, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAUFM3V4U3C24ELUMBXSWW3SCVEH3ANCNFSM4QKQB2IA .

Oops I forgot to add in the secrets to the config.

siteMetadata: { title: Great State Strength and Conditioning, description: Great State web page, author: @KevinBurton, …keyVaultSecrets },

Kevin

On Wed, Aug 26, 2020 at 12:15 PM Kevin Burton ronald.kevin.burton@gmail.com wrote:

So now gatsby-config looks like:

const { ClientSecretCredential } = require(“@azure/identity”); const { SecretClient } = require(“@azure/keyvault-secrets”); require(“dotenv”).config({ path: .env.${process.env.NODE_ENV}, })

const KVUri = https://${process.env.AZURE_KEY_VAULT_NAME}.vault.azure.net ;

const credential = new ClientSecretCredential(process.env.AZURE_TENANT_ID , process.env.AZURE_CLIENT_ID, process.env. AZURE_CLIENT_SECRET); const client = new SecretClient(KVUri, credential);

async function getSecrets() {

let keyVaultSecrets = { ‘auth0Domain’: ‘’, ‘auth0ClientId’: ‘’, ‘auth0Secret’: ‘’, ‘recaptchaSiteKey’: ‘’, ‘recaptchaSecretKey’: ‘’, ‘googleMapsApiKey’: ‘’, ‘wodifyUser’: ‘’, ‘wodifyPassword’: ‘’ };

const KVUri = https://${process.env.AZURE_KEY_VAULT_NAME}. vault.azure.net;

const credential = new ClientSecretCredential(process.env. AZURE_TENANT_ID, process.env. AZURE_CLIENT_ID, process.env. AZURE_CLIENT_SECRET); const client = new SecretClient(KVUri, credential); let retrievedSecret; retrievedSecret = await client.getSecret(‘Auth0Domain’); keyVaultSecrets.auth0Domain = retrievedSecret.value; retrievedSecret = await client.getSecret(‘Auth0ClientId’); keyVaultSecrets.auth0ClientId = retrievedSecret.value; retrievedSecret = await client.getSecret(‘Auth0Secret’); keyVaultSecrets.auth0Secret = retrievedSecret.value; retrievedSecret = await client.getSecret(‘RecaptchaSiteKey’); keyVaultSecrets.recaptchaSiteKey = retrievedSecret.value; retrievedSecret = await client.getSecret(‘RecaptchaSecretKey’); keyVaultSecrets.recaptchaSecretKey = retrievedSecret.value; retrievedSecret = await client.getSecret(‘GoogleMapsApiKey’); keyVaultSecrets.googleMapsApiKey = retrievedSecret.value; process.env.GOOGLE_MAPS_API_KEY = keyVaultSecrets.googleMapsApiKey; retrievedSecret = await client.getSecret(‘WodifyUser’); keyVaultSecrets.wodifyUser = retrievedSecret.value; retrievedSecret = await client.getSecret(‘WodifyPassword’); keyVaultSecrets.wodifyPassword = retrievedSecret.value; // console.log(keyVaultSecrets); return keyVaultSecrets; }

const keyVaultSecrets = await getSecrets();

let config = { siteMetadata: { title: Great State Strength and Conditioning, description: Great State web page, author: @KevinBurton, }, plugins: [ gatsby-plugin-react-helmet, { resolve: gatsby-source-filesystem, options: { name: images, path: ${__dirname}/src/assets, }, }, gatsby-plugin-styled-components, gatsby-transformer-sharp, gatsby-plugin-sharp, gatsby-plugin-material-ui, gatsby-plugin-sass,

// this (optional) plugin enables Progressive Web App + Offline functionality // To learn more, visit: https://gatsby.dev/offline // gatsby-plugin-offline, ], };

module.exports = config;

Adding

“author”: “Kevin Burton rkevinburton@charter.net”, “type”: “module”, “dependencies”: {

to package.json. But now I get

yarn start yarn run v1.22.4 $ yarn run develop $ gatsby develop internal/process/esm_loader.js:74 internalBinding(‘errors’).triggerUncaughtException( ^

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension “” for C:\Users\RKevi\source\repos\GreatState-gatsby.cache\tmp-30928-4nOKL4bzTny6 at Loader.defaultGetFormat [as _getFormat] (internal/modules/esm/get_format.js:65:15) at Loader.getFormat (internal/modules/esm/loader.js:101:42) at Loader.getModuleJob (internal/modules/esm/loader.js:230:31) at async Loader.import (internal/modules/esm/loader.js:164:17) at async Object.loadESM (internal/process/esm_loader.js:68:5) { code: ‘ERR_UNKNOWN_FILE_EXTENSION’ } error Command failed with exit code 1. info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command. error Command failed with exit code 1. info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

If I take the “type”:“module” out of package.json I get

For help, see: https://nodejs.org/en/docs/inspector

ERROR #10123 CONFIG

We encountered an error while trying to load your site’s gatsby-config. Please fix the error and try again.

Error: C:\Users\RKevi\source\repos\GreatState-gatsby\gatsby-config.js:55 const keyVaultSecrets = await getSecrets(); ^^^^^ SyntaxError: await is only valid in async function

  • v8-compile-cache.js:226 NativeCompileCache._moduleCompile

On Wed, Aug 26, 2020 at 12:04 PM Daniel Rodríguez < notifications@github.com> wrote:

@KevinBurton https://github.com/KevinBurton alright, for the top level await, I had to add this property and value to my package.json:

“type”: “module”,

After that I was able to run the code I sent you with the top-level await. I hope that helps!

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/Azure/azure-sdk-for-js/issues/10828#issuecomment-681006345, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAUFM3QHGUKLKGF4QW6MFALSCU57NANCNFSM4QKQB2IA .

By the way I am using node v14.8.0, I am not sure what needs to change to support this asynchronous feature?

On Wed, Aug 26, 2020 at 11:42 AM Kevin Burton ronald.kevin.burton@gmail.com wrote:

Thank you for your help.

Here is my gatsby-config.js

const { ClientSecretCredential } = require(“@azure/identity”); const { SecretClient } = require(“@azure/keyvault-secrets”); require(“dotenv”).config({ path: .env.${process.env.NODE_ENV}, })

const KVUri = https://${process.env.AZURE_KEY_VAULT_NAME}.vault.azure.net ;

const credential = new ClientSecretCredential(process.env.AZURE_TENANT_ID , process.env.AZURE_CLIENT_ID, process.env. AZURE_CLIENT_SECRET); const client = new SecretClient(KVUri, credential);

async function getSecrets() {

let keyVaultSecrets = { ‘auth0Domain’: ‘’, ‘auth0ClientId’: ‘’, ‘auth0Secret’: ‘’, ‘recaptchaSiteKey’: ‘’, ‘recaptchaSecretKey’: ‘’, ‘googleMapsApiKey’: ‘’, ‘wodifyUser’: ‘’, ‘wodifyPassword’: ‘’ };

const KVUri = https://${process.env.AZURE_KEY_VAULT_NAME}. vault.azure.net;

const credential = new ClientSecretCredential(process.env. AZURE_TENANT_ID, process.env. AZURE_CLIENT_ID, process.env. AZURE_CLIENT_SECRET); const client = new SecretClient(KVUri, credential); let retrievedSecret; retrievedSecret = await client.getSecret(‘Auth0Domain’); keyVaultSecrets.auth0Domain = retrievedSecret.value; retrievedSecret = await client.getSecret(‘Auth0ClientId’); keyVaultSecrets.auth0ClientId = retrievedSecret.value; retrievedSecret = await client.getSecret(‘Auth0Secret’); keyVaultSecrets.auth0Secret = retrievedSecret.value; retrievedSecret = await client.getSecret(‘RecaptchaSiteKey’); keyVaultSecrets.recaptchaSiteKey = retrievedSecret.value; retrievedSecret = await client.getSecret(‘RecaptchaSecretKey’); keyVaultSecrets.recaptchaSecretKey = retrievedSecret.value; retrievedSecret = await client.getSecret(‘GoogleMapsApiKey’); keyVaultSecrets.googleMapsApiKey = retrievedSecret.value; process.env.GOOGLE_MAPS_API_KEY = keyVaultSecrets.googleMapsApiKey; retrievedSecret = await client.getSecret(‘WodifyUser’); keyVaultSecrets.wodifyUser = retrievedSecret.value; retrievedSecret = await client.getSecret(‘WodifyPassword’); keyVaultSecrets.wodifyPassword = retrievedSecret.value; console.log(keyVaultSecrets); return keyVaultSecrets; }

let config = { siteMetadata: { title: Great State Strength and Conditioning, description: Great State web page, author: @KevinBurton, auth0Domain: ‘’, auth0ClientId: ‘’, auth0Secret: ‘’, recaptchaSiteKey: ‘’, recaptchaSecretKey: ‘’, googleMapsApiKey: ‘’, wodifyUser: ‘’, wodifyPassword: ‘’ }, plugins: [ gatsby-plugin-react-helmet, { resolve: gatsby-source-filesystem, options: { name: images, path: ${__dirname}/src/assets, }, }, gatsby-plugin-styled-components, gatsby-transformer-sharp, gatsby-plugin-sharp, gatsby-plugin-material-ui, gatsby-plugin-sass,

// this (optional) plugin enables Progressive Web App + Offline functionality // To learn more, visit: https://gatsby.dev/offline // gatsby-plugin-offline, ], };

getSecrets();

module.exports = config;

The problem is that the export doesn’t seem to wait for the asynchronous call to resolve before returning. Lets just focus on the googMapsApiKey. If I put a literal string for the value that is exported it seems to work. But what I want is the value resolved in the Promise. NOTE: There are no getters here that I have control over.

Kevin

On Wed, Aug 26, 2020 at 11:35 AM Daniel Rodríguez < notifications@github.com> wrote:

@KevinBurton https://github.com/KevinBurton oh that also helped me! Thank you.

So far, I’m understanding that you have a gatsby-config.js where you’re trying to use KeyVault-Secrets.

Do you mind sharing more of your gatsby-config.js? I want to see more clearly where you’re retrieving the secret.

The latest NodeJS version (or at least above 14.3.0) does support top-level await, so you could retrieve your secret in your gatsby-config.js before returning the configuration object, something like this:

// Imagine this is your gatsby-config.js

// You declare the KeyVault client first.

// Then you retrieve the secret at the top-level, no functions needed:

const secret = await keyVaultClient.getSecret(‘GoogleMapApiKey’);

// Then you proceed with your gatsby-config.js, where you can use that secret as many times as you need.

// …

Would that help?

Please share more information about your gatsby-config.json if that doesn’t help.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/Azure/azure-sdk-for-js/issues/10828#issuecomment-680990575, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAUFM3VY5VGESC57SFGEULTSCU2TLANCNFSM4QKQB2IA .