This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Note
Access to this page requires authorization. You can trysigning in orchanging directories.
Access to this page requires authorization. You can trychanging directories.
This article offers guidelines to help you maximize the performance and reliability of your JavaScript and TypeScript apps when authenticating to Azure services. To make the most of the Azure Identity library for JavaScript, it's important to understand potential issues and mitigation techniques.
DefaultAzureCredential is the most approachable way to get started with the Azure Identity library, but that convenience also introduces certain tradeoffs. Most notably, the specific credential in the chain that will succeed and be used for request authentication can't be guaranteed ahead of time. In a production environment, this unpredictability can introduce significant and sometimes subtle problems.
For example, consider the following hypothetical sequence of events:
DefaultAzureCredential to authenticate via managed identity.az login command to authenticate to Azure.DefaultAzureCredential skips the failedManagedIdentityCredential and searches for the next available credential, which isAzureCliCredential.To prevent these types of subtle issues or silent failures in production apps, replaceDefaultAzureCredential with a specificTokenCredential implementation, such asManagedIdentityCredential. See theAzure Identity client library documentation for available credentials.
For example, consider the followingDefaultAzureCredential configuration in an Express.js project:
import { DefaultAzureCredential } from "@azure/identity";import { SecretClient } from "@azure/keyvault-secrets";import { BlobServiceClient } from "@azure/storage-blob";const credential = new DefaultAzureCredential();const secretClient = new SecretClient("https://keyVaultName.vault.azure.net", credential);const blobServiceClient = new BlobServiceClient( "https://storageAccountName.blob.core.windows.net", credential);Modify the preceding code to select a credential based on the environment in which the app is running:
import { AzureDeveloperCliCredential, ManagedIdentityCredential, ChainedTokenCredential, AzureCliCredential } from "@azure/identity";import { SecretClient } from "@azure/keyvault-secrets";import { BlobServiceClient } from "@azure/storage-blob";let credential;// In production, use only ManagedIdentityCredentialif (process.env.NODE_ENV === 'production') { // For user-assigned managed identity, provide the client ID credential = new ManagedIdentityCredential(process.env.AZURE_CLIENT_ID);}// In development, use a chain of credentials appropriate for local workelse { credential = new ChainedTokenCredential( new AzureCliCredential(), new AzureDeveloperCliCredential() );}// Initialize Key Vault clientconst secretClient = new SecretClient("https://keyVaultName.vault.azure.net", credential);// Initialize Blob Storage clientconst blobServiceClient = new BlobServiceClient( "https://storageAccountName.blob.core.windows.net", credential);In this example, onlyManagedIdentityCredential is used in production. The local development environment's authentication needs are then serviced by the sequence of credentials defined in theelse clause.
Reuse credential instances when possible to improve app resilience and reduce the number of access token requests issued to Microsoft Entra ID. When a credential is reused, an attempt is made to fetch a token from the app token cache managed by the underlying MSAL dependency. For more information, seeToken caching in the Azure Identity client library.
Token caching behavior differs between browser and Node.js environments. In Node.js applications, tokens are cached in memory by default, which means the cache is lost when the application restarts. In browser applications, tokens can be persisted in browser storage (localStorage orsessionStorage) depending on the authentication flow and configuration. Understanding these differences is important when implementing credential reuse strategies for different application types.
Important
A high-volume app that doesn't reuse credentials may encounter HTTP 429 throttling responses from Microsoft Entra ID, which can lead to app outages.
The recommended credential reuse strategy differs by application framework.
To implement credential reuse in JavaScript applications, create a single credential instance and reuse it across all client objects:
import { DefaultAzureCredential, ManagedIdentityCredential } from "@azure/identity";import { SecretClient } from "@azure/keyvault-secrets";import { BlobServiceClient } from "@azure/storage-blob";// Create a single credential instanceconst credential = process.env.NODE_ENV === 'production' ? new ManagedIdentityCredential(process.env.AZURE_CLIENT_ID) : new DefaultAzureCredential();// Reuse the credential across different client objectsconst secretClient = new SecretClient("https://keyVaultName.vault.azure.net", credential);const blobServiceClient = new BlobServiceClient( "https://storageAccountName.blob.core.windows.net", credential);In Express.js applications, you can store the credential in app settings and access it in your route handlers:
import express from "express";import { DefaultAzureCredential, ManagedIdentityCredential } from "@azure/identity";import { SecretClient } from "@azure/keyvault-secrets";import { BlobServiceClient } from "@azure/storage-blob";const app = express();// Create a single credential instance at app startupapp.locals.credential = process.env.NODE_ENV === 'production' ? new ManagedIdentityCredential(process.env.AZURE_CLIENT_ID) : new DefaultAzureCredential();// Reuse the credential in route handlersapp.get('/api/secrets/:secretName', async (req, res) => { const secretClient = new SecretClient( "https://keyVaultName.vault.azure.net", req.app.locals.credential ); try { const secret = await secretClient.getSecret(req.params.secretName); res.json({ name: secret.name, value: secret.value }); } catch (error) { res.status(500).json({ error: error.message }); }});// Add this route to the existing Express appapp.get('/api/blobs/:containerName', async (req, res) => { const blobServiceClient = new BlobServiceClient( "https://storageAccountName.blob.core.windows.net", req.app.locals.credential ); try { // Get reference to a container const containerClient = blobServiceClient.getContainerClient(req.params.containerName); // List all blobs in the container const blobs = []; for await (const blob of containerClient.listBlobsFlat()) { blobs.push({ name: blob.name, contentType: blob.properties.contentType, size: blob.properties.contentLength, lastModified: blob.properties.lastModified }); } res.json({ containerName: req.params.containerName, blobs }); } catch (error) { res.status(500).json({ error: error.message }); }});app.listen(3000, () => console.log('Server running on port 3000'));If you use an Azure Identity library credential outside the context of an Azure SDK client library, it becomes your responsibility to managetoken lifetime and caching behavior in your app.
TherefreshAfterTimestamp property onAccessToken, which provides a hint to consumers as to when token refresh can be attempted, will be automatically used by Azure SDK client libraries that depend on the Azure Core library to refresh the token. For direct usage of Azure Identity library credentials that support token caching, the underlying MSAL cache automatically refreshes proactively when therefreshAfterTimestamp time occurs. This design allows the client code to callTokenCredential.getToken() each time a token is needed and delegate the refresh to the library.
To only callTokenCredential.getToken() when necessary, observe therefreshAfterTimestamp date and proactively attempt to refresh the token after that time. The specific implementation is up to the customer.
The Azure Identity library for JavaScript allows you to authenticate via managed identity withManagedIdentityCredential. The way in which you useManagedIdentityCredential impacts the applied retry strategy:
DefaultAzureCredential, no retries are attempted when the initial token acquisition attempt fails or times out after a short duration. This is the least resilient option because it's optimized to "fail fast" for an efficient development inner loop.ChainedTokenCredential orManagedIdentityCredential directly:import { ManagedIdentityCredential } from "@azure/identity";const credential = new ManagedIdentityCredential( process.env.AZURE_CLIENT_ID, // For user-assigned managed identity { retryOptions: { maxRetries: 3, // Maximum number of retry attempts retryDelayInMs: 500, // Initial delay between retries (in milliseconds) maxRetryDelayInMs: 5000 // Maximum delay between retries (in milliseconds) } });For more information on customizing retry policies for managed identity, see one of the following options that extend fromTokenCredentialOptions:
Was this page helpful?
Need help with this topic?
Want to try using Ask Learn to clarify or guide you through this topic?
Was this page helpful?
Want to try using Ask Learn to clarify or guide you through this topic?