Use Azure Key Vault secrets in Express.js app

With Azure CLI, store secrets in Azure Key Vault, then use those secrets programmatically from Key Vault in your Express.js app.

Prepare your development environment

Complete the Express.js with Cosmos DB tutorial but do not delete the resources at the end of the procedure.

When you complete the previous tutorial, you should have an Express.js app using a Cosmos DB database deployed to an Azure web app.

Sign in to Azure CLI

In the Visual Studio Code integrated terminal, sign in to the Azure CLI. This requires you to authenticate in a browser with your account, which has permission on a valid Azure Subscription.

Use the az Login command to sign in.

az login

Create a Key Vault resource with Azure CLI

Use the az keyvault create command to create a Key Vault resource in the resource group.

az keyvault create \
    --subscription REPLACE_WITH_YOUR_SUBSCRIPTION_NAME_OR_ID \
    --resource-group REPLACE_WITH_YOUR_RESOURCE_GROUP_NAME \
    --name REPLACE_WITH_YOUR_KEY_VAULT_NAME

Your Azure account is the only one authorized to perform any operations on this new vault. Make note of the output values:

  • Vault Name: The name you provided to the --name parameter above.
  • Vault URI: The URL format is https://<YOUR_KEY_VAULT_NAME>.vault.azure.net/.

Create a service principal with Azure CLI

The service principal allows you to create and use resources without having to use or expose your personal user account. The service principal is stored as an App Registration in Azure Active Directory.

This sample uses the DefaultAzureCredential, which requires authentication setup. One example of setting up the credential is to create and use a service principal.

  1. Use the az ad sp create-for-rbac command to create a service principal with a scope for your resource group.

    az ad sp create-for-rbac \
        --name SERVICE-PRINCIPAL-NAME \
        --role Contributor \
        --scopes "/subscriptions/SUBSCRIPTION_NAME_OR_ID/resourceGroups/RESOURCE-GROUP-NAME"
    
    Term Replace with
    SERVICE-PRINCIPAL-NAME An example SERVICE-PRINCIPAL-NAME is demo-keyvault-service-principal-YOUR-NAME, where YOUR-NAME is postpended to the string.
    SUBSCRIPTION_NAME_OR_ID Your subscription ID is preferred. You can find this on the resource group's Overview page in the Azure portal.
    RESOURCE-GROUP-NAME Your resource group name - the service principal authorization is scoped to just this resource group.

    Troubleshooting: If you receive an error on this step, review the following Azure CLI issue 16317. Try executing the command from a different terminal or command line.

  2. Capture and save the service principal output results of the command to use later.

    {
        "appId": "YOUR-APP-ID-VALUE",
        "displayName": "YOUR-SERVICE-PRINCIPAL-DISPLAY-NAME",
        "name": "YOUR-SERVICE-PRINCIPAL-NAME",
        "password": "!@#$%",
        "tenant": "YOUR-TENANT-ID"
    }
    

    Notice that the value of the appId property has the same value as the name property.

Give your service principal access to your key vault

Use the az keyvault set-policy command to give your service principal access to your Key Vault with Azure CLI command. The value for YOUR-SERVICE-PRINCIPAL-NAME is your service principal output's name value. Do not use the displayName value.

az keyvault set-policy \
    --subscription REPLACE-WITH-YOUR-SUBSCRIPTION-NAME-OR-ID \
    --resource-group RESOURCE-GROUP-NAME \
    --name "REPLACE-WITH-YOUR-KEY-VAULT-NAME" \
    --spn YOUR-SERVICE-PRINCIPAL-NAME \
    --secret-permissions get list

This service principal will only be able to list all secrets or get a specific secret. You can see this service principal in the Azure portal for your Key Vault

Store your secret environment variable in Key Vault resource

Use the az keyvault secret set command to add your MongoDB connection string, created in the prior tutorial, as a secret named DATABASE-URL to your key vault on the Settings -> Access policies page.

az keyvault secret set \
    --subscription REPLACE-WITH-YOUR-SUBSCRIPTION-NAME-OR-ID \
    --vault-name "REPLACE-WITH-YOUR-KEY-VAULT-NAME" \
    --name "DATABASE-URL" \
    --value "YOUR-COSMOS-DB-MONGODB-CONNECTION-STRING"

Note

DATABASE-URL, as a secret name, is not a keyword. You could choose any name to identify the secret. Just use that name consistently in the remaining instructions.

Optional: Configure Express.js required environment variables to use Azure Identity

Complete this step if you can't use the Visual Studio Code credential, Azure CLI credential, or the Azure PowerShell credential. Learn more about local development credentials.

Set these environment variables in the .env file of the sample project to create the REQUIRED context to use DefaultAzureCredential.

  • AZURE_TENANT_ID: The tenant from the service principal output above.
  • AZURE_CLIENT_ID: The appId from the service principal output above.
  • AZURE_CLIENT_SECRET: The password from the service principal output above.

When you deploy the application to Azure app service, you'll also need to add these settings to your web app.

Note

These variables names are keywords and must be used as-is, without changes, in order for Azure Identity to work successfully.

Configure Express.js required environment variables to use Azure Key Vault

Set these environment variables in the .env file of the sample project to programmatically determine which Key Vault resource and secret to use.

  • KEY_VAULT_NAME: Same value as REPLACE-WITH-YOUR-KEY-VAULT-NAME used in previous commands.
  • KEY_VAULT_SECRET_NAME_DATABASE_URL: The secret name, DATABASE-URL. Notice the name uses a dash, -, instead of an underscore, _ used in the previous tutorial.

When you deploy the application to Azure app service, you'll also need to add these settings to your web app.

Note

These variable names are specific to this sample. You can change them but make sure to change them in the environment file, the source code file, and your deployed web app settings.

Run the local program

  1. Run the Express.js app with the following command:

    npm start
    
  2. Open the Express.js app in the browser: http://localhost:3000.

  3. Interact with the app, adding and deleting tasks.

Update the App Service app settings for Key vault

Add the Key vault and DefaultAzureCredential to the Azure App Service's app settings.

  1. Use the following Azure CLI command to add the KEY_VAULT_NAME app setting. The value is in the .env file.

    az webapp config appsettings set \
        --name YOUR-APP-SERVICE-NAME \
        --resource-group REPLACE_WITH_YOUR_RESOURCE_GROUP_NAME
        --settings KEY_VAULT_NAME=msdocs-key-vault-123
    
    Property Value
    KEY_VAULT_NAME msdocs-key-vault-123
  2. Use the following Azure CLI command to add the KEY_VAULT_SECRET_NAME_DATABASE_URL app setting. The value is in the .env file.

    az webapp config appsettings set \
        --name YOUR-APP-SERVICE-NAME \
        --resource-group REPLACE_WITH_YOUR_RESOURCE_GROUP_NAME
        --settings KEY_VAULT_SECRET_NAME_DATABASE_URL=DATABASE-URL
    
    Property Value
    KEY_VAULT_SECRET_NAME_DATABASE_URL DATABASE-URL

Update the App Service app settings for service principal

To use the service principal to authorize access from the hosting platform to Key vault in source code, the App Service environment needs to those specifically-named settings for the DefaultAzureCredential.

  1. Use the following Azure CLI command to add the AZURE_TENANT_ID app setting. The value is in the .env file.

    az webapp config appsettings set \
        --name YOUR-APP-SERVICE-NAME \
        --resource-group REPLACE_WITH_YOUR_RESOURCE_GROUP_NAME
        --settings AZURE_TENANT_ID=
    
    Property Value
    AZURE_TENANT_ID This is the tenant property from the service principal object.
  2. Use the following Azure CLI command to add the AZURE_CLIENT_ID app setting. The value is in the .env file.

    az webapp config appsettings set \
        --name YOUR-APP-SERVICE-NAME \
        --resource-group REPLACE_WITH_YOUR_RESOURCE_GROUP_NAME
        --settings AZURE_CLIENT_ID=
    
    Property Value
    AZURE_CLIENT_ID This is the appId property from the service principal object.
  3. Use the following Azure CLI command to add the AZURE_CLIENT_SECRET app setting. The value is in the .env file.

    az webapp config appsettings set \
        --name YOUR-APP-SERVICE-NAME \
        --resource-group REPLACE_WITH_YOUR_RESOURCE_GROUP_NAME
        --settings AZURE_CLIENT_SECRET=
    
    Property Value
    AZURE_CLIENT_SECRET This is the password property from the service principal object.

Clean up resources - remove resource group

Once you've completed this tutorial, you need to remove the resource group with the az group delete command.

az group delete \
--name REPLACE_WITH_YOUR_RESOURCE_GROUP_NAME  -y

This command may take a few minutes.

Clean up resources - remove service principal

Delete your service principal with the az ad sp delete command.

az ad sp delete \
--id YOUR-SERVICE-PRINCIPAL-NAME

Next steps