wangzhibo
2026-05-09 53418655c061ac26f66058253f39200aced1ab1d
1
{"version":3,"file":"environmentCredential.js","sourceRoot":"","sources":["../../../src/credentials/environmentCredential.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport { AuthenticationError, CredentialUnavailableError } from \"../errors.js\";\nimport { credentialLogger, formatError, formatSuccess, processEnvVars } from \"../util/logging.js\";\n\nimport { ClientCertificateCredential } from \"./clientCertificateCredential.js\";\nimport { ClientSecretCredential } from \"./clientSecretCredential.js\";\nimport type { EnvironmentCredentialOptions } from \"./environmentCredentialOptions.js\";\nimport { UsernamePasswordCredential } from \"./usernamePasswordCredential.js\";\nimport { checkTenantId } from \"../util/tenantIdUtils.js\";\nimport { tracingClient } from \"../util/tracing.js\";\n\n/**\n * Contains the list of all supported environment variable names so that an\n * appropriate error message can be generated when no credentials can be\n * configured.\n *\n * @internal\n */\nexport const AllSupportedEnvironmentVariables = [\n  \"AZURE_TENANT_ID\",\n  \"AZURE_CLIENT_ID\",\n  \"AZURE_CLIENT_SECRET\",\n  \"AZURE_CLIENT_CERTIFICATE_PATH\",\n  \"AZURE_CLIENT_CERTIFICATE_PASSWORD\",\n  \"AZURE_USERNAME\",\n  \"AZURE_PASSWORD\",\n  \"AZURE_ADDITIONALLY_ALLOWED_TENANTS\",\n  \"AZURE_CLIENT_SEND_CERTIFICATE_CHAIN\",\n];\n\nfunction getAdditionallyAllowedTenants(): string[] {\n  const additionallyAllowedValues = process.env.AZURE_ADDITIONALLY_ALLOWED_TENANTS ?? \"\";\n  return additionallyAllowedValues.split(\";\");\n}\n\nconst credentialName = \"EnvironmentCredential\";\nconst logger = credentialLogger(credentialName);\n\nexport function getSendCertificateChain(): boolean {\n  const sendCertificateChain = (\n    process.env.AZURE_CLIENT_SEND_CERTIFICATE_CHAIN ?? \"\"\n  ).toLowerCase();\n  const result = sendCertificateChain === \"true\" || sendCertificateChain === \"1\";\n  logger.verbose(\n    `AZURE_CLIENT_SEND_CERTIFICATE_CHAIN: ${process.env.AZURE_CLIENT_SEND_CERTIFICATE_CHAIN}; sendCertificateChain: ${result}`,\n  );\n  return result;\n}\n\n/**\n * Enables authentication to Microsoft Entra ID using a client secret or certificate.\n */\nexport class EnvironmentCredential implements TokenCredential {\n  private _credential?:\n    | ClientSecretCredential\n    | ClientCertificateCredential\n    | UsernamePasswordCredential = undefined;\n  /**\n   * Creates an instance of the EnvironmentCredential class and decides what credential to use depending on the available environment variables.\n   *\n   * Required environment variables:\n   * - `AZURE_TENANT_ID`: The Microsoft Entra tenant (directory) ID.\n   * - `AZURE_CLIENT_ID`: The client (application) ID of an App Registration in the tenant.\n   *\n   * If setting the AZURE_TENANT_ID, then you can also set the additionally allowed tenants\n   * - `AZURE_ADDITIONALLY_ALLOWED_TENANTS`: For multi-tenant applications, specifies additional tenants for which the credential may acquire tokens with a single semicolon delimited string. Use * to allow all tenants.\n   *\n   * Environment variables used for client credential authentication:\n   * - `AZURE_CLIENT_SECRET`: A client secret that was generated for the App Registration.\n   * - `AZURE_CLIENT_CERTIFICATE_PATH`: The path to a PEM certificate to use during the authentication, instead of the client secret.\n   * - `AZURE_CLIENT_CERTIFICATE_PASSWORD`: (optional) password for the certificate file.\n   * - `AZURE_CLIENT_SEND_CERTIFICATE_CHAIN`: (optional) indicates that the certificate chain should be set in x5c header to support subject name / issuer based authentication.\n   *\n   * Username and password authentication is deprecated, since it doesn't support multifactor authentication (MFA). See https://aka.ms/azsdk/identity/mfa for more details. Users can still provide environment variables for this authentication method:\n   * - `AZURE_USERNAME`: Username to authenticate with.\n   * - `AZURE_PASSWORD`: Password to authenticate with.\n   *\n   * If the environment variables required to perform the authentication are missing, a {@link CredentialUnavailableError} will be thrown.\n   * If the authentication fails, or if there's an unknown error, an {@link AuthenticationError} will be thrown.\n   *\n   * @param options - Options for configuring the client which makes the authentication request.\n   */\n  constructor(options?: EnvironmentCredentialOptions) {\n    // Keep track of any missing environment variables for error details\n\n    const assigned = processEnvVars(AllSupportedEnvironmentVariables).assigned.join(\", \");\n    logger.info(`Found the following environment variables: ${assigned}`);\n\n    const tenantId = process.env.AZURE_TENANT_ID,\n      clientId = process.env.AZURE_CLIENT_ID,\n      clientSecret = process.env.AZURE_CLIENT_SECRET;\n\n    const additionallyAllowedTenantIds = getAdditionallyAllowedTenants();\n    const sendCertificateChain = getSendCertificateChain();\n    const newOptions = { ...options, additionallyAllowedTenantIds, sendCertificateChain };\n\n    if (tenantId) {\n      checkTenantId(logger, tenantId);\n    }\n\n    if (tenantId && clientId && clientSecret) {\n      logger.info(\n        `Invoking ClientSecretCredential with tenant ID: ${tenantId}, clientId: ${clientId} and clientSecret: [REDACTED]`,\n      );\n      this._credential = new ClientSecretCredential(tenantId, clientId, clientSecret, newOptions);\n      return;\n    }\n\n    const certificatePath = process.env.AZURE_CLIENT_CERTIFICATE_PATH;\n    const certificatePassword = process.env.AZURE_CLIENT_CERTIFICATE_PASSWORD;\n    if (tenantId && clientId && certificatePath) {\n      logger.info(\n        `Invoking ClientCertificateCredential with tenant ID: ${tenantId}, clientId: ${clientId} and certificatePath: ${certificatePath}`,\n      );\n      this._credential = new ClientCertificateCredential(\n        tenantId,\n        clientId,\n        { certificatePath, certificatePassword },\n        newOptions,\n      );\n      return;\n    }\n\n    const username = process.env.AZURE_USERNAME;\n    const password = process.env.AZURE_PASSWORD;\n    if (tenantId && clientId && username && password) {\n      logger.info(\n        `Invoking UsernamePasswordCredential with tenant ID: ${tenantId}, clientId: ${clientId} and username: ${username}`,\n      );\n\n      logger.warning(\n        \"Environment is configured to use username and password authentication. This authentication method is deprecated, as it doesn't support multifactor authentication (MFA). Use a more secure credential. For more details, see https://aka.ms/azsdk/identity/mfa.\",\n      );\n      this._credential = new UsernamePasswordCredential(\n        tenantId,\n        clientId,\n        username,\n        password,\n        newOptions,\n      );\n    }\n  }\n\n  /**\n   * Authenticates with Microsoft Entra ID and returns an access token if successful.\n   *\n   * @param scopes - The list of scopes for which the token will have access.\n   * @param options - Optional parameters. See {@link GetTokenOptions}.\n   */\n  async getToken(scopes: string | string[], options: GetTokenOptions = {}): Promise<AccessToken> {\n    return tracingClient.withSpan(`${credentialName}.getToken`, options, async (newOptions) => {\n      if (this._credential) {\n        try {\n          const result = await this._credential.getToken(scopes, newOptions);\n          logger.getToken.info(formatSuccess(scopes));\n          return result;\n        } catch (err: any) {\n          const authenticationError = new AuthenticationError(400, {\n            error: `${credentialName} authentication failed. To troubleshoot, visit https://aka.ms/azsdk/js/identity/environmentcredential/troubleshoot.`,\n            error_description: err.message.toString().split(\"More details:\").join(\"\"),\n          });\n          logger.getToken.info(formatError(scopes, authenticationError));\n          throw authenticationError;\n        }\n      }\n      throw new CredentialUnavailableError(\n        `${credentialName} is unavailable. No underlying credential could be used. To troubleshoot, visit https://aka.ms/azsdk/js/identity/environmentcredential/troubleshoot.`,\n      );\n    });\n  }\n}\n"]}