UNPKG

@azure/identity

Version:

Provides credential implementations for Azure SDK libraries that can authenticate with Microsoft Entra ID

162 lines (161 loc) 8.62 kB
// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. import { ChainedTokenCredential } from "./chainedTokenCredential.js"; import { credentialLogger } from "../util/logging.js"; import { createDefaultAzureCliCredential, createDefaultAzureDeveloperCliCredential, createDefaultAzurePowershellCredential, createDefaultBrokerCredential, createDefaultManagedIdentityCredential, createDefaultVisualStudioCodeCredential, createDefaultWorkloadIdentityCredential, createDefaultEnvironmentCredential, } from "./defaultAzureCredentialFunctions.js"; const logger = credentialLogger("DefaultAzureCredential"); /** * A no-op credential that logs the reason it was skipped if getToken is called. * @internal */ export class UnavailableDefaultCredential { credentialUnavailableErrorMessage; credentialName; constructor(credentialName, message) { this.credentialName = credentialName; this.credentialUnavailableErrorMessage = message; } getToken() { logger.getToken.info(`Skipping ${this.credentialName}, reason: ${this.credentialUnavailableErrorMessage}`); return Promise.resolve(null); } } /** * Provides a default {@link ChainedTokenCredential} configuration that works for most * applications that use Azure SDK client libraries. For more information, see * [DefaultAzureCredential overview](https://aka.ms/azsdk/js/identity/credential-chains#use-defaultazurecredential-for-flexibility). * * The following credential types will be tried, in order: * * - {@link EnvironmentCredential} * - {@link WorkloadIdentityCredential} * - {@link ManagedIdentityCredential} * - {@link VisualStudioCodeCredential} * - {@link AzureCliCredential} * - {@link AzurePowerShellCredential} * - {@link AzureDeveloperCliCredential} * - BrokerCredential (a broker-enabled credential that requires \@azure/identity-broker is installed) * * Consult the documentation of these credential types for more information * on how they attempt authentication. * * The following example demonstrates how to use the `requiredEnvVars` option to ensure that certain environment variables are set before the `DefaultAzureCredential` is instantiated. * If any of the specified environment variables are missing or empty, an error will be thrown, preventing the application from continuing execution without the necessary configuration. * It also demonstrates how to set the `AZURE_TOKEN_CREDENTIALS` environment variable to control which credentials are included in the chain. * ```ts snippet:defaultazurecredential_requiredEnvVars * import { DefaultAzureCredential } from "@azure/identity"; * * const credential = new DefaultAzureCredential({ * requiredEnvVars: [ * "AZURE_CLIENT_ID", * "AZURE_TENANT_ID", * "AZURE_CLIENT_SECRET", * "AZURE_TOKEN_CREDENTIALS", * ], * }); * ``` */ export class DefaultAzureCredential extends ChainedTokenCredential { constructor(options) { validateRequiredEnvVars(options); // If AZURE_TOKEN_CREDENTIALS is not set, use the default credential chain. const azureTokenCredentials = process.env.AZURE_TOKEN_CREDENTIALS ? process.env.AZURE_TOKEN_CREDENTIALS.trim().toLowerCase() : undefined; const devCredentialFunctions = [ createDefaultVisualStudioCodeCredential, createDefaultAzureCliCredential, createDefaultAzurePowershellCredential, createDefaultAzureDeveloperCliCredential, createDefaultBrokerCredential, ]; const prodCredentialFunctions = [ createDefaultEnvironmentCredential, createDefaultWorkloadIdentityCredential, createDefaultManagedIdentityCredential, ]; let credentialFunctions = []; const validCredentialNames = "EnvironmentCredential, WorkloadIdentityCredential, ManagedIdentityCredential, VisualStudioCodeCredential, AzureCliCredential, AzurePowerShellCredential, AzureDeveloperCliCredential"; // If AZURE_TOKEN_CREDENTIALS is set, use it to determine which credentials to use. // The value of AZURE_TOKEN_CREDENTIALS should be either "dev" or "prod" or any one of these credentials - {validCredentialNames}. if (azureTokenCredentials) { switch (azureTokenCredentials) { case "dev": credentialFunctions = devCredentialFunctions; break; case "prod": credentialFunctions = prodCredentialFunctions; break; case "environmentcredential": credentialFunctions = [createDefaultEnvironmentCredential]; break; case "workloadidentitycredential": credentialFunctions = [createDefaultWorkloadIdentityCredential]; break; case "managedidentitycredential": // Setting `sendProbeRequest` to false to ensure ManagedIdentityCredential behavior // is consistent when used standalone in DAC chain or used directly. credentialFunctions = [ () => createDefaultManagedIdentityCredential({ sendProbeRequest: false }), ]; break; case "visualstudiocodecredential": credentialFunctions = [createDefaultVisualStudioCodeCredential]; break; case "azureclicredential": credentialFunctions = [createDefaultAzureCliCredential]; break; case "azurepowershellcredential": credentialFunctions = [createDefaultAzurePowershellCredential]; break; case "azuredeveloperclicredential": credentialFunctions = [createDefaultAzureDeveloperCliCredential]; break; default: { // If AZURE_TOKEN_CREDENTIALS is set to an unsupported value, throw an error. // This will prevent the creation of the DefaultAzureCredential. const errorMessage = `Invalid value for AZURE_TOKEN_CREDENTIALS = ${process.env.AZURE_TOKEN_CREDENTIALS}. Valid values are 'prod' or 'dev' or any of these credentials - ${validCredentialNames}.`; logger.warning(errorMessage); throw new Error(errorMessage); } } } else { // If AZURE_TOKEN_CREDENTIALS is not set, use the default credential chain. credentialFunctions = [...prodCredentialFunctions, ...devCredentialFunctions]; } // Errors from individual credentials should not be thrown in the DefaultAzureCredential constructor, instead throwing on getToken() which is handled by ChainedTokenCredential. // When adding new credentials to the default chain, consider: // 1. Making the constructor parameters required and explicit // 2. Validating any required parameters in the factory function // 3. Returning a UnavailableDefaultCredential from the factory function if a credential is unavailable for any reason const credentials = credentialFunctions.map((createCredentialFn) => { try { return createCredentialFn(options ?? {}); } catch (err) { logger.warning(`Skipped ${createCredentialFn.name} because of an error creating the credential: ${err}`); return new UnavailableDefaultCredential(createCredentialFn.name, err.message); } }); super(...credentials); } } /** * This function checks that all environment variables in `options.requiredEnvVars` are set and non-empty. * If any are missing or empty, it throws an error. */ function validateRequiredEnvVars(options) { if (options?.requiredEnvVars) { const requiredVars = Array.isArray(options.requiredEnvVars) ? options.requiredEnvVars : [options.requiredEnvVars]; const missing = requiredVars.filter((envVar) => !process.env[envVar]); if (missing.length > 0) { const errorMessage = `Required environment ${missing.length === 1 ? "variable" : "variables"} '${missing.join(", ")}' for DefaultAzureCredential ${missing.length === 1 ? "is" : "are"} not set or empty.`; logger.warning(errorMessage); throw new Error(errorMessage); } } } //# sourceMappingURL=defaultAzureCredential.js.map