@azure/identity 2.0.0-beta.6 → 2.0.2-alpha.20211028.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of @azure/identity might be problematic. Click here for more details.
- package/CHANGELOG.md +160 -12
- package/README.md +51 -3
- package/dist/index.js +307 -238
- package/dist/index.js.map +1 -1
- package/dist-esm/src/client/identityClient.js +2 -2
- package/dist-esm/src/client/identityClient.js.map +1 -1
- package/dist-esm/src/credentials/authorizationCodeCredential.browser.js +1 -1
- package/dist-esm/src/credentials/authorizationCodeCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/{applicationCredential.browser.js → azureApplicationCredential.browser.js} +9 -4
- package/dist-esm/src/credentials/azureApplicationCredential.browser.js.map +1 -0
- package/dist-esm/src/credentials/azureApplicationCredential.js +36 -0
- package/dist-esm/src/credentials/azureApplicationCredential.js.map +1 -0
- package/dist-esm/src/credentials/azureCliCredential.browser.js +7 -0
- package/dist-esm/src/credentials/azureCliCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/azureCliCredential.js +10 -10
- package/dist-esm/src/credentials/azureCliCredential.js.map +1 -1
- package/dist-esm/src/credentials/azurePowerShellCredential.browser.js +3 -1
- package/dist-esm/src/credentials/azurePowerShellCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/azurePowerShellCredential.js +13 -13
- package/dist-esm/src/credentials/azurePowerShellCredential.js.map +1 -1
- package/dist-esm/src/credentials/chainedTokenCredential.js +2 -2
- package/dist-esm/src/credentials/chainedTokenCredential.js.map +1 -1
- package/dist-esm/src/credentials/clientCertificateCredential.browser.js +7 -0
- package/dist-esm/src/credentials/clientCertificateCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/clientCertificateCredential.js +18 -15
- package/dist-esm/src/credentials/clientCertificateCredential.js.map +1 -1
- package/dist-esm/src/credentials/clientCertificateCredentialOptions.js.map +1 -1
- package/dist-esm/src/credentials/clientSecretCredential.browser.js +1 -1
- package/dist-esm/src/credentials/clientSecretCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/clientSecretCredential.js +1 -1
- package/dist-esm/src/credentials/clientSecretCredential.js.map +1 -1
- package/dist-esm/src/credentials/clientSecretCredentialOptions.js.map +1 -1
- package/dist-esm/src/credentials/defaultAzureCredential.js +16 -12
- package/dist-esm/src/credentials/defaultAzureCredential.js.map +1 -1
- package/dist-esm/src/credentials/deviceCodeCredential.browser.js +7 -0
- package/dist-esm/src/credentials/deviceCodeCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/deviceCodeCredential.js +14 -0
- package/dist-esm/src/credentials/deviceCodeCredential.js.map +1 -1
- package/dist-esm/src/credentials/environmentCredential.browser.js +7 -0
- package/dist-esm/src/credentials/environmentCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/environmentCredential.js +5 -21
- package/dist-esm/src/credentials/environmentCredential.js.map +1 -1
- package/dist-esm/src/credentials/interactiveBrowserCredential.browser.js +7 -7
- package/dist-esm/src/credentials/interactiveBrowserCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/interactiveBrowserCredential.js +7 -7
- package/dist-esm/src/credentials/interactiveBrowserCredential.js.map +1 -1
- package/dist-esm/src/credentials/interactiveBrowserCredentialOptions.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/arcMsi.js +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/arcMsi.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/fabricMsi.js +7 -2
- package/dist-esm/src/credentials/managedIdentityCredential/fabricMsi.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/imdsMsi.js +32 -23
- package/dist-esm/src/credentials/managedIdentityCredential/imdsMsi.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/index.js +4 -5
- package/dist-esm/src/credentials/managedIdentityCredential/index.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/utils.js +4 -1
- package/dist-esm/src/credentials/managedIdentityCredential/utils.js.map +1 -1
- package/dist-esm/src/credentials/onBehalfOfCredential.browser.js +6 -0
- package/dist-esm/src/credentials/onBehalfOfCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/onBehalfOfCredential.js +6 -11
- package/dist-esm/src/credentials/onBehalfOfCredential.js.map +1 -1
- package/dist-esm/src/credentials/onBehalfOfCredentialOptions.js.map +1 -1
- package/dist-esm/src/credentials/usernamePasswordCredential.browser.js +1 -1
- package/dist-esm/src/credentials/usernamePasswordCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/usernamePasswordCredential.js +1 -3
- package/dist-esm/src/credentials/usernamePasswordCredential.js.map +1 -1
- package/dist-esm/src/credentials/visualStudioCodeCredential.browser.js +6 -0
- package/dist-esm/src/credentials/visualStudioCodeCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/visualStudioCodeCredential.js +5 -7
- package/dist-esm/src/credentials/visualStudioCodeCredential.js.map +1 -1
- package/dist-esm/src/{client/errors.js → errors.js} +15 -0
- package/dist-esm/src/errors.js.map +1 -0
- package/dist-esm/src/index.js +1 -4
- package/dist-esm/src/index.js.map +1 -1
- package/dist-esm/src/msal/browserFlows/browserCommon.js +8 -7
- package/dist-esm/src/msal/browserFlows/browserCommon.js.map +1 -1
- package/dist-esm/src/msal/browserFlows/msalAuthCode.js +12 -4
- package/dist-esm/src/msal/browserFlows/msalAuthCode.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalAuthorizationCode.js +1 -1
- package/dist-esm/src/msal/nodeFlows/msalAuthorizationCode.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalClientCertificate.js +6 -5
- package/dist-esm/src/msal/nodeFlows/msalClientCertificate.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalOnBehalfOf.js +1 -1
- package/dist-esm/src/msal/nodeFlows/msalOnBehalfOf.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalOpenBrowser.js +1 -1
- package/dist-esm/src/msal/nodeFlows/msalOpenBrowser.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/nodeCommon.js +13 -7
- package/dist-esm/src/msal/nodeFlows/nodeCommon.js.map +1 -1
- package/dist-esm/src/msal/utils.js +7 -4
- package/dist-esm/src/msal/utils.js.map +1 -1
- package/dist-esm/src/util/tracing.js +1 -1
- package/dist-esm/src/util/tracing.js.map +1 -1
- package/dist-esm/src/util/validateMultiTenant.browser.js +22 -0
- package/dist-esm/src/util/validateMultiTenant.browser.js.map +1 -0
- package/dist-esm/src/util/validateMultiTenant.js +17 -12
- package/dist-esm/src/util/validateMultiTenant.js.map +1 -1
- package/package.json +10 -8
- package/types/identity.d.ts +133 -233
- package/dist-esm/src/client/errors.js.map +0 -1
- package/dist-esm/src/credentials/applicationCredential.browser.js.map +0 -1
- package/dist-esm/src/credentials/applicationCredential.js +0 -34
- package/dist-esm/src/credentials/applicationCredential.js.map +0 -1
- package/dist-esm/src/msal/errors.js +0 -22
- package/dist-esm/src/msal/errors.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactiveBrowserCredential.js","sourceRoot":"","sources":["../../../src/credentials/interactiveBrowserCredential.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAMlC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAExC,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAOpE,MAAM,MAAM,GAAG,gBAAgB,CAAC,8BAA8B,CAAC,CAAC;AAEhE
|
|
1
|
+
{"version":3,"file":"interactiveBrowserCredential.js","sourceRoot":"","sources":["../../../src/credentials/interactiveBrowserCredential.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAMlC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAExC,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAOpE,MAAM,MAAM,GAAG,gBAAgB,CAAC,8BAA8B,CAAC,CAAC;AAEhE;;;GAGG;AACH,MAAM,OAAO,4BAA4B;IAIvC;;;;;;;;;;;OAWG;IACH,YACE,UAEmD,EAAE;QAErD,MAAM,WAAW,GACf,OAAO,OAAO,CAAC,WAAW,KAAK,UAAU;YACvC,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE;YACvB,CAAC,CAAC,OAAO,CAAC,WAAW,IAAI,kBAAkB,CAAC;QAEhD,IAAI,CAAC,QAAQ,GAAG,IAAI,eAAe,iCAC9B,OAAO,KACV,sBAAsB,EAAE,OAAO,EAC/B,MAAM;YACN,WAAW,IACX,CAAC;QACH,IAAI,CAAC,8BAA8B,GAAG,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,8BAA8B,CAAC;IAChF,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,QAAQ,CAAC,MAAyB,EAAE,UAA2B,EAAE;QACrE,OAAO,KAAK,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;YAC9E,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC9D,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,kCACpC,UAAU,KACb,8BAA8B,EAAE,IAAI,CAAC,8BAA8B,IACnE,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,YAAY,CAChB,MAAyB,EACzB,UAA2B,EAAE;QAE7B,OAAO,KAAK,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,eAAe,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;YAClF,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC9D,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;YACtD,OAAO,IAAI,CAAC,QAAQ,CAAC,gBAAgB,EAAE,CAAC;QAC1C,CAAC,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/* eslint-disable @typescript-eslint/no-unused-vars */\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\n\nimport { credentialLogger } from \"../util/logging\";\nimport { trace } from \"../util/tracing\";\nimport { AuthenticationRecord } from \"../msal/types\";\nimport { MsalOpenBrowser } from \"../msal/nodeFlows/msalOpenBrowser\";\nimport { MsalFlow } from \"../msal/flows\";\nimport {\n InteractiveBrowserCredentialInBrowserOptions,\n InteractiveBrowserCredentialNodeOptions\n} from \"./interactiveBrowserCredentialOptions\";\n\nconst logger = credentialLogger(\"InteractiveBrowserCredential\");\n\n/**\n * Enables authentication to Azure Active Directory inside of the web browser\n * using the interactive login flow.\n */\nexport class InteractiveBrowserCredential implements TokenCredential {\n private msalFlow: MsalFlow;\n private disableAutomaticAuthentication?: boolean;\n\n /**\n * Creates an instance of InteractiveBrowserCredential with the details needed.\n *\n * This credential uses the [Authorization Code Flow](https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-auth-code-flow).\n * On Node.js, it will open a browser window while it listens for a redirect response from the authentication service.\n * On browsers, it authenticates via popups. The `loginStyle` optional parameter can be set to `redirect` to authenticate by redirecting the user to an Azure secure login page, which then will redirect the user back to the web application where the authentication started.\n *\n * For Node.js, if a `clientId` is provided, the Azure Active Directory application will need to be configured to have a \"Mobile and desktop applications\" redirect endpoint.\n * Follow our guide on [setting up Redirect URIs for Desktop apps that calls to web APIs](https://docs.microsoft.com/azure/active-directory/develop/scenario-desktop-app-registration#redirect-uris).\n *\n * @param options - Options for configuring the client which makes the authentication requests.\n */\n constructor(\n options:\n | InteractiveBrowserCredentialNodeOptions\n | InteractiveBrowserCredentialInBrowserOptions = {}\n ) {\n const redirectUri =\n typeof options.redirectUri === \"function\"\n ? options.redirectUri()\n : options.redirectUri || \"http://localhost\";\n\n this.msalFlow = new MsalOpenBrowser({\n ...options,\n tokenCredentialOptions: options,\n logger,\n redirectUri\n });\n this.disableAutomaticAuthentication = options?.disableAutomaticAuthentication;\n }\n\n /**\n * Authenticates with Azure Active Directory and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.\n *\n * If the user provided the option `disableAutomaticAuthentication`,\n * once the token can't be retrieved silently,\n * this method won't attempt to request user interaction to retrieve the token.\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 return trace(`${this.constructor.name}.getToken`, options, async (newOptions) => {\n const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];\n return this.msalFlow.getToken(arrayScopes, {\n ...newOptions,\n disableAutomaticAuthentication: this.disableAutomaticAuthentication\n });\n });\n }\n\n /**\n * Authenticates with Azure Active Directory and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.\n *\n * If the token can't be retrieved silently, this method will require user interaction to retrieve the token.\n *\n * On Node.js, this credential has [Proof Key for Code Exchange (PKCE)](https://datatracker.ietf.org/doc/html/rfc7636) enabled by default.\n * PKCE is a security feature that mitigates authentication code interception attacks.\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 authenticate(\n scopes: string | string[],\n options: GetTokenOptions = {}\n ): Promise<AuthenticationRecord | undefined> {\n return trace(`${this.constructor.name}.authenticate`, options, async (newOptions) => {\n const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];\n await this.msalFlow.getToken(arrayScopes, newOptions);\n return this.msalFlow.getActiveAccount();\n });\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactiveBrowserCredentialOptions.js","sourceRoot":"","sources":["../../../src/credentials/interactiveBrowserCredentialOptions.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { InteractiveCredentialOptions } from \"./interactiveCredentialOptions\";\nimport { CredentialPersistenceOptions } from \"./credentialPersistenceOptions\";\n\n/**\n * (Browser-only feature)\n * The \"login style\" to use in the authentication flow:\n * - \"redirect\" redirects the user to the authentication page and then\n * redirects them back to the page once authentication is completed.\n * - \"popup\" opens a new browser window through with the redirect flow\n * is initiated. The user's existing browser window does not leave\n * the current page\n */\nexport type BrowserLoginStyle = \"redirect\" | \"popup\";\n\n/**\n * Defines the common options for the InteractiveBrowserCredential class.\n */\nexport interface
|
|
1
|
+
{"version":3,"file":"interactiveBrowserCredentialOptions.js","sourceRoot":"","sources":["../../../src/credentials/interactiveBrowserCredentialOptions.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { InteractiveCredentialOptions } from \"./interactiveCredentialOptions\";\nimport { CredentialPersistenceOptions } from \"./credentialPersistenceOptions\";\n\n/**\n * (Browser-only feature)\n * The \"login style\" to use in the authentication flow:\n * - \"redirect\" redirects the user to the authentication page and then\n * redirects them back to the page once authentication is completed.\n * - \"popup\" opens a new browser window through with the redirect flow\n * is initiated. The user's existing browser window does not leave\n * the current page\n */\nexport type BrowserLoginStyle = \"redirect\" | \"popup\";\n\n/**\n * Defines the common options for the InteractiveBrowserCredential class.\n */\nexport interface InteractiveBrowserCredentialNodeOptions\n extends InteractiveCredentialOptions,\n CredentialPersistenceOptions {\n /**\n * Gets the redirect URI of the application. This should be same as the value\n * in the application registration portal. Defaults to `window.location.href`.\n */\n redirectUri?: string | (() => string);\n\n /**\n * The Azure Active Directory tenant (directory) ID.\n */\n tenantId?: string;\n\n /**\n * The client (application) ID of an App Registration in the tenant.\n */\n clientId?: string;\n\n /**\n * loginHint allows a user name to be pre-selected for interactive logins.\n * Setting this option skips the account selection prompt and immediately attempts to login with the specified account.\n */\n loginHint?: string;\n}\n\n/**\n * Defines the common options for the InteractiveBrowserCredential class.\n */\nexport interface InteractiveBrowserCredentialInBrowserOptions extends InteractiveCredentialOptions {\n /**\n * Gets the redirect URI of the application. This should be same as the value\n * in the application registration portal. Defaults to `window.location.href`.\n */\n redirectUri?: string | (() => string);\n\n /**\n * The Azure Active Directory tenant (directory) ID.\n */\n tenantId?: string;\n\n /**\n * The client (application) ID of an App Registration in the tenant.\n * This parameter is required on the browser.\n */\n clientId: string;\n\n /**\n * Specifies whether a redirect or a popup window should be used to\n * initiate the user authentication flow. Possible values are \"redirect\"\n * or \"popup\" (default) for browser and \"popup\" (default) for node.\n *\n */\n loginStyle?: BrowserLoginStyle;\n\n /**\n * loginHint allows a user name to be pre-selected for interactive logins.\n * Setting this option skips the account selection prompt and immediately attempts to login with the specified account.\n */\n loginHint?: string;\n}\n"]}
|
|
@@ -5,7 +5,7 @@ import { readFile } from "fs";
|
|
|
5
5
|
import { credentialLogger } from "../../util/logging";
|
|
6
6
|
import { mapScopesToResource, msiGenericGetToken } from "./utils";
|
|
7
7
|
import { azureArcAPIVersion } from "./constants";
|
|
8
|
-
import { AuthenticationError } from "../../
|
|
8
|
+
import { AuthenticationError } from "../../errors";
|
|
9
9
|
const msiName = "ManagedIdentityCredential - Azure Arc MSI";
|
|
10
10
|
const logger = credentialLogger(msiName);
|
|
11
11
|
// Azure Arc MSI doesn't have a special expiresIn parser.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"arcMsi.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/arcMsi.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EAEtB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAE9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"arcMsi.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/arcMsi.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport {\n createHttpHeaders,\n createPipelineRequest,\n PipelineRequestOptions\n} from \"@azure/core-rest-pipeline\";\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { readFile } from \"fs\";\nimport { MSI, MSIConfiguration } from \"./models\";\nimport { credentialLogger } from \"../../util/logging\";\nimport { IdentityClient } from \"../../client/identityClient\";\nimport { mapScopesToResource, msiGenericGetToken } from \"./utils\";\nimport { azureArcAPIVersion } from \"./constants\";\nimport { AuthenticationError } from \"../../errors\";\n\nconst msiName = \"ManagedIdentityCredential - Azure Arc MSI\";\nconst logger = credentialLogger(msiName);\n\n// Azure Arc MSI doesn't have a special expiresIn parser.\nconst expiresInParser = undefined;\n\nfunction prepareRequestOptions(scopes: string | string[]): PipelineRequestOptions {\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n throw new Error(`${msiName}: Multiple scopes are not supported.`);\n }\n const queryParameters: any = {\n resource,\n \"api-version\": azureArcAPIVersion\n };\n\n const query = new URLSearchParams(queryParameters);\n\n // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.\n if (!process.env.IDENTITY_ENDPOINT) {\n throw new Error(`${msiName}: Missing environment variable: IDENTITY_ENDPOINT`);\n }\n\n return createPipelineRequest({\n // Should be similar to: http://localhost:40342/metadata/identity/oauth2/token\n url: `${process.env.IDENTITY_ENDPOINT}?${query.toString()}`,\n method: \"GET\",\n headers: createHttpHeaders({\n Accept: \"application/json\",\n Metadata: \"true\"\n })\n });\n}\n\n// Since \"fs\"'s readFileSync locks the thread, and to avoid extra dependencies.\nfunction readFileAsync(path: string, options: { encoding: string }): Promise<string> {\n return new Promise((resolve, reject) =>\n readFile(path, options, (err, data) => {\n if (err) {\n reject(err);\n }\n resolve(data);\n })\n );\n}\n\nasync function filePathRequest(\n identityClient: IdentityClient,\n requestPrepareOptions: PipelineRequestOptions\n): Promise<string | undefined> {\n const response = await identityClient.sendRequest(createPipelineRequest(requestPrepareOptions));\n\n if (response.status !== 401) {\n let message = \"\";\n if (response.bodyAsText) {\n message = ` Response: ${response.bodyAsText}`;\n }\n throw new AuthenticationError(\n response.status,\n `${msiName}: To authenticate with Azure Arc MSI, status code 401 is expected on the first request. ${message}`\n );\n }\n\n const authHeader = response.headers.get(\"www-authenticate\") || \"\";\n try {\n return authHeader.split(\"=\").slice(1)[0];\n } catch (e) {\n throw Error(`Invalid www-authenticate header format: ${authHeader}`);\n }\n}\n\nexport const arcMsi: MSI = {\n async isAvailable(scopes): Promise<boolean> {\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n logger.info(`${msiName}: Unavailable. Multiple scopes are not supported.`);\n return false;\n }\n const result = Boolean(process.env.IMDS_ENDPOINT && process.env.IDENTITY_ENDPOINT);\n if (!result) {\n logger.info(\n `${msiName}: The environment variables needed are: IMDS_ENDPOINT and IDENTITY_ENDPOINT`\n );\n }\n return result;\n },\n async getToken(\n configuration: MSIConfiguration,\n getTokenOptions: GetTokenOptions = {}\n ): Promise<AccessToken | null> {\n const { identityClient, scopes, clientId } = configuration;\n\n logger.info(`${msiName}: Authenticating.`);\n\n if (clientId) {\n throw new Error(\n `${msiName}: User assigned identity is not supported by the Azure Arc Managed Identity Endpoint. To authenticate with the system assigned identity, omit the client id when constructing the ManagedIdentityCredential, or if authenticating with the DefaultAzureCredential ensure the AZURE_CLIENT_ID environment variable is not set.`\n );\n }\n\n const requestOptions = {\n disableJsonStringifyOnBody: true,\n deserializationMapper: undefined,\n abortSignal: getTokenOptions.abortSignal,\n ...prepareRequestOptions(scopes),\n allowInsecureConnection: true\n };\n\n const filePath = await filePathRequest(identityClient, requestOptions);\n\n if (!filePath) {\n throw new Error(`${msiName}: Failed to find the token file.`);\n }\n\n const key = await readFileAsync(filePath, { encoding: \"utf-8\" });\n requestOptions.headers?.set(\"Authorization\", `Basic ${key}`);\n\n return msiGenericGetToken(identityClient, requestOptions, expiresInParser, getTokenOptions);\n }\n};\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT license.
|
|
3
|
+
import https from "https";
|
|
3
4
|
import { createHttpHeaders } from "@azure/core-rest-pipeline";
|
|
4
5
|
import { credentialLogger } from "../../util/logging";
|
|
5
6
|
import { mapScopesToResource, msiGenericGetToken } from "./utils";
|
|
@@ -64,7 +65,7 @@ export const fabricMsi = {
|
|
|
64
65
|
return result;
|
|
65
66
|
},
|
|
66
67
|
async getToken(configuration, getTokenOptions = {}) {
|
|
67
|
-
const {
|
|
68
|
+
const { scopes, identityClient, clientId } = configuration;
|
|
68
69
|
logger.info([
|
|
69
70
|
`${msiName}:`,
|
|
70
71
|
"Using the endpoint and the secret coming from the environment variables:",
|
|
@@ -72,7 +73,11 @@ export const fabricMsi = {
|
|
|
72
73
|
"IDENTITY_HEADER=[REDACTED] and",
|
|
73
74
|
"IDENTITY_SERVER_THUMBPRINT=[REDACTED]."
|
|
74
75
|
].join(" "));
|
|
75
|
-
return msiGenericGetToken(identityClient, prepareRequestOptions(scopes, clientId), expiresInParser, getTokenOptions
|
|
76
|
+
return msiGenericGetToken(identityClient, prepareRequestOptions(scopes, clientId), expiresInParser, getTokenOptions, new https.Agent({
|
|
77
|
+
// This is necessary because Service Fabric provides a self-signed certificate.
|
|
78
|
+
// The alternative path is to verify the certificate using the IDENTITY_SERVER_THUMBPRINT env variable.
|
|
79
|
+
rejectUnauthorized: false
|
|
80
|
+
}));
|
|
76
81
|
}
|
|
77
82
|
};
|
|
78
83
|
//# sourceMappingURL=fabricMsi.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fabricMsi.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/fabricMsi.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC,OAAO,EAAE,iBAAiB,EAA0B,MAAM,2BAA2B,CAAC;AAGtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,OAAO,GAAG,wCAAwC,CAAC;AACzD,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;AAEzC,SAAS,eAAe,CAAC,WAAgB;IACvC,gFAAgF;IAChF,OAAO,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,qBAAqB,CAC5B,MAAyB,EACzB,QAAiB;IAEjB,MAAM,QAAQ,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,CAAC,QAAQ,EAAE;QACb,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,sCAAsC,CAAC,CAAC;KACnE;IAED,MAAM,eAAe,GAAQ;QAC3B,QAAQ;QACR,aAAa,EAAE,kBAAkB;KAClC,CAAC;IAEF,IAAI,QAAQ,EAAE;QACZ,eAAe,CAAC,SAAS,GAAG,QAAQ,CAAC;KACtC;IAED,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,eAAe,CAAC,CAAC;IAEnD,wIAAwI;IACxI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE;QAClC,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;KACpE;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE;QAChC,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;KAClE;IAED,OAAO;QACL,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,KAAK,CAAC,QAAQ,EAAE,EAAE;QAC3D,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,iBAAiB,CAAC;YACzB,MAAM,EAAE,kBAAkB;YAC1B,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe;SACpC,CAAC;KACH,CAAC;AACJ,CAAC;AAED,6GAA6G;AAC7G,EAAE;AACF,iBAAiB;AACjB,2CAA2C;AAC3C,4BAA4B;AAC5B,EAAE;AACF,kCAAkC;AAClC,EAAE;AACF,wIAAwI;AACxI,EAAE;AAEF,MAAM,CAAC,MAAM,SAAS,GAAQ;IAC5B,KAAK,CAAC,WAAW,CAAC,MAAM;QACtB,MAAM,QAAQ,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;QAC7C,IAAI,CAAC,QAAQ,EAAE;YACb,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,mDAAmD,CAAC,CAAC;YAC3E,OAAO,KAAK,CAAC;SACd;QACD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACxB,MAAM,MAAM,GAAG,OAAO,CACpB,GAAG,CAAC,iBAAiB,IAAI,GAAG,CAAC,eAAe,IAAI,GAAG,CAAC,0BAA0B,CAC/E,CAAC;QACF,IAAI,CAAC,MAAM,EAAE;YACX,MAAM,CAAC,IAAI,CACT,GAAG,OAAO,wHAAwH,CACnI,CAAC;SACH;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,KAAK,CAAC,QAAQ,CACZ,aAA+B,EAC/B,kBAAmC,EAAE;QAErC,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"fabricMsi.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/fabricMsi.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport https from \"https\";\nimport { createHttpHeaders, PipelineRequestOptions } from \"@azure/core-rest-pipeline\";\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { MSI, MSIConfiguration } from \"./models\";\nimport { credentialLogger } from \"../../util/logging\";\nimport { mapScopesToResource, msiGenericGetToken } from \"./utils\";\nimport { azureFabricVersion } from \"./constants\";\n\nconst msiName = \"ManagedIdentityCredential - Fabric MSI\";\nconst logger = credentialLogger(msiName);\n\nfunction expiresInParser(requestBody: any): number {\n // Parses a string representation of the seconds since epoch into a number value\n return Number(requestBody.expires_on);\n}\n\nfunction prepareRequestOptions(\n scopes: string | string[],\n clientId?: string\n): PipelineRequestOptions {\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n throw new Error(`${msiName}: Multiple scopes are not supported.`);\n }\n\n const queryParameters: any = {\n resource,\n \"api-version\": azureFabricVersion\n };\n\n if (clientId) {\n queryParameters.client_id = clientId;\n }\n\n const query = new URLSearchParams(queryParameters);\n\n // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.\n if (!process.env.IDENTITY_ENDPOINT) {\n throw new Error(\"Missing environment variable: IDENTITY_ENDPOINT\");\n }\n if (!process.env.IDENTITY_HEADER) {\n throw new Error(\"Missing environment variable: IDENTITY_HEADER\");\n }\n\n return {\n url: `${process.env.IDENTITY_ENDPOINT}?${query.toString()}`,\n method: \"GET\",\n headers: createHttpHeaders({\n Accept: \"application/json\",\n Secret: process.env.IDENTITY_HEADER\n })\n };\n}\n\n// This credential can be easily tested by deploying a container to Azure Service Fabric with the Dockerfile:\n//\n// FROM node:12\n// RUN wget https://host.any/path/bash.sh\n// CMD [\"bash\", \"bash.sh\"]\n//\n// Where the bash script contains:\n//\n// curl --insecure $IDENTITY_ENDPOINT'?api-version=2019-07-01-preview&resource=https://vault.azure.net/' -H \"Secret: $IDENTITY_HEADER\"\n//\n\nexport const fabricMsi: MSI = {\n async isAvailable(scopes): Promise<boolean> {\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n logger.info(`${msiName}: Unavailable. Multiple scopes are not supported.`);\n return false;\n }\n const env = process.env;\n const result = Boolean(\n env.IDENTITY_ENDPOINT && env.IDENTITY_HEADER && env.IDENTITY_SERVER_THUMBPRINT\n );\n if (!result) {\n logger.info(\n `${msiName}: Unavailable. The environment variables needed are: IDENTITY_ENDPOINT, IDENTITY_HEADER and IDENTITY_SERVER_THUMBPRINT`\n );\n }\n return result;\n },\n async getToken(\n configuration: MSIConfiguration,\n getTokenOptions: GetTokenOptions = {}\n ): Promise<AccessToken | null> {\n const { scopes, identityClient, clientId } = configuration;\n\n logger.info(\n [\n `${msiName}:`,\n \"Using the endpoint and the secret coming from the environment variables:\",\n `IDENTITY_ENDPOINT=${process.env.IDENTITY_ENDPOINT},`,\n \"IDENTITY_HEADER=[REDACTED] and\",\n \"IDENTITY_SERVER_THUMBPRINT=[REDACTED].\"\n ].join(\" \")\n );\n\n return msiGenericGetToken(\n identityClient,\n prepareRequestOptions(scopes, clientId),\n expiresInParser,\n getTokenOptions,\n new https.Agent({\n // This is necessary because Service Fabric provides a self-signed certificate.\n // The alternative path is to verify the certificate using the IDENTITY_SERVER_THUMBPRINT env variable.\n rejectUnauthorized: false\n })\n );\n }\n};\n"]}
|
|
@@ -7,14 +7,14 @@ import { credentialLogger } from "../../util/logging";
|
|
|
7
7
|
import { createSpan } from "../../util/tracing";
|
|
8
8
|
import { imdsApiVersion, imdsEndpointPath, imdsHost } from "./constants";
|
|
9
9
|
import { mapScopesToResource, msiGenericGetToken } from "./utils";
|
|
10
|
-
import { AuthenticationError } from "../../
|
|
10
|
+
import { AuthenticationError } from "../../errors";
|
|
11
11
|
const msiName = "ManagedIdentityCredential - IMDS";
|
|
12
12
|
const logger = credentialLogger(msiName);
|
|
13
13
|
function expiresInParser(requestBody) {
|
|
14
14
|
if (requestBody.expires_on) {
|
|
15
15
|
// Use the expires_on timestamp if it's available
|
|
16
16
|
const expires = +requestBody.expires_on * 1000;
|
|
17
|
-
logger.info(`${msiName}:
|
|
17
|
+
logger.info(`${msiName}: Using expires_on: ${expires} (original value: ${requestBody.expires_on})`);
|
|
18
18
|
return expires;
|
|
19
19
|
}
|
|
20
20
|
else {
|
|
@@ -24,29 +24,41 @@ function expiresInParser(requestBody) {
|
|
|
24
24
|
return expires;
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
-
function prepareRequestOptions(scopes, clientId) {
|
|
27
|
+
function prepareRequestOptions(scopes, clientId, options) {
|
|
28
28
|
var _a;
|
|
29
29
|
const resource = mapScopesToResource(scopes);
|
|
30
30
|
if (!resource) {
|
|
31
31
|
throw new Error(`${msiName}: Multiple scopes are not supported.`);
|
|
32
32
|
}
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (
|
|
38
|
-
queryParameters
|
|
33
|
+
const { skipQuery, skipMetadataHeader } = options || {};
|
|
34
|
+
let query = "";
|
|
35
|
+
// Pod Identity will try to process this request even if the Metadata header is missing.
|
|
36
|
+
// We can exclude the request query to ensure no IMDS endpoint tries to process the ping request.
|
|
37
|
+
if (!skipQuery) {
|
|
38
|
+
const queryParameters = {
|
|
39
|
+
resource,
|
|
40
|
+
"api-version": imdsApiVersion
|
|
41
|
+
};
|
|
42
|
+
if (clientId) {
|
|
43
|
+
queryParameters.client_id = clientId;
|
|
44
|
+
}
|
|
45
|
+
const params = new URLSearchParams(queryParameters);
|
|
46
|
+
query = `?${params.toString()}`;
|
|
39
47
|
}
|
|
40
|
-
const params = new URLSearchParams(queryParameters);
|
|
41
|
-
const query = params.toString();
|
|
42
48
|
const url = new URL(imdsEndpointPath, (_a = process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) !== null && _a !== void 0 ? _a : imdsHost);
|
|
49
|
+
const rawHeaders = {
|
|
50
|
+
Accept: "application/json",
|
|
51
|
+
Metadata: "true"
|
|
52
|
+
};
|
|
53
|
+
// Remove the Metadata header to invoke a request error from some IMDS endpoints.
|
|
54
|
+
if (skipMetadataHeader) {
|
|
55
|
+
delete rawHeaders.Metadata;
|
|
56
|
+
}
|
|
43
57
|
return {
|
|
44
|
-
|
|
58
|
+
// In this case, the `?` should be added in the "query" variable `skipQuery` is not set.
|
|
59
|
+
url: `${url}${query}`,
|
|
45
60
|
method: "GET",
|
|
46
|
-
headers: createHttpHeaders(
|
|
47
|
-
Accept: "application/json",
|
|
48
|
-
Metadata: "true"
|
|
49
|
-
})
|
|
61
|
+
headers: createHttpHeaders(rawHeaders)
|
|
50
62
|
};
|
|
51
63
|
}
|
|
52
64
|
// 800ms -> 1600ms -> 3200ms
|
|
@@ -68,13 +80,10 @@ export const imdsMsi = {
|
|
|
68
80
|
if (process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) {
|
|
69
81
|
return true;
|
|
70
82
|
}
|
|
71
|
-
const requestOptions = prepareRequestOptions(resource, clientId
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
// IMDS endpoint
|
|
76
|
-
requestOptions.headers.delete("Metadata");
|
|
77
|
-
}
|
|
83
|
+
const requestOptions = prepareRequestOptions(resource, clientId, {
|
|
84
|
+
skipMetadataHeader: true,
|
|
85
|
+
skipQuery: true
|
|
86
|
+
});
|
|
78
87
|
requestOptions.tracingOptions = options.tracingOptions;
|
|
79
88
|
try {
|
|
80
89
|
// Create a request with a timeout since we expect that
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"imdsMsi.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/imdsMsi.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { delay } from \"@azure/core-util\";\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport {\n createHttpHeaders,\n PipelineRequestOptions,\n createPipelineRequest,\n RestError\n} from \"@azure/core-rest-pipeline\";\nimport { SpanStatusCode } from \"@azure/core-tracing\";\nimport { IdentityClient } from \"../../client/identityClient\";\nimport { credentialLogger } from \"../../util/logging\";\nimport { createSpan } from \"../../util/tracing\";\nimport { imdsApiVersion, imdsEndpointPath, imdsHost } from \"./constants\";\nimport { MSI, MSIConfiguration } from \"./models\";\nimport { mapScopesToResource, msiGenericGetToken } from \"./utils\";\nimport { AuthenticationError } from \"../../client/errors\";\n\nconst msiName = \"ManagedIdentityCredential - IMDS\";\nconst logger = credentialLogger(msiName);\n\nfunction expiresInParser(requestBody: any): number {\n if (requestBody.expires_on) {\n // Use the expires_on timestamp if it's available\n const expires = +requestBody.expires_on * 1000;\n logger.info(\n `${msiName}: IMDS using expires_on: ${expires} (original value: ${requestBody.expires_on})`\n );\n return expires;\n } else {\n // If these aren't possible, use expires_in and calculate a timestamp\n const expires = Date.now() + requestBody.expires_in * 1000;\n logger.info(\n `${msiName}: IMDS using expires_in: ${expires} (original value: ${requestBody.expires_in})`\n );\n return expires;\n }\n}\n\nfunction prepareRequestOptions(\n scopes: string | string[],\n clientId?: string\n): PipelineRequestOptions {\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n throw new Error(`${msiName}: Multiple scopes are not supported.`);\n }\n\n const queryParameters: any = {\n resource,\n \"api-version\": imdsApiVersion\n };\n\n if (clientId) {\n queryParameters.client_id = clientId;\n }\n\n const params = new URLSearchParams(queryParameters);\n const query = params.toString();\n const url = new URL(imdsEndpointPath, process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST ?? imdsHost);\n\n return {\n url: `${url}?${query}`,\n method: \"GET\",\n headers: createHttpHeaders({\n Accept: \"application/json\",\n Metadata: \"true\"\n })\n };\n}\n\n// 800ms -> 1600ms -> 3200ms\nexport const imdsMsiRetryConfig = {\n maxRetries: 3,\n startDelayInMs: 800,\n intervalIncrement: 2\n};\n\nexport const imdsMsi: MSI = {\n async isAvailable(\n scopes: string | string[],\n identityClient: IdentityClient,\n clientId?: string,\n getTokenOptions?: GetTokenOptions\n ): Promise<boolean> {\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n logger.info(`${msiName}: Unavailable. Multiple scopes are not supported.`);\n return false;\n }\n const { span, updatedOptions: options } = createSpan(\n \"ManagedIdentityCredential-pingImdsEndpoint\",\n getTokenOptions\n );\n\n // if the PodIdenityEndpoint environment variable was set no need to probe the endpoint, it can be assumed to exist\n if (process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) {\n return true;\n }\n\n const requestOptions = prepareRequestOptions(resource, clientId);\n\n // This will always be populated, but let's make TypeScript happy\n if (requestOptions.headers) {\n // Remove the Metadata header to invoke a request error from\n // IMDS endpoint\n requestOptions.headers.delete(\"Metadata\");\n }\n\n requestOptions.tracingOptions = options.tracingOptions;\n\n try {\n // Create a request with a timeout since we expect that\n // not having a \"Metadata\" header should cause an error to be\n // returned quickly from the endpoint, proving its availability.\n const request = createPipelineRequest(requestOptions);\n\n request.timeout = options.requestOptions?.timeout ?? 300;\n\n // This MSI uses the imdsEndpoint to get the token, which only uses http://\n request.allowInsecureConnection = true;\n\n try {\n logger.info(`${msiName}: Pinging the Azure IMDS endpoint`);\n await identityClient.sendRequest(request);\n } catch (err) {\n if (\n (err.name === \"RestError\" && err.code === RestError.REQUEST_SEND_ERROR) ||\n err.name === \"AbortError\" ||\n err.code === \"ENETUNREACH\" || // Network unreachable\n err.code === \"ECONNREFUSED\" || // connection refused\n err.code === \"EHOSTDOWN\" // host is down\n ) {\n // If the request failed, or Node.js was unable to establish a connection,\n // or the host was down, we'll assume the IMDS endpoint isn't available.\n logger.info(`${msiName}: The Azure IMDS endpoint is unavailable`);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n return false;\n }\n }\n\n // If we received any response, the endpoint is available\n logger.info(`${msiName}: The Azure IMDS endpoint is available`);\n return true;\n } catch (err) {\n // createWebResource failed.\n // This error should bubble up to the user.\n logger.info(\n `${msiName}: Error when creating the WebResource for the Azure IMDS endpoint: ${err.message}`\n );\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n throw err;\n } finally {\n span.end();\n }\n },\n async getToken(\n configuration: MSIConfiguration,\n getTokenOptions: GetTokenOptions = {}\n ): Promise<AccessToken | null> {\n const { identityClient, scopes, clientId } = configuration;\n\n logger.info(\n `${msiName}: Using the Azure IMDS endpoint coming from the environment variable MSI_ENDPOINT=${process.env.MSI_ENDPOINT}, and using the cloud shell to proceed with the authentication.`\n );\n\n let nextDelayInMs = imdsMsiRetryConfig.startDelayInMs;\n for (let retries = 0; retries < imdsMsiRetryConfig.maxRetries; retries++) {\n try {\n return await msiGenericGetToken(\n identityClient,\n prepareRequestOptions(scopes, clientId),\n expiresInParser,\n getTokenOptions\n );\n } catch (error) {\n if (error.statusCode === 404) {\n await delay(nextDelayInMs);\n nextDelayInMs *= imdsMsiRetryConfig.intervalIncrement;\n continue;\n }\n throw error;\n }\n }\n\n throw new AuthenticationError(\n 404,\n `${msiName}: Failed to retrieve IMDS token after ${imdsMsiRetryConfig.maxRetries} retries.`\n );\n }\n};\n"]}
|
|
1
|
+
{"version":3,"file":"imdsMsi.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/imdsMsi.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { delay } from \"@azure/core-util\";\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport {\n createHttpHeaders,\n PipelineRequestOptions,\n createPipelineRequest,\n RestError\n} from \"@azure/core-rest-pipeline\";\nimport { SpanStatusCode } from \"@azure/core-tracing\";\nimport { IdentityClient } from \"../../client/identityClient\";\nimport { credentialLogger } from \"../../util/logging\";\nimport { createSpan } from \"../../util/tracing\";\nimport { imdsApiVersion, imdsEndpointPath, imdsHost } from \"./constants\";\nimport { MSI, MSIConfiguration } from \"./models\";\nimport { mapScopesToResource, msiGenericGetToken } from \"./utils\";\nimport { AuthenticationError } from \"../../errors\";\n\nconst msiName = \"ManagedIdentityCredential - IMDS\";\nconst logger = credentialLogger(msiName);\n\nfunction expiresInParser(requestBody: any): number {\n if (requestBody.expires_on) {\n // Use the expires_on timestamp if it's available\n const expires = +requestBody.expires_on * 1000;\n logger.info(\n `${msiName}: Using expires_on: ${expires} (original value: ${requestBody.expires_on})`\n );\n return expires;\n } else {\n // If these aren't possible, use expires_in and calculate a timestamp\n const expires = Date.now() + requestBody.expires_in * 1000;\n logger.info(\n `${msiName}: IMDS using expires_in: ${expires} (original value: ${requestBody.expires_in})`\n );\n return expires;\n }\n}\n\nfunction prepareRequestOptions(\n scopes: string | string[],\n clientId?: string,\n options?: {\n skipQuery?: boolean;\n skipMetadataHeader?: boolean;\n }\n): PipelineRequestOptions {\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n throw new Error(`${msiName}: Multiple scopes are not supported.`);\n }\n\n const { skipQuery, skipMetadataHeader } = options || {};\n let query = \"\";\n\n // Pod Identity will try to process this request even if the Metadata header is missing.\n // We can exclude the request query to ensure no IMDS endpoint tries to process the ping request.\n if (!skipQuery) {\n const queryParameters: any = {\n resource,\n \"api-version\": imdsApiVersion\n };\n if (clientId) {\n queryParameters.client_id = clientId;\n }\n const params = new URLSearchParams(queryParameters);\n query = `?${params.toString()}`;\n }\n\n const url = new URL(imdsEndpointPath, process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST ?? imdsHost);\n\n const rawHeaders: Record<string, string> = {\n Accept: \"application/json\",\n Metadata: \"true\"\n };\n\n // Remove the Metadata header to invoke a request error from some IMDS endpoints.\n if (skipMetadataHeader) {\n delete rawHeaders.Metadata;\n }\n\n return {\n // In this case, the `?` should be added in the \"query\" variable `skipQuery` is not set.\n url: `${url}${query}`,\n method: \"GET\",\n headers: createHttpHeaders(rawHeaders)\n };\n}\n\n// 800ms -> 1600ms -> 3200ms\nexport const imdsMsiRetryConfig = {\n maxRetries: 3,\n startDelayInMs: 800,\n intervalIncrement: 2\n};\n\nexport const imdsMsi: MSI = {\n async isAvailable(\n scopes: string | string[],\n identityClient: IdentityClient,\n clientId?: string,\n getTokenOptions?: GetTokenOptions\n ): Promise<boolean> {\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n logger.info(`${msiName}: Unavailable. Multiple scopes are not supported.`);\n return false;\n }\n const { span, updatedOptions: options } = createSpan(\n \"ManagedIdentityCredential-pingImdsEndpoint\",\n getTokenOptions\n );\n\n // if the PodIdenityEndpoint environment variable was set no need to probe the endpoint, it can be assumed to exist\n if (process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) {\n return true;\n }\n\n const requestOptions = prepareRequestOptions(resource, clientId, {\n skipMetadataHeader: true,\n skipQuery: true\n });\n requestOptions.tracingOptions = options.tracingOptions;\n\n try {\n // Create a request with a timeout since we expect that\n // not having a \"Metadata\" header should cause an error to be\n // returned quickly from the endpoint, proving its availability.\n const request = createPipelineRequest(requestOptions);\n\n request.timeout = options.requestOptions?.timeout ?? 300;\n\n // This MSI uses the imdsEndpoint to get the token, which only uses http://\n request.allowInsecureConnection = true;\n\n try {\n logger.info(`${msiName}: Pinging the Azure IMDS endpoint`);\n await identityClient.sendRequest(request);\n } catch (err) {\n if (\n (err.name === \"RestError\" && err.code === RestError.REQUEST_SEND_ERROR) ||\n err.name === \"AbortError\" ||\n err.code === \"ENETUNREACH\" || // Network unreachable\n err.code === \"ECONNREFUSED\" || // connection refused\n err.code === \"EHOSTDOWN\" // host is down\n ) {\n // If the request failed, or Node.js was unable to establish a connection,\n // or the host was down, we'll assume the IMDS endpoint isn't available.\n logger.info(`${msiName}: The Azure IMDS endpoint is unavailable`);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n return false;\n }\n }\n\n // If we received any response, the endpoint is available\n logger.info(`${msiName}: The Azure IMDS endpoint is available`);\n return true;\n } catch (err) {\n // createWebResource failed.\n // This error should bubble up to the user.\n logger.info(\n `${msiName}: Error when creating the WebResource for the Azure IMDS endpoint: ${err.message}`\n );\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n throw err;\n } finally {\n span.end();\n }\n },\n async getToken(\n configuration: MSIConfiguration,\n getTokenOptions: GetTokenOptions = {}\n ): Promise<AccessToken | null> {\n const { identityClient, scopes, clientId } = configuration;\n\n logger.info(\n `${msiName}: Using the Azure IMDS endpoint coming from the environment variable MSI_ENDPOINT=${process.env.MSI_ENDPOINT}, and using the cloud shell to proceed with the authentication.`\n );\n\n let nextDelayInMs = imdsMsiRetryConfig.startDelayInMs;\n for (let retries = 0; retries < imdsMsiRetryConfig.maxRetries; retries++) {\n try {\n return await msiGenericGetToken(\n identityClient,\n prepareRequestOptions(scopes, clientId),\n expiresInParser,\n getTokenOptions\n );\n } catch (error) {\n if (error.statusCode === 404) {\n await delay(nextDelayInMs);\n nextDelayInMs *= imdsMsiRetryConfig.intervalIncrement;\n continue;\n }\n throw error;\n }\n }\n\n throw new AuthenticationError(\n 404,\n `${msiName}: Failed to retrieve IMDS token after ${imdsMsiRetryConfig.maxRetries} retries.`\n );\n }\n};\n"]}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Licensed under the MIT license.
|
|
3
3
|
import { SpanStatusCode } from "@azure/core-tracing";
|
|
4
4
|
import { IdentityClient } from "../../client/identityClient";
|
|
5
|
-
import { AuthenticationError, CredentialUnavailableError } from "../../
|
|
5
|
+
import { AuthenticationError, CredentialUnavailableError } from "../../errors";
|
|
6
6
|
import { credentialLogger, formatSuccess, formatError } from "../../util/logging";
|
|
7
7
|
import { appServiceMsi2017 } from "./appServiceMsi2017";
|
|
8
8
|
import { createSpan } from "../../util/tracing";
|
|
@@ -10,6 +10,7 @@ import { cloudShellMsi } from "./cloudShellMsi";
|
|
|
10
10
|
import { imdsMsi } from "./imdsMsi";
|
|
11
11
|
import { arcMsi } from "./arcMsi";
|
|
12
12
|
import { tokenExchangeMsi } from "./tokenExchangeMsi";
|
|
13
|
+
import { fabricMsi } from "./fabricMsi";
|
|
13
14
|
const logger = credentialLogger("ManagedIdentityCredential");
|
|
14
15
|
/**
|
|
15
16
|
* Attempts authentication using a managed identity that has been assigned
|
|
@@ -41,9 +42,7 @@ export class ManagedIdentityCredential {
|
|
|
41
42
|
if (this.cachedMSI) {
|
|
42
43
|
return this.cachedMSI;
|
|
43
44
|
}
|
|
44
|
-
|
|
45
|
-
// which is necessary since Service Fabric only provides self-signed certificates on their Identity Endpoint.
|
|
46
|
-
const MSIs = [appServiceMsi2017, cloudShellMsi, arcMsi, tokenExchangeMsi(), imdsMsi];
|
|
45
|
+
const MSIs = [fabricMsi, appServiceMsi2017, cloudShellMsi, arcMsi, tokenExchangeMsi(), imdsMsi];
|
|
47
46
|
for (const msi of MSIs) {
|
|
48
47
|
if (await msi.isAvailable(scopes, this.identityClient, clientId, getTokenOptions)) {
|
|
49
48
|
this.cachedMSI = msi;
|
|
@@ -85,7 +84,7 @@ export class ManagedIdentityCredential {
|
|
|
85
84
|
*/
|
|
86
85
|
async getToken(scopes, options) {
|
|
87
86
|
let result = null;
|
|
88
|
-
const { span, updatedOptions } = createSpan("ManagedIdentityCredential
|
|
87
|
+
const { span, updatedOptions } = createSpan("ManagedIdentityCredential.getToken", options);
|
|
89
88
|
try {
|
|
90
89
|
// isEndpointAvailable can be true, false, or null,
|
|
91
90
|
// If it's null, it means we don't yet know whether
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/index.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { SpanStatusCode } from \"@azure/core-tracing\";\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\n\nimport { IdentityClient, TokenCredentialOptions } from \"../../client/identityClient\";\nimport { AuthenticationError, CredentialUnavailableError } from \"../../client/errors\";\nimport { credentialLogger, formatSuccess, formatError } from \"../../util/logging\";\nimport { appServiceMsi2017 } from \"./appServiceMsi2017\";\nimport { createSpan } from \"../../util/tracing\";\nimport { cloudShellMsi } from \"./cloudShellMsi\";\nimport { imdsMsi } from \"./imdsMsi\";\nimport { MSI } from \"./models\";\nimport { arcMsi } from \"./arcMsi\";\nimport { tokenExchangeMsi } from \"./tokenExchangeMsi\";\n\nconst logger = credentialLogger(\"ManagedIdentityCredential\");\n\n/**\n * Attempts authentication using a managed identity that has been assigned\n * to the deployment environment. This authentication type works in Azure VMs,\n * App Service and Azure Functions applications, and inside of Azure Cloud Shell.\n *\n * More information about configuring managed identities can be found here:\n *\n * https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview\n */\nexport class ManagedIdentityCredential implements TokenCredential {\n private identityClient: IdentityClient;\n private clientId: string | undefined;\n private isEndpointUnavailable: boolean | null = null;\n\n /**\n * Creates an instance of ManagedIdentityCredential with the client ID of a\n * user-assigned identity, or app registration (when working with AKS pod-identity).\n *\n * @param clientId - The client ID of the user-assigned identity, or app registration (when working with AKS pod-identity).\n * @param options - Options for configuring the client which makes the access token request.\n */\n constructor(clientId: string, options?: TokenCredentialOptions);\n /**\n * Creates an instance of ManagedIdentityCredential\n *\n * @param options - Options for configuring the client which makes the access token request.\n */\n constructor(options?: TokenCredentialOptions);\n /**\n * @internal\n * @hidden\n */\n constructor(\n clientIdOrOptions: string | TokenCredentialOptions | undefined,\n options?: TokenCredentialOptions\n ) {\n if (typeof clientIdOrOptions === \"string\") {\n // clientId, options constructor\n this.clientId = clientIdOrOptions;\n this.identityClient = new IdentityClient(options);\n } else {\n // options only constructor\n this.identityClient = new IdentityClient(clientIdOrOptions);\n }\n }\n\n private cachedMSI: MSI | undefined;\n\n private async cachedAvailableMSI(\n scopes: string | string[],\n clientId?: string,\n getTokenOptions?: GetTokenOptions\n ): Promise<MSI> {\n if (this.cachedMSI) {\n return this.cachedMSI;\n }\n\n // \"fabricMsi\" can't be added yet because our HTTPs pipeline doesn't allow skipping the SSL verification step,\n // which is necessary since Service Fabric only provides self-signed certificates on their Identity Endpoint.\n const MSIs = [appServiceMsi2017, cloudShellMsi, arcMsi, tokenExchangeMsi(), imdsMsi];\n\n for (const msi of MSIs) {\n if (await msi.isAvailable(scopes, this.identityClient, clientId, getTokenOptions)) {\n this.cachedMSI = msi;\n return msi;\n }\n }\n\n throw new CredentialUnavailableError(\"ManagedIdentityCredential - No MSI credential available\");\n }\n\n private async authenticateManagedIdentity(\n scopes: string | string[],\n clientId?: string,\n getTokenOptions?: GetTokenOptions\n ): Promise<AccessToken | null> {\n const { span, updatedOptions } = createSpan(\n \"ManagedIdentityCredential-authenticateManagedIdentity\",\n getTokenOptions\n );\n\n try {\n // Determining the available MSI, and avoiding checking for other MSIs while the program is running.\n const availableMSI = await this.cachedAvailableMSI(scopes, clientId, updatedOptions);\n\n return availableMSI.getToken(\n {\n identityClient: this.identityClient,\n scopes,\n clientId\n },\n updatedOptions\n );\n } catch (err) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n throw err;\n } finally {\n span.end();\n }\n }\n\n /**\n * Authenticates with Azure Active Directory and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.\n * If an unexpected error occurs, an {@link AuthenticationError} will be thrown with the details of the failure.\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 public async getToken(\n scopes: string | string[],\n options?: GetTokenOptions\n ): Promise<AccessToken> {\n let result: AccessToken | null = null;\n\n const { span, updatedOptions } = createSpan(\"ManagedIdentityCredential-getToken\", options);\n\n try {\n // isEndpointAvailable can be true, false, or null,\n // If it's null, it means we don't yet know whether\n // the endpoint is available and need to check for it.\n if (this.isEndpointUnavailable !== true) {\n result = await this.authenticateManagedIdentity(scopes, this.clientId, updatedOptions);\n\n if (result === null) {\n // If authenticateManagedIdentity returns null,\n // it means no MSI endpoints are available.\n // If so, we avoid trying to reach to them in future requests.\n this.isEndpointUnavailable = true;\n\n // It also means that the endpoint answered with either 200 or 201 (see the sendTokenRequest method),\n // yet we had no access token. For this reason, we'll throw once with a specific message:\n const error = new CredentialUnavailableError(\n \"The managed identity endpoint was reached, yet no tokens were received.\"\n );\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n\n // Since `authenticateManagedIdentity` didn't throw, and the result was not null,\n // We will assume that this endpoint is reachable from this point forward,\n // and avoid pinging again to it.\n this.isEndpointUnavailable = false;\n } else {\n // We've previously determined that the endpoint was unavailable,\n // either because it was unreachable or permanently unable to authenticate.\n const error = new CredentialUnavailableError(\n \"The managed identity endpoint is not currently available\"\n );\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n\n logger.getToken.info(formatSuccess(scopes));\n return result;\n } catch (err) {\n // CredentialUnavailable errors are expected to reach here.\n // We intend them to bubble up, so that DefaultAzureCredential can catch them.\n if (err.name === \"AuthenticationRequiredError\") {\n throw err;\n }\n\n // Expected errors to reach this point:\n // - Errors coming from a method unexpectedly breaking.\n // - When identityClient.sendTokenRequest throws, in which case\n // if the status code was 400, it means that the endpoint is working,\n // but no identity is available.\n\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n\n // If either the network is unreachable,\n // we can safely assume the credential is unavailable.\n if (err.code === \"ENETUNREACH\") {\n const error = new CredentialUnavailableError(\n `ManagedIdentityCredential is unavailable. Network unreachable. Message: ${err.message}`\n );\n\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n\n // If either the host was unreachable,\n // we can safely assume the credential is unavailable.\n if (err.code === \"EHOSTUNREACH\") {\n const error = new CredentialUnavailableError(\n `ManagedIdentityCredential is unavailable. No managed identity endpoint found. Message: ${err.message}`\n );\n\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n\n // If err.statusCode has a value of 400, it comes from sendTokenRequest,\n // and it means that the endpoint is working, but that no identity is available.\n if (err.statusCode === 400) {\n throw new CredentialUnavailableError(\n `ManagedIdentityCredential: The managed identity endpoint is indicating there's no available identity. Message: ${err.message}`\n );\n }\n\n // If the error has no status code, we can assume there was no available identity.\n // This will throw silently during any ChainedTokenCredential.\n if (err.statusCode === undefined) {\n throw new CredentialUnavailableError(\n `ManagedIdentityCredential authentication failed. Message ${err.message}`\n );\n }\n\n // Any other error should break the chain.\n throw new AuthenticationError(err.statusCode, {\n error: \"ManagedIdentityCredential authentication failed.\",\n error_description: err.message\n });\n } finally {\n // Finally is always called, both if we return and if we throw in the above try/catch.\n span.end();\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/index.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { SpanStatusCode } from \"@azure/core-tracing\";\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\n\nimport { IdentityClient, TokenCredentialOptions } from \"../../client/identityClient\";\nimport { AuthenticationError, CredentialUnavailableError } from \"../../errors\";\nimport { credentialLogger, formatSuccess, formatError } from \"../../util/logging\";\nimport { appServiceMsi2017 } from \"./appServiceMsi2017\";\nimport { createSpan } from \"../../util/tracing\";\nimport { cloudShellMsi } from \"./cloudShellMsi\";\nimport { imdsMsi } from \"./imdsMsi\";\nimport { MSI } from \"./models\";\nimport { arcMsi } from \"./arcMsi\";\nimport { tokenExchangeMsi } from \"./tokenExchangeMsi\";\nimport { fabricMsi } from \"./fabricMsi\";\n\nconst logger = credentialLogger(\"ManagedIdentityCredential\");\n\n/**\n * Attempts authentication using a managed identity that has been assigned\n * to the deployment environment. This authentication type works in Azure VMs,\n * App Service and Azure Functions applications, and inside of Azure Cloud Shell.\n *\n * More information about configuring managed identities can be found here:\n *\n * https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview\n */\nexport class ManagedIdentityCredential implements TokenCredential {\n private identityClient: IdentityClient;\n private clientId: string | undefined;\n private isEndpointUnavailable: boolean | null = null;\n\n /**\n * Creates an instance of ManagedIdentityCredential with the client ID of a\n * user-assigned identity, or app registration (when working with AKS pod-identity).\n *\n * @param clientId - The client ID of the user-assigned identity, or app registration (when working with AKS pod-identity).\n * @param options - Options for configuring the client which makes the access token request.\n */\n constructor(clientId: string, options?: TokenCredentialOptions);\n /**\n * Creates an instance of ManagedIdentityCredential\n *\n * @param options - Options for configuring the client which makes the access token request.\n */\n constructor(options?: TokenCredentialOptions);\n /**\n * @internal\n * @hidden\n */\n constructor(\n clientIdOrOptions: string | TokenCredentialOptions | undefined,\n options?: TokenCredentialOptions\n ) {\n if (typeof clientIdOrOptions === \"string\") {\n // clientId, options constructor\n this.clientId = clientIdOrOptions;\n this.identityClient = new IdentityClient(options);\n } else {\n // options only constructor\n this.identityClient = new IdentityClient(clientIdOrOptions);\n }\n }\n\n private cachedMSI: MSI | undefined;\n\n private async cachedAvailableMSI(\n scopes: string | string[],\n clientId?: string,\n getTokenOptions?: GetTokenOptions\n ): Promise<MSI> {\n if (this.cachedMSI) {\n return this.cachedMSI;\n }\n\n const MSIs = [fabricMsi, appServiceMsi2017, cloudShellMsi, arcMsi, tokenExchangeMsi(), imdsMsi];\n\n for (const msi of MSIs) {\n if (await msi.isAvailable(scopes, this.identityClient, clientId, getTokenOptions)) {\n this.cachedMSI = msi;\n return msi;\n }\n }\n\n throw new CredentialUnavailableError(\"ManagedIdentityCredential - No MSI credential available\");\n }\n\n private async authenticateManagedIdentity(\n scopes: string | string[],\n clientId?: string,\n getTokenOptions?: GetTokenOptions\n ): Promise<AccessToken | null> {\n const { span, updatedOptions } = createSpan(\n \"ManagedIdentityCredential-authenticateManagedIdentity\",\n getTokenOptions\n );\n\n try {\n // Determining the available MSI, and avoiding checking for other MSIs while the program is running.\n const availableMSI = await this.cachedAvailableMSI(scopes, clientId, updatedOptions);\n\n return availableMSI.getToken(\n {\n identityClient: this.identityClient,\n scopes,\n clientId\n },\n updatedOptions\n );\n } catch (err) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n throw err;\n } finally {\n span.end();\n }\n }\n\n /**\n * Authenticates with Azure Active Directory and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.\n * If an unexpected error occurs, an {@link AuthenticationError} will be thrown with the details of the failure.\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 public async getToken(\n scopes: string | string[],\n options?: GetTokenOptions\n ): Promise<AccessToken> {\n let result: AccessToken | null = null;\n\n const { span, updatedOptions } = createSpan(\"ManagedIdentityCredential.getToken\", options);\n\n try {\n // isEndpointAvailable can be true, false, or null,\n // If it's null, it means we don't yet know whether\n // the endpoint is available and need to check for it.\n if (this.isEndpointUnavailable !== true) {\n result = await this.authenticateManagedIdentity(scopes, this.clientId, updatedOptions);\n\n if (result === null) {\n // If authenticateManagedIdentity returns null,\n // it means no MSI endpoints are available.\n // If so, we avoid trying to reach to them in future requests.\n this.isEndpointUnavailable = true;\n\n // It also means that the endpoint answered with either 200 or 201 (see the sendTokenRequest method),\n // yet we had no access token. For this reason, we'll throw once with a specific message:\n const error = new CredentialUnavailableError(\n \"The managed identity endpoint was reached, yet no tokens were received.\"\n );\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n\n // Since `authenticateManagedIdentity` didn't throw, and the result was not null,\n // We will assume that this endpoint is reachable from this point forward,\n // and avoid pinging again to it.\n this.isEndpointUnavailable = false;\n } else {\n // We've previously determined that the endpoint was unavailable,\n // either because it was unreachable or permanently unable to authenticate.\n const error = new CredentialUnavailableError(\n \"The managed identity endpoint is not currently available\"\n );\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n\n logger.getToken.info(formatSuccess(scopes));\n return result;\n } catch (err) {\n // CredentialUnavailable errors are expected to reach here.\n // We intend them to bubble up, so that DefaultAzureCredential can catch them.\n if (err.name === \"AuthenticationRequiredError\") {\n throw err;\n }\n\n // Expected errors to reach this point:\n // - Errors coming from a method unexpectedly breaking.\n // - When identityClient.sendTokenRequest throws, in which case\n // if the status code was 400, it means that the endpoint is working,\n // but no identity is available.\n\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n\n // If either the network is unreachable,\n // we can safely assume the credential is unavailable.\n if (err.code === \"ENETUNREACH\") {\n const error = new CredentialUnavailableError(\n `ManagedIdentityCredential is unavailable. Network unreachable. Message: ${err.message}`\n );\n\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n\n // If either the host was unreachable,\n // we can safely assume the credential is unavailable.\n if (err.code === \"EHOSTUNREACH\") {\n const error = new CredentialUnavailableError(\n `ManagedIdentityCredential is unavailable. No managed identity endpoint found. Message: ${err.message}`\n );\n\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n\n // If err.statusCode has a value of 400, it comes from sendTokenRequest,\n // and it means that the endpoint is working, but that no identity is available.\n if (err.statusCode === 400) {\n throw new CredentialUnavailableError(\n `ManagedIdentityCredential: The managed identity endpoint is indicating there's no available identity. Message: ${err.message}`\n );\n }\n\n // If the error has no status code, we can assume there was no available identity.\n // This will throw silently during any ChainedTokenCredential.\n if (err.statusCode === undefined) {\n throw new CredentialUnavailableError(\n `ManagedIdentityCredential authentication failed. Message ${err.message}`\n );\n }\n\n // Any other error should break the chain.\n throw new AuthenticationError(err.statusCode, {\n error: \"ManagedIdentityCredential authentication failed.\",\n error_description: err.message\n });\n } finally {\n // Finally is always called, both if we return and if we throw in the above try/catch.\n span.end();\n }\n }\n}\n"]}
|
|
@@ -26,8 +26,11 @@ export function mapScopesToResource(scopes) {
|
|
|
26
26
|
}
|
|
27
27
|
return scope.substr(0, scope.lastIndexOf(DefaultScopeSuffix));
|
|
28
28
|
}
|
|
29
|
-
export async function msiGenericGetToken(identityClient, requestOptions, expiresInParser, getTokenOptions = {}) {
|
|
29
|
+
export async function msiGenericGetToken(identityClient, requestOptions, expiresInParser, getTokenOptions = {}, agent) {
|
|
30
30
|
const request = createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, requestOptions), { allowInsecureConnection: true }));
|
|
31
|
+
if (agent) {
|
|
32
|
+
request.agent = agent;
|
|
33
|
+
}
|
|
31
34
|
const tokenResponse = await identityClient.sendTokenRequest(request, expiresInParser);
|
|
32
35
|
return (tokenResponse && tokenResponse.accessToken) || null;
|
|
33
36
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/utils.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EAA0B,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/utils.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EAA0B,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAG1F,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGjD;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAyB;IAC3D,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;QACzB,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;YACvB,OAAO;SACR;QAED,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;KACnB;SAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;QACrC,KAAK,GAAG,MAAM,CAAC;KAChB;IAED,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE;QACvC,OAAO,KAAK,CAAC;KACd;IAED,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,cAA8B,EAC9B,cAAsC,EACtC,eAA+C,EAC/C,kBAAmC,EAAE,EACrC,KAAa;IAEb,MAAM,OAAO,GAAG,qBAAqB,+BACnC,WAAW,EAAE,eAAe,CAAC,WAAW,IACrC,cAAc,KACjB,uBAAuB,EAAE,IAAI,IAC7B,CAAC;IAEH,IAAI,KAAK,EAAE;QACT,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;KACvB;IAED,MAAM,aAAa,GAAG,MAAM,cAAc,CAAC,gBAAgB,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IACtF,OAAO,CAAC,aAAa,IAAI,aAAa,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC;AAC9D,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { PipelineRequestOptions, createPipelineRequest } from \"@azure/core-rest-pipeline\";\nimport { Agent } from \"http\";\nimport { IdentityClient } from \"../../client/identityClient\";\nimport { DefaultScopeSuffix } from \"./constants\";\nimport { MSIExpiresInParser } from \"./models\";\n\n/**\n * Most MSIs send requests to the IMDS endpoint, or a similar endpoint. These are GET requests that require sending a `resource` parameter on the query.\n * This resource can be derived from the scopes received through the getToken call, as long as only one scope is received.\n * Multiple scopes assume that the resulting token will have access to multiple resources, which won't be the case.\n *\n * For that reason, when we encounter multiple scopes, we return undefined.\n * It's up to the individual MSI implementations to throw the errors (which helps us provide less generic errors).\n */\nexport function mapScopesToResource(scopes: string | string[]): string | undefined {\n let scope = \"\";\n if (Array.isArray(scopes)) {\n if (scopes.length !== 1) {\n return;\n }\n\n scope = scopes[0];\n } else if (typeof scopes === \"string\") {\n scope = scopes;\n }\n\n if (!scope.endsWith(DefaultScopeSuffix)) {\n return scope;\n }\n\n return scope.substr(0, scope.lastIndexOf(DefaultScopeSuffix));\n}\n\nexport async function msiGenericGetToken(\n identityClient: IdentityClient,\n requestOptions: PipelineRequestOptions,\n expiresInParser: MSIExpiresInParser | undefined,\n getTokenOptions: GetTokenOptions = {},\n agent?: Agent\n): Promise<AccessToken | null> {\n const request = createPipelineRequest({\n abortSignal: getTokenOptions.abortSignal,\n ...requestOptions,\n allowInsecureConnection: true\n });\n\n if (agent) {\n request.agent = agent;\n }\n\n const tokenResponse = await identityClient.sendTokenRequest(request, expiresInParser);\n return (tokenResponse && tokenResponse.accessToken) || null;\n}\n"]}
|
|
@@ -4,7 +4,13 @@ import { credentialLogger, formatError } from "../util/logging";
|
|
|
4
4
|
const credentialName = "OnBehalfOfCredential";
|
|
5
5
|
const BrowserNotSupportedError = new Error(`${credentialName}: Not supported in the browser.`);
|
|
6
6
|
const logger = credentialLogger(credentialName);
|
|
7
|
+
/**
|
|
8
|
+
* Enables authentication to Azure Active Directory using the [On Behalf Of flow](https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow).
|
|
9
|
+
*/
|
|
7
10
|
export class OnBehalfOfCredential {
|
|
11
|
+
/**
|
|
12
|
+
* Only available in Node.js
|
|
13
|
+
*/
|
|
8
14
|
constructor() {
|
|
9
15
|
logger.info(formatError("", BrowserNotSupportedError));
|
|
10
16
|
throw BrowserNotSupportedError;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onBehalfOfCredential.browser.js","sourceRoot":"","sources":["../../../src/credentials/onBehalfOfCredential.browser.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEhE,MAAM,cAAc,GAAG,sBAAsB,CAAC;AAC9C,MAAM,wBAAwB,GAAG,IAAI,KAAK,CAAC,GAAG,cAAc,iCAAiC,CAAC,CAAC;AAC/F,MAAM,MAAM,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC;AAEhD,MAAM,OAAO,oBAAoB;IAC/B;QACE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC;QACvD,MAAM,wBAAwB,CAAC;IACjC,CAAC;IAEM,QAAQ;QACb,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC;QAChE,MAAM,wBAAwB,CAAC;IACjC,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { TokenCredential, AccessToken } from \"@azure/core-auth\";\nimport { credentialLogger, formatError } from \"../util/logging\";\n\nconst credentialName = \"OnBehalfOfCredential\";\nconst BrowserNotSupportedError = new Error(`${credentialName}: Not supported in the browser.`);\nconst logger = credentialLogger(credentialName);\n\nexport class OnBehalfOfCredential implements TokenCredential {\n constructor() {\n logger.info(formatError(\"\", BrowserNotSupportedError));\n throw BrowserNotSupportedError;\n }\n\n public getToken(): Promise<AccessToken | null> {\n logger.getToken.info(formatError(\"\", BrowserNotSupportedError));\n throw BrowserNotSupportedError;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"onBehalfOfCredential.browser.js","sourceRoot":"","sources":["../../../src/credentials/onBehalfOfCredential.browser.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEhE,MAAM,cAAc,GAAG,sBAAsB,CAAC;AAC9C,MAAM,wBAAwB,GAAG,IAAI,KAAK,CAAC,GAAG,cAAc,iCAAiC,CAAC,CAAC;AAC/F,MAAM,MAAM,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC;AAEhD;;GAEG;AACH,MAAM,OAAO,oBAAoB;IAC/B;;OAEG;IACH;QACE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC;QACvD,MAAM,wBAAwB,CAAC;IACjC,CAAC;IAEM,QAAQ;QACb,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC;QAChE,MAAM,wBAAwB,CAAC;IACjC,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { TokenCredential, AccessToken } from \"@azure/core-auth\";\nimport { credentialLogger, formatError } from \"../util/logging\";\n\nconst credentialName = \"OnBehalfOfCredential\";\nconst BrowserNotSupportedError = new Error(`${credentialName}: Not supported in the browser.`);\nconst logger = credentialLogger(credentialName);\n\n/**\n * Enables authentication to Azure Active Directory using the [On Behalf Of flow](https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow).\n */\nexport class OnBehalfOfCredential implements TokenCredential {\n /**\n * Only available in Node.js\n */\n constructor() {\n logger.info(formatError(\"\", BrowserNotSupportedError));\n throw BrowserNotSupportedError;\n }\n\n public getToken(): Promise<AccessToken | null> {\n logger.getToken.info(formatError(\"\", BrowserNotSupportedError));\n throw BrowserNotSupportedError;\n }\n}\n"]}
|
|
@@ -28,22 +28,17 @@ export class OnBehalfOfCredential {
|
|
|
28
28
|
* await client.getKey("key-name");
|
|
29
29
|
* ```
|
|
30
30
|
*
|
|
31
|
-
* @param configuration - Configuration specific to this credential.
|
|
32
31
|
* @param options - Optional parameters, generally common across credentials.
|
|
33
32
|
*/
|
|
34
|
-
constructor(
|
|
35
|
-
this.configuration = configuration;
|
|
33
|
+
constructor(options) {
|
|
36
34
|
this.options = options;
|
|
37
|
-
const {
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
if (!tenantId ||
|
|
41
|
-
!clientId ||
|
|
42
|
-
!(secretConfiguration.clientSecret || certificateConfiguration.certificatePath) ||
|
|
43
|
-
!userAssertionToken) {
|
|
35
|
+
const { clientSecret } = options;
|
|
36
|
+
const { certificatePath } = options;
|
|
37
|
+
const { tenantId, clientId, userAssertionToken } = options;
|
|
38
|
+
if (!tenantId || !clientId || !(clientSecret || certificatePath) || !userAssertionToken) {
|
|
44
39
|
throw new Error(`${credentialName}: tenantId, clientId, clientSecret (or certificatePath) and userAssertionToken are required parameters.`);
|
|
45
40
|
}
|
|
46
|
-
this.msalFlow = new MsalOnBehalfOf(Object.assign(Object.assign(
|
|
41
|
+
this.msalFlow = new MsalOnBehalfOf(Object.assign(Object.assign({}, this.options), { logger, tokenCredentialOptions: this.options }));
|
|
47
42
|
}
|
|
48
43
|
/**
|
|
49
44
|
* Authenticates with Azure Active Directory and returns an access token if successful.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onBehalfOfCredential.js","sourceRoot":"","sources":["../../../src/credentials/onBehalfOfCredential.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAIlC,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"onBehalfOfCredential.js","sourceRoot":"","sources":["../../../src/credentials/onBehalfOfCredential.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAIlC,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAQxC,MAAM,cAAc,GAAG,sBAAsB,CAAC;AAC9C,MAAM,MAAM,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC;AAEhD;;GAEG;AACH,MAAM,OAAO,oBAAoB;IAG/B;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,YAAoB,OAAoC;QAApC,YAAO,GAAP,OAAO,CAA6B;QACtD,MAAM,EAAE,YAAY,EAAE,GAAG,OAA4C,CAAC;QACtE,MAAM,EAAE,eAAe,EAAE,GAAG,OAAiD,CAAC;QAC9E,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAC;QAC3D,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,YAAY,IAAI,eAAe,CAAC,IAAI,CAAC,kBAAkB,EAAE;YACvF,MAAM,IAAI,KAAK,CACb,GAAG,cAAc,yGAAyG,CAC3H,CAAC;SACH;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,cAAc,iCAC7B,IAAI,CAAC,OAAO,KACf,MAAM,EACN,sBAAsB,EAAE,IAAI,CAAC,OAAO,IACpC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,QAAQ,CAAC,MAAyB,EAAE,UAA2B,EAAE;QACrE,OAAO,KAAK,CAAC,GAAG,cAAc,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;YACvE,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC9D,OAAO,IAAI,CAAC,QAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\n\nimport { MsalOnBehalfOf } from \"../msal/nodeFlows/msalOnBehalfOf\";\nimport { credentialLogger } from \"../util/logging\";\nimport { trace } from \"../util/tracing\";\nimport { MsalFlow } from \"../msal/flows\";\nimport {\n OnBehalfOfCredentialCertificateOptions,\n OnBehalfOfCredentialOptions,\n OnBehalfOfCredentialSecretOptions\n} from \"./onBehalfOfCredentialOptions\";\n\nconst credentialName = \"OnBehalfOfCredential\";\nconst logger = credentialLogger(credentialName);\n\n/**\n * Enables authentication to Azure Active Directory using the [On Behalf Of flow](https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow).\n */\nexport class OnBehalfOfCredential implements TokenCredential {\n private msalFlow: MsalFlow;\n\n /**\n * Creates an instance of the {@link OnBehalfOfCredential} with the details\n * needed to authenticate against Azure Active Directory with a client\n * secret or a path to a PEM certificate, and an user assertion.\n *\n * Example using the `KeyClient` from [\\@azure/keyvault-keys](https://www.npmjs.com/package/\\@azure/keyvault-keys):\n *\n * ```ts\n * const tokenCredential = new OnBehalfOfCredential({\n * tenantId,\n * clientId,\n * clientSecret, // or `certificatePath: \"/path/to/certificate.pem\"\n * userAssertionToken: \"access-token\"\n * });\n * const client = new KeyClient(\"vault-url\", tokenCredential);\n *\n * await client.getKey(\"key-name\");\n * ```\n *\n * @param options - Optional parameters, generally common across credentials.\n */\n constructor(private options: OnBehalfOfCredentialOptions) {\n const { clientSecret } = options as OnBehalfOfCredentialSecretOptions;\n const { certificatePath } = options as OnBehalfOfCredentialCertificateOptions;\n const { tenantId, clientId, userAssertionToken } = options;\n if (!tenantId || !clientId || !(clientSecret || certificatePath) || !userAssertionToken) {\n throw new Error(\n `${credentialName}: tenantId, clientId, clientSecret (or certificatePath) and userAssertionToken are required parameters.`\n );\n }\n this.msalFlow = new MsalOnBehalfOf({\n ...this.options,\n logger,\n tokenCredentialOptions: this.options\n });\n }\n\n /**\n * Authenticates with Azure Active Directory and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure the underlying network requests.\n */\n async getToken(scopes: string | string[], options: GetTokenOptions = {}): Promise<AccessToken> {\n return trace(`${credentialName}.getToken`, options, async (newOptions) => {\n const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];\n return this.msalFlow!.getToken(arrayScopes, newOptions);\n });\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onBehalfOfCredentialOptions.js","sourceRoot":"","sources":["../../../src/credentials/onBehalfOfCredentialOptions.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { TokenCredentialOptions } from \"../client/identityClient\";\nimport { CredentialPersistenceOptions } from \"./credentialPersistenceOptions\";\n\n/**\n *
|
|
1
|
+
{"version":3,"file":"onBehalfOfCredentialOptions.js","sourceRoot":"","sources":["../../../src/credentials/onBehalfOfCredentialOptions.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { TokenCredentialOptions } from \"../client/identityClient\";\nimport { CredentialPersistenceOptions } from \"./credentialPersistenceOptions\";\n\n/**\n * Defines the parameters to authenticate the {@link OnBehalfOfCredential} with a secret.\n */\nexport interface OnBehalfOfCredentialSecretOptions {\n /**\n * The Azure Active Directory tenant (directory) ID.\n */\n tenantId: string;\n /**\n * The client (application) ID of an App Registration in the tenant.\n */\n clientId: string;\n /**\n * A client secret that was generated for the App Registration.\n */\n clientSecret: string;\n /**\n * The user assertion for the On-Behalf-Of flow.\n */\n userAssertionToken: string;\n /**\n * The path to a PEM-encoded certificate should not be provided when the secret options are provided.\n */\n certificatePath?: never;\n /**\n * Option to include x5c header should not be provided when the secret options are provided.\n */\n sendCertificateChain?: never;\n}\n\n/**\n * Defines the parameters to authenticate the {@link OnBehalfOfCredential} with a certificate.\n */\nexport interface OnBehalfOfCredentialCertificateOptions {\n /**\n * The Azure Active Directory tenant (directory) ID.\n */\n tenantId: string;\n /**\n * The client (application) ID of an App Registration in the tenant.\n */\n clientId: string;\n /**\n * The path to a PEM-encoded public/private key certificate on the filesystem.\n */\n certificatePath: string;\n /**\n * Option to include x5c header for SubjectName and Issuer name authorization.\n * Set this option to send base64 encoded public certificate in the client assertion header as an x5c claim\n */\n sendCertificateChain?: boolean;\n /**\n * The user assertion for the On-Behalf-Of flow.\n */\n userAssertionToken: string;\n /**\n * Client secret should not be provided when certificate options are provided.\n */\n clientSecret?: never;\n}\n\n/**\n * Optional parameters for the {@link OnBehalfOfCredential} class.\n */\nexport type OnBehalfOfCredentialOptions = (\n | OnBehalfOfCredentialSecretOptions\n | OnBehalfOfCredentialCertificateOptions\n) &\n TokenCredentialOptions &\n CredentialPersistenceOptions;\n"]}
|
|
@@ -45,7 +45,7 @@ export class UsernamePasswordCredential {
|
|
|
45
45
|
* TokenCredential implementation might make.
|
|
46
46
|
*/
|
|
47
47
|
async getToken(scopes, options) {
|
|
48
|
-
const { span, updatedOptions: newOptions } = createSpan("UsernamePasswordCredential
|
|
48
|
+
const { span, updatedOptions: newOptions } = createSpan("UsernamePasswordCredential.getToken", options);
|
|
49
49
|
try {
|
|
50
50
|
const urlSuffix = getIdentityTokenEndpointSuffix(this.tenantId);
|
|
51
51
|
const params = new URLSearchParams({
|