wangzhibo
2026-05-09 53418655c061ac26f66058253f39200aced1ab1d
1
{"version":3,"file":"chainedTokenCredential.js","sourceRoot":"","sources":["../../../src/credentials/chainedTokenCredential.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EAAE,4BAA4B,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AACxF,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;GAEG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,gBAAgB,CAAC,wBAAwB,CAAC,CAAC;AAEjE;;;;GAIG;AACH,MAAM,OAAO,sBAAsB;IACzB,QAAQ,GAAsB,EAAE,CAAC;IAEzC;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,YAAY,GAAG,OAA0B;QACvC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC1B,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,QAAQ,CAAC,MAAyB,EAAE,UAA2B,EAAE;QACrE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC/D,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAC5B,MAAyB,EACzB,UAA2B,EAAE;QAE7B,IAAI,KAAK,GAAuB,IAAI,CAAC;QACrC,IAAI,oBAAqC,CAAC;QAC1C,MAAM,MAAM,GAAY,EAAE,CAAC;QAE3B,OAAO,aAAa,CAAC,QAAQ,CAC3B,iCAAiC,EACjC,OAAO,EACP,KAAK,EAAE,cAAc,EAAE,EAAE;YACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;gBAChE,IAAI,CAAC;oBACH,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;oBAChE,oBAAoB,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;gBAC1C,CAAC;gBAAC,OAAO,GAAQ,EAAE,CAAC;oBAClB,IACE,GAAG,CAAC,IAAI,KAAK,4BAA4B;wBACzC,GAAG,CAAC,IAAI,KAAK,6BAA6B,EAC1C,CAAC;wBACD,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;oBACnB,CAAC;yBAAM,CAAC;wBACN,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;wBAC/C,MAAM,GAAG,CAAC;oBACZ,CAAC;gBACH,CAAC;YACH,CAAC;YAED,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChC,MAAM,GAAG,GAAG,IAAI,4BAA4B,CAC1C,MAAM,EACN,+CAA+C,CAChD,CAAC;gBACF,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;gBAC/C,MAAM,GAAG,CAAC;YACZ,CAAC;YAED,MAAM,CAAC,QAAQ,CAAC,IAAI,CAClB,cAAc,oBAAoB,CAAC,WAAW,CAAC,IAAI,KAAK,aAAa,CAAC,MAAM,CAAC,EAAE,CAChF,CAAC;YAEF,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACnB,MAAM,IAAI,0BAA0B,CAAC,kCAAkC,CAAC,CAAC;YAC3E,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC;QACzC,CAAC,CACF,CAAC;IACJ,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport { AggregateAuthenticationError, CredentialUnavailableError } from \"../errors.js\";\nimport { credentialLogger, formatError, formatSuccess } from \"../util/logging.js\";\nimport { tracingClient } from \"../util/tracing.js\";\n\n/**\n * @internal\n */\nexport const logger = credentialLogger(\"ChainedTokenCredential\");\n\n/**\n * Enables multiple `TokenCredential` implementations to be tried in order until\n * one of the getToken methods returns an access token. For more information, see\n * [ChainedTokenCredential overview](https://aka.ms/azsdk/js/identity/credential-chains#use-chainedtokencredential-for-granularity).\n */\nexport class ChainedTokenCredential implements TokenCredential {\n  private _sources: TokenCredential[] = [];\n\n  /**\n   * Creates an instance of ChainedTokenCredential using the given credentials.\n   *\n   * @param sources - `TokenCredential` implementations to be tried in order.\n   *\n   * Example usage:\n   * ```ts snippet:chained_token_credential_example\n   * import { ClientSecretCredential, ChainedTokenCredential } from \"@azure/identity\";\n   *\n   * const tenantId = \"<tenant-id>\";\n   * const clientId = \"<client-id>\";\n   * const clientSecret = \"<client-secret>\";\n   * const anotherClientId = \"<another-client-id>\";\n   * const anotherSecret = \"<another-client-secret>\";\n   *\n   * const firstCredential = new ClientSecretCredential(tenantId, clientId, clientSecret);\n   * const secondCredential = new ClientSecretCredential(tenantId, anotherClientId, anotherSecret);\n   *\n   * const credentialChain = new ChainedTokenCredential(firstCredential, secondCredential);\n   * ```\n   */\n  constructor(...sources: TokenCredential[]) {\n    this._sources = sources;\n  }\n\n  /**\n   * Returns the first access token returned by one of the chained\n   * `TokenCredential` implementations.  Throws an {@link AggregateAuthenticationError}\n   * when one or more credentials throws an {@link AuthenticationError} and\n   * no credentials have returned an access token.\n   *\n   * This method is called automatically by Azure SDK client libraries. You may call this method\n   * directly, but you must also handle token caching and token refreshing.\n   *\n   * @param scopes - The list of scopes for which the token will have access.\n   * @param options - The options used to configure any requests this\n   *                `TokenCredential` implementation might make.\n   */\n  async getToken(scopes: string | string[], options: GetTokenOptions = {}): Promise<AccessToken> {\n    const { token } = await this.getTokenInternal(scopes, options);\n    return token;\n  }\n\n  private async getTokenInternal(\n    scopes: string | string[],\n    options: GetTokenOptions = {},\n  ): Promise<{ token: AccessToken; successfulCredential: TokenCredential }> {\n    let token: AccessToken | null = null;\n    let successfulCredential: TokenCredential;\n    const errors: Error[] = [];\n\n    return tracingClient.withSpan(\n      \"ChainedTokenCredential.getToken\",\n      options,\n      async (updatedOptions) => {\n        for (let i = 0; i < this._sources.length && token === null; i++) {\n          try {\n            token = await this._sources[i].getToken(scopes, updatedOptions);\n            successfulCredential = this._sources[i];\n          } catch (err: any) {\n            if (\n              err.name === \"CredentialUnavailableError\" ||\n              err.name === \"AuthenticationRequiredError\"\n            ) {\n              errors.push(err);\n            } else {\n              logger.getToken.info(formatError(scopes, err));\n              throw err;\n            }\n          }\n        }\n\n        if (!token && errors.length > 0) {\n          const err = new AggregateAuthenticationError(\n            errors,\n            \"ChainedTokenCredential authentication failed.\",\n          );\n          logger.getToken.info(formatError(scopes, err));\n          throw err;\n        }\n\n        logger.getToken.info(\n          `Result for ${successfulCredential.constructor.name}: ${formatSuccess(scopes)}`,\n        );\n\n        if (token === null) {\n          throw new CredentialUnavailableError(\"Failed to retrieve a valid token\");\n        }\n        return { token, successfulCredential };\n      },\n    );\n  }\n}\n"]}