@azure/identity 4.5.0-beta.1 → 4.5.0-beta.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.
- package/README.md +22 -1
- package/dist/index.js +238 -112
- package/dist/index.js.map +1 -1
- package/dist-esm/src/client/identityClient.js +1 -2
- package/dist-esm/src/client/identityClient.js.map +1 -1
- package/dist-esm/src/constants.js +1 -1
- package/dist-esm/src/constants.js.map +1 -1
- package/dist-esm/src/credentials/azurePipelinesCredential.js +50 -26
- package/dist-esm/src/credentials/azurePipelinesCredential.js.map +1 -1
- package/dist-esm/src/credentials/azurePowerShellCredential.js +63 -19
- package/dist-esm/src/credentials/azurePowerShellCredential.js.map +1 -1
- package/dist-esm/src/credentials/clientAssertionCredential.js +9 -2
- package/dist-esm/src/credentials/clientAssertionCredential.js.map +1 -1
- package/dist-esm/src/credentials/clientCertificateCredential.js +35 -27
- package/dist-esm/src/credentials/clientCertificateCredential.js.map +1 -1
- package/dist-esm/src/credentials/clientSecretCredential.js +9 -2
- package/dist-esm/src/credentials/clientSecretCredential.js.map +1 -1
- package/dist-esm/src/credentials/deviceCodeCredential.js +1 -1
- package/dist-esm/src/credentials/deviceCodeCredential.js.map +1 -1
- package/dist-esm/src/credentials/deviceCodeCredentialOptions.js.map +1 -1
- package/dist-esm/src/credentials/environmentCredential.js +11 -1
- package/dist-esm/src/credentials/environmentCredential.js.map +1 -1
- package/dist-esm/src/credentials/interactiveBrowserCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/interactiveBrowserCredential.js +1 -1
- 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/msalMsiProvider.js +6 -5
- package/dist-esm/src/credentials/managedIdentityCredential/msalMsiProvider.js.map +1 -1
- package/dist-esm/src/credentials/onBehalfOfCredential.js +16 -9
- package/dist-esm/src/credentials/onBehalfOfCredential.js.map +1 -1
- package/dist-esm/src/credentials/usernamePasswordCredential.js +13 -3
- package/dist-esm/src/credentials/usernamePasswordCredential.js.map +1 -1
- package/dist-esm/src/credentials/workloadIdentityCredential.js +16 -6
- package/dist-esm/src/credentials/workloadIdentityCredential.js.map +1 -1
- package/dist-esm/src/errors.js +12 -7
- package/dist-esm/src/errors.js.map +1 -1
- package/dist-esm/src/msal/browserFlows/flows.js.map +1 -0
- package/dist-esm/src/msal/browserFlows/msalBrowserCommon.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalClient.js +8 -1
- package/dist-esm/src/msal/nodeFlows/msalClient.js.map +1 -1
- package/package.json +3 -3
- package/types/identity.d.ts +26 -8
- package/dist-esm/src/msal/flows.js.map +0 -1
- package/dist-esm/src/msal/nodeFlows/msalAuthorizationCode.js +0 -47
- package/dist-esm/src/msal/nodeFlows/msalAuthorizationCode.js.map +0 -1
- package/dist-esm/src/msal/nodeFlows/msalClientAssertion.js +0 -42
- package/dist-esm/src/msal/nodeFlows/msalClientAssertion.js.map +0 -1
- package/dist-esm/src/msal/nodeFlows/msalClientCertificate.js +0 -112
- package/dist-esm/src/msal/nodeFlows/msalClientCertificate.js.map +0 -1
- package/dist-esm/src/msal/nodeFlows/msalClientSecret.js +0 -33
- package/dist-esm/src/msal/nodeFlows/msalClientSecret.js.map +0 -1
- package/dist-esm/src/msal/nodeFlows/msalDeviceCode.js +0 -35
- package/dist-esm/src/msal/nodeFlows/msalDeviceCode.js.map +0 -1
- package/dist-esm/src/msal/nodeFlows/msalNodeCommon.js +0 -323
- package/dist-esm/src/msal/nodeFlows/msalNodeCommon.js.map +0 -1
- package/dist-esm/src/msal/nodeFlows/msalOnBehalfOf.js +0 -58
- package/dist-esm/src/msal/nodeFlows/msalOnBehalfOf.js.map +0 -1
- package/dist-esm/src/msal/nodeFlows/msalOpenBrowser.js +0 -113
- package/dist-esm/src/msal/nodeFlows/msalOpenBrowser.js.map +0 -1
- package/dist-esm/src/msal/nodeFlows/msalUsernamePassword.js +0 -33
- package/dist-esm/src/msal/nodeFlows/msalUsernamePassword.js.map +0 -1
- /package/dist-esm/src/msal/{flows.js → browserFlows/flows.js} +0 -0
@@ -3,7 +3,6 @@
|
|
3
3
|
import { ServiceClient } from "@azure/core-client";
|
4
4
|
import { isNode } from "@azure/core-util";
|
5
5
|
import { createHttpHeaders, createPipelineRequest, } from "@azure/core-rest-pipeline";
|
6
|
-
import { AbortController } from "@azure/abort-controller";
|
7
6
|
import { AuthenticationError, AuthenticationErrorName } from "../errors";
|
8
7
|
import { getIdentityTokenEndpointSuffix } from "../util/identityTokenEndpoint";
|
9
8
|
import { DefaultAuthorityHost, SDK_VERSION } from "../constants";
|
@@ -143,7 +142,7 @@ export class IdentityClient extends ServiceClient {
|
|
143
142
|
controller.signal.onabort = (...params) => {
|
144
143
|
this.abortControllers.set(correlationId, undefined);
|
145
144
|
if (existingOnAbort) {
|
146
|
-
existingOnAbort(
|
145
|
+
existingOnAbort.apply(controller.signal, params);
|
147
146
|
}
|
148
147
|
};
|
149
148
|
return controller.signal;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"identityClient.js","sourceRoot":"","sources":["../../../src/client/identityClient.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport type { INetworkModule, NetworkRequestOptions, NetworkResponse } from \"@azure/msal-node\";\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { ServiceClient } from \"@azure/core-client\";\nimport { isNode } from \"@azure/core-util\";\nimport {\n PipelineRequest,\n PipelineResponse,\n createHttpHeaders,\n createPipelineRequest,\n} from \"@azure/core-rest-pipeline\";\nimport { AbortController, AbortSignalLike } from \"@azure/abort-controller\";\nimport { AuthenticationError, AuthenticationErrorName } from \"../errors\";\nimport { getIdentityTokenEndpointSuffix } from \"../util/identityTokenEndpoint\";\nimport { DefaultAuthorityHost, SDK_VERSION } from \"../constants\";\nimport { tracingClient } from \"../util/tracing\";\nimport { logger } from \"../util/logging\";\nimport { TokenCredentialOptions } from \"../tokenCredentialOptions\";\nimport {\n TokenResponseParsedBody,\n parseExpirationTimestamp,\n} from \"../credentials/managedIdentityCredential/utils\";\n\nconst noCorrelationId = \"noCorrelationId\";\n\n/**\n * An internal type used to communicate details of a token request's\n * response that should not be sent back as part of the access token.\n */\nexport interface TokenResponse {\n /**\n * The AccessToken to be returned from getToken.\n */\n accessToken: AccessToken;\n /**\n * The refresh token if the 'offline_access' scope was used.\n */\n refreshToken?: string;\n}\n\n/**\n * @internal\n */\nexport function getIdentityClientAuthorityHost(options?: TokenCredentialOptions): string {\n // The authorityHost can come from options or from the AZURE_AUTHORITY_HOST environment variable.\n let authorityHost = options?.authorityHost;\n\n // The AZURE_AUTHORITY_HOST environment variable can only be provided in Node.js.\n if (isNode) {\n authorityHost = authorityHost ?? process.env.AZURE_AUTHORITY_HOST;\n }\n\n // If the authorityHost is not provided, we use the default one from the public cloud: https://login.microsoftonline.com\n return authorityHost ?? DefaultAuthorityHost;\n}\n\n/**\n * The network module used by the Identity credentials.\n *\n * It allows for credentials to abort any pending request independently of the MSAL flow,\n * by calling to the `abortRequests()` method.\n *\n */\nexport class IdentityClient extends ServiceClient implements INetworkModule {\n public authorityHost: string;\n private allowLoggingAccountIdentifiers?: boolean;\n private abortControllers: Map<string, AbortController[] | undefined>;\n private allowInsecureConnection: boolean = false;\n // used for WorkloadIdentity\n private tokenCredentialOptions: TokenCredentialOptions;\n\n constructor(options?: TokenCredentialOptions) {\n const packageDetails = `azsdk-js-identity/${SDK_VERSION}`;\n const userAgentPrefix = options?.userAgentOptions?.userAgentPrefix\n ? `${options.userAgentOptions.userAgentPrefix} ${packageDetails}`\n : `${packageDetails}`;\n\n const baseUri = getIdentityClientAuthorityHost(options);\n if (!baseUri.startsWith(\"https:\")) {\n throw new Error(\"The authorityHost address must use the 'https' protocol.\");\n }\n\n super({\n requestContentType: \"application/json; charset=utf-8\",\n retryOptions: {\n maxRetries: 3,\n },\n ...options,\n userAgentOptions: {\n userAgentPrefix,\n },\n baseUri,\n });\n\n this.authorityHost = baseUri;\n this.abortControllers = new Map();\n this.allowLoggingAccountIdentifiers = options?.loggingOptions?.allowLoggingAccountIdentifiers;\n // used for WorkloadIdentity\n this.tokenCredentialOptions = { ...options };\n\n // used for ManagedIdentity\n if (options?.allowInsecureConnection) {\n this.allowInsecureConnection = options.allowInsecureConnection;\n }\n }\n\n async sendTokenRequest(request: PipelineRequest): Promise<TokenResponse | null> {\n logger.info(`IdentityClient: sending token request to [${request.url}]`);\n const response = await this.sendRequest(request);\n if (response.bodyAsText && (response.status === 200 || response.status === 201)) {\n const parsedBody: TokenResponseParsedBody = JSON.parse(response.bodyAsText);\n\n if (!parsedBody.access_token) {\n return null;\n }\n\n this.logIdentifiers(response);\n\n const token = {\n accessToken: {\n token: parsedBody.access_token,\n expiresOnTimestamp: parseExpirationTimestamp(parsedBody),\n },\n refreshToken: parsedBody.refresh_token,\n };\n\n logger.info(\n `IdentityClient: [${request.url}] token acquired, expires on ${token.accessToken.expiresOnTimestamp}`,\n );\n return token;\n } else {\n const error = new AuthenticationError(response.status, response.bodyAsText);\n logger.warning(\n `IdentityClient: authentication error. HTTP status: ${response.status}, ${error.errorResponse.errorDescription}`,\n );\n throw error;\n }\n }\n\n async refreshAccessToken(\n tenantId: string,\n clientId: string,\n scopes: string,\n refreshToken: string | undefined,\n clientSecret: string | undefined,\n options: GetTokenOptions = {},\n ): Promise<TokenResponse | null> {\n if (refreshToken === undefined) {\n return null;\n }\n logger.info(\n `IdentityClient: refreshing access token with client ID: ${clientId}, scopes: ${scopes} started`,\n );\n\n const refreshParams = {\n grant_type: \"refresh_token\",\n client_id: clientId,\n refresh_token: refreshToken,\n scope: scopes,\n };\n\n if (clientSecret !== undefined) {\n (refreshParams as any).client_secret = clientSecret;\n }\n\n const query = new URLSearchParams(refreshParams);\n\n return tracingClient.withSpan(\n \"IdentityClient.refreshAccessToken\",\n options,\n async (updatedOptions) => {\n try {\n const urlSuffix = getIdentityTokenEndpointSuffix(tenantId);\n const request = createPipelineRequest({\n url: `${this.authorityHost}/${tenantId}/${urlSuffix}`,\n method: \"POST\",\n body: query.toString(),\n abortSignal: options.abortSignal,\n headers: createHttpHeaders({\n Accept: \"application/json\",\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n }),\n tracingOptions: updatedOptions.tracingOptions,\n });\n\n const response = await this.sendTokenRequest(request);\n logger.info(`IdentityClient: refreshed token for client ID: ${clientId}`);\n return response;\n } catch (err: any) {\n if (\n err.name === AuthenticationErrorName &&\n err.errorResponse.error === \"interaction_required\"\n ) {\n // It's likely that the refresh token has expired, so\n // return null so that the credential implementation will\n // initiate the authentication flow again.\n logger.info(`IdentityClient: interaction required for client ID: ${clientId}`);\n return null;\n } else {\n logger.warning(\n `IdentityClient: failed refreshing token for client ID: ${clientId}: ${err}`,\n );\n throw err;\n }\n }\n },\n );\n }\n\n // Here is a custom layer that allows us to abort requests that go through MSAL,\n // since MSAL doesn't allow us to pass options all the way through.\n\n generateAbortSignal(correlationId: string): AbortSignalLike {\n const controller = new AbortController();\n const controllers = this.abortControllers.get(correlationId) || [];\n controllers.push(controller);\n this.abortControllers.set(correlationId, controllers);\n const existingOnAbort = controller.signal.onabort;\n controller.signal.onabort = (...params) => {\n this.abortControllers.set(correlationId, undefined);\n if (existingOnAbort) {\n existingOnAbort(...params);\n }\n };\n return controller.signal;\n }\n\n abortRequests(correlationId?: string): void {\n const key = correlationId || noCorrelationId;\n const controllers = [\n ...(this.abortControllers.get(key) || []),\n // MSAL passes no correlation ID to the get requests...\n ...(this.abortControllers.get(noCorrelationId) || []),\n ];\n if (!controllers.length) {\n return;\n }\n for (const controller of controllers) {\n controller.abort();\n }\n this.abortControllers.set(key, undefined);\n }\n\n getCorrelationId(options?: NetworkRequestOptions): string {\n const parameter = options?.body\n ?.split(\"&\")\n .map((part) => part.split(\"=\"))\n .find(([key]) => key === \"client-request-id\");\n return parameter && parameter.length ? parameter[1] || noCorrelationId : noCorrelationId;\n }\n\n // The MSAL network module methods follow\n\n async sendGetRequestAsync<T>(\n url: string,\n options?: NetworkRequestOptions,\n ): Promise<NetworkResponse<T>> {\n const request = createPipelineRequest({\n url,\n method: \"GET\",\n body: options?.body,\n allowInsecureConnection: this.allowInsecureConnection,\n headers: createHttpHeaders(options?.headers),\n abortSignal: this.generateAbortSignal(noCorrelationId),\n });\n\n const response = await this.sendRequest(request);\n\n this.logIdentifiers(response);\n\n return {\n body: response.bodyAsText ? JSON.parse(response.bodyAsText) : undefined,\n headers: response.headers.toJSON(),\n status: response.status,\n };\n }\n\n async sendPostRequestAsync<T>(\n url: string,\n options?: NetworkRequestOptions,\n ): Promise<NetworkResponse<T>> {\n const request = createPipelineRequest({\n url,\n method: \"POST\",\n body: options?.body,\n headers: createHttpHeaders(options?.headers),\n allowInsecureConnection: this.allowInsecureConnection,\n // MSAL doesn't send the correlation ID on the get requests.\n abortSignal: this.generateAbortSignal(this.getCorrelationId(options)),\n });\n\n const response = await this.sendRequest(request);\n\n this.logIdentifiers(response);\n\n return {\n body: response.bodyAsText ? JSON.parse(response.bodyAsText) : undefined,\n headers: response.headers.toJSON(),\n status: response.status,\n };\n }\n\n /**\n *\n * @internal\n */\n getTokenCredentialOptions(): TokenCredentialOptions {\n return this.tokenCredentialOptions;\n }\n /**\n * If allowLoggingAccountIdentifiers was set on the constructor options\n * we try to log the account identifiers by parsing the received access token.\n *\n * The account identifiers we try to log are:\n * - `appid`: The application or Client Identifier.\n * - `upn`: User Principal Name.\n * - It might not be available in some authentication scenarios.\n * - If it's not available, we put a placeholder: \"No User Principal Name available\".\n * - `tid`: Tenant Identifier.\n * - `oid`: Object Identifier of the authenticated user.\n */\n private logIdentifiers(response: PipelineResponse): void {\n if (!this.allowLoggingAccountIdentifiers || !response.bodyAsText) {\n return;\n }\n const unavailableUpn = \"No User Principal Name available\";\n try {\n const parsed = (response as any).parsedBody || JSON.parse(response.bodyAsText);\n const accessToken = parsed.access_token;\n if (!accessToken) {\n // Without an access token allowLoggingAccountIdentifiers isn't useful.\n return;\n }\n const base64Metadata = accessToken.split(\".\")[1];\n const { appid, upn, tid, oid } = JSON.parse(\n Buffer.from(base64Metadata, \"base64\").toString(\"utf8\"),\n );\n\n logger.info(\n `[Authenticated account] Client ID: ${appid}. Tenant ID: ${tid}. User Principal Name: ${\n upn || unavailableUpn\n }. Object ID (user): ${oid}`,\n );\n } catch (e: any) {\n logger.warning(\n \"allowLoggingAccountIdentifiers was set, but we couldn't log the account information. Error:\",\n e.message,\n );\n }\n }\n}\n"]}
|
1
|
+
{"version":3,"file":"identityClient.js","sourceRoot":"","sources":["../../../src/client/identityClient.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport type { INetworkModule, NetworkRequestOptions, NetworkResponse } from \"@azure/msal-node\";\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { ServiceClient } from \"@azure/core-client\";\nimport { isNode } from \"@azure/core-util\";\nimport {\n PipelineRequest,\n PipelineResponse,\n createHttpHeaders,\n createPipelineRequest,\n} from \"@azure/core-rest-pipeline\";\nimport { AbortSignalLike } from \"@azure/abort-controller\";\nimport { AuthenticationError, AuthenticationErrorName } from \"../errors\";\nimport { getIdentityTokenEndpointSuffix } from \"../util/identityTokenEndpoint\";\nimport { DefaultAuthorityHost, SDK_VERSION } from \"../constants\";\nimport { tracingClient } from \"../util/tracing\";\nimport { logger } from \"../util/logging\";\nimport { TokenCredentialOptions } from \"../tokenCredentialOptions\";\nimport {\n TokenResponseParsedBody,\n parseExpirationTimestamp,\n} from \"../credentials/managedIdentityCredential/utils\";\n\nconst noCorrelationId = \"noCorrelationId\";\n\n/**\n * An internal type used to communicate details of a token request's\n * response that should not be sent back as part of the access token.\n */\nexport interface TokenResponse {\n /**\n * The AccessToken to be returned from getToken.\n */\n accessToken: AccessToken;\n /**\n * The refresh token if the 'offline_access' scope was used.\n */\n refreshToken?: string;\n}\n\n/**\n * @internal\n */\nexport function getIdentityClientAuthorityHost(options?: TokenCredentialOptions): string {\n // The authorityHost can come from options or from the AZURE_AUTHORITY_HOST environment variable.\n let authorityHost = options?.authorityHost;\n\n // The AZURE_AUTHORITY_HOST environment variable can only be provided in Node.js.\n if (isNode) {\n authorityHost = authorityHost ?? process.env.AZURE_AUTHORITY_HOST;\n }\n\n // If the authorityHost is not provided, we use the default one from the public cloud: https://login.microsoftonline.com\n return authorityHost ?? DefaultAuthorityHost;\n}\n\n/**\n * The network module used by the Identity credentials.\n *\n * It allows for credentials to abort any pending request independently of the MSAL flow,\n * by calling to the `abortRequests()` method.\n *\n */\nexport class IdentityClient extends ServiceClient implements INetworkModule {\n public authorityHost: string;\n private allowLoggingAccountIdentifiers?: boolean;\n private abortControllers: Map<string, AbortController[] | undefined>;\n private allowInsecureConnection: boolean = false;\n // used for WorkloadIdentity\n private tokenCredentialOptions: TokenCredentialOptions;\n\n constructor(options?: TokenCredentialOptions) {\n const packageDetails = `azsdk-js-identity/${SDK_VERSION}`;\n const userAgentPrefix = options?.userAgentOptions?.userAgentPrefix\n ? `${options.userAgentOptions.userAgentPrefix} ${packageDetails}`\n : `${packageDetails}`;\n\n const baseUri = getIdentityClientAuthorityHost(options);\n if (!baseUri.startsWith(\"https:\")) {\n throw new Error(\"The authorityHost address must use the 'https' protocol.\");\n }\n\n super({\n requestContentType: \"application/json; charset=utf-8\",\n retryOptions: {\n maxRetries: 3,\n },\n ...options,\n userAgentOptions: {\n userAgentPrefix,\n },\n baseUri,\n });\n\n this.authorityHost = baseUri;\n this.abortControllers = new Map();\n this.allowLoggingAccountIdentifiers = options?.loggingOptions?.allowLoggingAccountIdentifiers;\n // used for WorkloadIdentity\n this.tokenCredentialOptions = { ...options };\n\n // used for ManagedIdentity\n if (options?.allowInsecureConnection) {\n this.allowInsecureConnection = options.allowInsecureConnection;\n }\n }\n\n async sendTokenRequest(request: PipelineRequest): Promise<TokenResponse | null> {\n logger.info(`IdentityClient: sending token request to [${request.url}]`);\n const response = await this.sendRequest(request);\n if (response.bodyAsText && (response.status === 200 || response.status === 201)) {\n const parsedBody: TokenResponseParsedBody = JSON.parse(response.bodyAsText);\n\n if (!parsedBody.access_token) {\n return null;\n }\n\n this.logIdentifiers(response);\n\n const token = {\n accessToken: {\n token: parsedBody.access_token,\n expiresOnTimestamp: parseExpirationTimestamp(parsedBody),\n },\n refreshToken: parsedBody.refresh_token,\n };\n\n logger.info(\n `IdentityClient: [${request.url}] token acquired, expires on ${token.accessToken.expiresOnTimestamp}`,\n );\n return token;\n } else {\n const error = new AuthenticationError(response.status, response.bodyAsText);\n logger.warning(\n `IdentityClient: authentication error. HTTP status: ${response.status}, ${error.errorResponse.errorDescription}`,\n );\n throw error;\n }\n }\n\n async refreshAccessToken(\n tenantId: string,\n clientId: string,\n scopes: string,\n refreshToken: string | undefined,\n clientSecret: string | undefined,\n options: GetTokenOptions = {},\n ): Promise<TokenResponse | null> {\n if (refreshToken === undefined) {\n return null;\n }\n logger.info(\n `IdentityClient: refreshing access token with client ID: ${clientId}, scopes: ${scopes} started`,\n );\n\n const refreshParams = {\n grant_type: \"refresh_token\",\n client_id: clientId,\n refresh_token: refreshToken,\n scope: scopes,\n };\n\n if (clientSecret !== undefined) {\n (refreshParams as any).client_secret = clientSecret;\n }\n\n const query = new URLSearchParams(refreshParams);\n\n return tracingClient.withSpan(\n \"IdentityClient.refreshAccessToken\",\n options,\n async (updatedOptions) => {\n try {\n const urlSuffix = getIdentityTokenEndpointSuffix(tenantId);\n const request = createPipelineRequest({\n url: `${this.authorityHost}/${tenantId}/${urlSuffix}`,\n method: \"POST\",\n body: query.toString(),\n abortSignal: options.abortSignal,\n headers: createHttpHeaders({\n Accept: \"application/json\",\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n }),\n tracingOptions: updatedOptions.tracingOptions,\n });\n\n const response = await this.sendTokenRequest(request);\n logger.info(`IdentityClient: refreshed token for client ID: ${clientId}`);\n return response;\n } catch (err: any) {\n if (\n err.name === AuthenticationErrorName &&\n err.errorResponse.error === \"interaction_required\"\n ) {\n // It's likely that the refresh token has expired, so\n // return null so that the credential implementation will\n // initiate the authentication flow again.\n logger.info(`IdentityClient: interaction required for client ID: ${clientId}`);\n return null;\n } else {\n logger.warning(\n `IdentityClient: failed refreshing token for client ID: ${clientId}: ${err}`,\n );\n throw err;\n }\n }\n },\n );\n }\n\n // Here is a custom layer that allows us to abort requests that go through MSAL,\n // since MSAL doesn't allow us to pass options all the way through.\n\n generateAbortSignal(correlationId: string): AbortSignalLike {\n const controller = new AbortController();\n const controllers = this.abortControllers.get(correlationId) || [];\n controllers.push(controller);\n this.abortControllers.set(correlationId, controllers);\n const existingOnAbort = controller.signal.onabort;\n controller.signal.onabort = (...params) => {\n this.abortControllers.set(correlationId, undefined);\n if (existingOnAbort) {\n existingOnAbort.apply(controller.signal, params);\n }\n };\n return controller.signal;\n }\n\n abortRequests(correlationId?: string): void {\n const key = correlationId || noCorrelationId;\n const controllers = [\n ...(this.abortControllers.get(key) || []),\n // MSAL passes no correlation ID to the get requests...\n ...(this.abortControllers.get(noCorrelationId) || []),\n ];\n if (!controllers.length) {\n return;\n }\n for (const controller of controllers) {\n controller.abort();\n }\n this.abortControllers.set(key, undefined);\n }\n\n getCorrelationId(options?: NetworkRequestOptions): string {\n const parameter = options?.body\n ?.split(\"&\")\n .map((part) => part.split(\"=\"))\n .find(([key]) => key === \"client-request-id\");\n return parameter && parameter.length ? parameter[1] || noCorrelationId : noCorrelationId;\n }\n\n // The MSAL network module methods follow\n\n async sendGetRequestAsync<T>(\n url: string,\n options?: NetworkRequestOptions,\n ): Promise<NetworkResponse<T>> {\n const request = createPipelineRequest({\n url,\n method: \"GET\",\n body: options?.body,\n allowInsecureConnection: this.allowInsecureConnection,\n headers: createHttpHeaders(options?.headers),\n abortSignal: this.generateAbortSignal(noCorrelationId),\n });\n\n const response = await this.sendRequest(request);\n\n this.logIdentifiers(response);\n\n return {\n body: response.bodyAsText ? JSON.parse(response.bodyAsText) : undefined,\n headers: response.headers.toJSON(),\n status: response.status,\n };\n }\n\n async sendPostRequestAsync<T>(\n url: string,\n options?: NetworkRequestOptions,\n ): Promise<NetworkResponse<T>> {\n const request = createPipelineRequest({\n url,\n method: \"POST\",\n body: options?.body,\n headers: createHttpHeaders(options?.headers),\n allowInsecureConnection: this.allowInsecureConnection,\n // MSAL doesn't send the correlation ID on the get requests.\n abortSignal: this.generateAbortSignal(this.getCorrelationId(options)),\n });\n\n const response = await this.sendRequest(request);\n\n this.logIdentifiers(response);\n\n return {\n body: response.bodyAsText ? JSON.parse(response.bodyAsText) : undefined,\n headers: response.headers.toJSON(),\n status: response.status,\n };\n }\n\n /**\n *\n * @internal\n */\n getTokenCredentialOptions(): TokenCredentialOptions {\n return this.tokenCredentialOptions;\n }\n /**\n * If allowLoggingAccountIdentifiers was set on the constructor options\n * we try to log the account identifiers by parsing the received access token.\n *\n * The account identifiers we try to log are:\n * - `appid`: The application or Client Identifier.\n * - `upn`: User Principal Name.\n * - It might not be available in some authentication scenarios.\n * - If it's not available, we put a placeholder: \"No User Principal Name available\".\n * - `tid`: Tenant Identifier.\n * - `oid`: Object Identifier of the authenticated user.\n */\n private logIdentifiers(response: PipelineResponse): void {\n if (!this.allowLoggingAccountIdentifiers || !response.bodyAsText) {\n return;\n }\n const unavailableUpn = \"No User Principal Name available\";\n try {\n const parsed = (response as any).parsedBody || JSON.parse(response.bodyAsText);\n const accessToken = parsed.access_token;\n if (!accessToken) {\n // Without an access token allowLoggingAccountIdentifiers isn't useful.\n return;\n }\n const base64Metadata = accessToken.split(\".\")[1];\n const { appid, upn, tid, oid } = JSON.parse(\n Buffer.from(base64Metadata, \"base64\").toString(\"utf8\"),\n );\n\n logger.info(\n `[Authenticated account] Client ID: ${appid}. Tenant ID: ${tid}. User Principal Name: ${\n upn || unavailableUpn\n }. Object ID (user): ${oid}`,\n );\n } catch (e: any) {\n logger.warning(\n \"allowLoggingAccountIdentifiers was set, but we couldn't log the account information. Error:\",\n e.message,\n );\n }\n }\n}\n"]}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,cAAc,CAAC;AAE1C;;;GAGG;AACH,2EAA2E;AAC3E,6CAA6C;AAC7C,uGAAuG;AACvG,MAAM,CAAC,MAAM,uBAAuB,GAAG,sCAAsC,CAAC;AAE9E;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAC;AAExC;;GAEG;AACH,MAAM,CAAN,IAAY,mBAiBX;AAjBD,WAAY,mBAAmB;IAC7B;;OAEG;IACH,oEAA6C,CAAA;IAC7C;;OAEG;IACH,wEAAiD,CAAA;IACjD;;OAEG;IACH,2EAAoD,CAAA;IACpD;;OAEG;IACH,6EAAsD,CAAA;AACxD,CAAC,EAjBW,mBAAmB,KAAnB,mBAAmB,QAiB9B;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,mBAAmB,CAAC,gBAAgB,CAAC;AAEzE;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAa,CAAC,GAAG,CAAC,CAAC;AAE3C;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAEtC;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,OAAO,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,YAAY,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/**\n * Current version of the `@azure/identity` package.\n */\nexport const SDK_VERSION = `4.5.0-beta.
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,cAAc,CAAC;AAE1C;;;GAGG;AACH,2EAA2E;AAC3E,6CAA6C;AAC7C,uGAAuG;AACvG,MAAM,CAAC,MAAM,uBAAuB,GAAG,sCAAsC,CAAC;AAE9E;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAC;AAExC;;GAEG;AACH,MAAM,CAAN,IAAY,mBAiBX;AAjBD,WAAY,mBAAmB;IAC7B;;OAEG;IACH,oEAA6C,CAAA;IAC7C;;OAEG;IACH,wEAAiD,CAAA;IACjD;;OAEG;IACH,2EAAoD,CAAA;IACpD;;OAEG;IACH,6EAAsD,CAAA;AACxD,CAAC,EAjBW,mBAAmB,KAAnB,mBAAmB,QAiB9B;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,mBAAmB,CAAC,gBAAgB,CAAC;AAEzE;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAa,CAAC,GAAG,CAAC,CAAC;AAE3C;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAEtC;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,OAAO,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,YAAY,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/**\n * Current version of the `@azure/identity` package.\n */\nexport const SDK_VERSION = `4.5.0-beta.2`;\n\n/**\n * The default client ID for authentication\n * @internal\n */\n// TODO: temporary - this is the Azure CLI clientID - we'll replace it when\n// Developer Sign On application is available\n// https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/src/Constants.cs#L9\nexport const DeveloperSignOnClientId = \"04b07795-8ddb-461a-bbee-02f9e1bf7b46\";\n\n/**\n * The default tenant for authentication\n * @internal\n */\nexport const DefaultTenantId = \"common\";\n\n/**\n * A list of known Azure authority hosts\n */\nexport enum AzureAuthorityHosts {\n /**\n * China-based Azure Authority Host\n */\n AzureChina = \"https://login.chinacloudapi.cn\",\n /**\n * Germany-based Azure Authority Host\n */\n AzureGermany = \"https://login.microsoftonline.de\",\n /**\n * US Government Azure Authority Host\n */\n AzureGovernment = \"https://login.microsoftonline.us\",\n /**\n * Public Cloud Azure Authority Host\n */\n AzurePublicCloud = \"https://login.microsoftonline.com\",\n}\n\n/**\n * @internal\n * The default authority host.\n */\nexport const DefaultAuthorityHost = AzureAuthorityHosts.AzurePublicCloud;\n\n/**\n * @internal\n * Allow acquiring tokens for any tenant for multi-tentant auth.\n */\nexport const ALL_TENANTS: string[] = [\"*\"];\n\n/**\n * @internal\n */\nexport const CACHE_CAE_SUFFIX = \"cae\";\n\n/**\n * @internal\n */\nexport const CACHE_NON_CAE_SUFFIX = \"nocae\";\n\n/**\n * @internal\n *\n * The default name for the cache persistence plugin.\n * Matches the constant defined in the cache persistence package.\n */\nexport const DEFAULT_TOKEN_CACHE_NAME = \"msal.cache\";\n"]}
|
@@ -1,11 +1,11 @@
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
2
2
|
// Licensed under the MIT license.
|
3
|
-
import { ClientAssertionCredential } from "./clientAssertionCredential";
|
4
3
|
import { AuthenticationError, CredentialUnavailableError } from "../errors";
|
5
|
-
import { credentialLogger } from "../util/logging";
|
6
|
-
import { checkTenantId } from "../util/tenantIdUtils";
|
7
4
|
import { createHttpHeaders, createPipelineRequest } from "@azure/core-rest-pipeline";
|
5
|
+
import { ClientAssertionCredential } from "./clientAssertionCredential";
|
8
6
|
import { IdentityClient } from "../client/identityClient";
|
7
|
+
import { checkTenantId } from "../util/tenantIdUtils";
|
8
|
+
import { credentialLogger } from "../util/logging";
|
9
9
|
const credentialName = "AzurePipelinesCredential";
|
10
10
|
const logger = credentialLogger(credentialName);
|
11
11
|
const OIDC_API_VERSION = "7.1";
|
@@ -23,8 +23,17 @@ export class AzurePipelinesCredential {
|
|
23
23
|
* @param options - The identity client options to use for authentication.
|
24
24
|
*/
|
25
25
|
constructor(tenantId, clientId, serviceConnectionId, systemAccessToken, options) {
|
26
|
-
if (!clientId
|
27
|
-
throw new CredentialUnavailableError(`${credentialName}: is unavailable.
|
26
|
+
if (!clientId) {
|
27
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. clientId is a required parameter.`);
|
28
|
+
}
|
29
|
+
if (!tenantId) {
|
30
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. tenantId is a required parameter.`);
|
31
|
+
}
|
32
|
+
if (!serviceConnectionId) {
|
33
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. serviceConnectionId is a required parameter.`);
|
34
|
+
}
|
35
|
+
if (!systemAccessToken) {
|
36
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. systemAccessToken is a required parameter.`);
|
28
37
|
}
|
29
38
|
this.identityClient = new IdentityClient(options);
|
30
39
|
checkTenantId(logger, tenantId);
|
@@ -77,30 +86,45 @@ export class AzurePipelinesCredential {
|
|
77
86
|
}),
|
78
87
|
});
|
79
88
|
const response = await this.identityClient.sendRequest(request);
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
89
|
+
return handleOidcResponse(response);
|
90
|
+
}
|
91
|
+
}
|
92
|
+
export function handleOidcResponse(response) {
|
93
|
+
const text = response.bodyAsText;
|
94
|
+
if (!text) {
|
95
|
+
logger.error(`${credentialName}: Authentication Failed. Received null token from OIDC request. Response status- ${response.status}. Complete response - ${JSON.stringify(response)}`);
|
96
|
+
throw new AuthenticationError(response.status, {
|
97
|
+
error: `${credentialName}: Authentication Failed. Received null token from OIDC request.`,
|
98
|
+
error_description: `${JSON.stringify(response)}. See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/azurepipelinescredential/troubleshoot`,
|
99
|
+
});
|
100
|
+
}
|
101
|
+
try {
|
102
|
+
const result = JSON.parse(text);
|
103
|
+
if (result === null || result === void 0 ? void 0 : result.oidcToken) {
|
104
|
+
return result.oidcToken;
|
84
105
|
}
|
85
|
-
|
86
|
-
const
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
else {
|
91
|
-
let errorMessage = `${credentialName}: Authentication Failed. oidcToken field not detected in the response.`;
|
92
|
-
if (response.status !== 200) {
|
93
|
-
errorMessage += `Response = ${JSON.stringify(result)}`;
|
94
|
-
}
|
95
|
-
logger.error(errorMessage);
|
96
|
-
throw new AuthenticationError(response.status, errorMessage);
|
106
|
+
else {
|
107
|
+
const errorMessage = `${credentialName}: Authentication Failed. oidcToken field not detected in the response.`;
|
108
|
+
let errorDescription = ``;
|
109
|
+
if (response.status !== 200) {
|
110
|
+
errorDescription = `Complete response - ${JSON.stringify(result)}. See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/azurepipelinescredential/troubleshoot`;
|
97
111
|
}
|
112
|
+
logger.error(errorMessage);
|
113
|
+
logger.error(errorDescription);
|
114
|
+
throw new AuthenticationError(response.status, {
|
115
|
+
error: errorMessage,
|
116
|
+
error_description: errorDescription,
|
117
|
+
});
|
98
118
|
}
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
119
|
+
}
|
120
|
+
catch (e) {
|
121
|
+
const errorDetails = `${credentialName}: Authentication Failed. oidcToken field not detected in the response.`;
|
122
|
+
logger.error(`Response from service = ${text} and error message = ${e.message}`);
|
123
|
+
logger.error(errorDetails);
|
124
|
+
throw new AuthenticationError(response.status, {
|
125
|
+
error: errorDetails,
|
126
|
+
error_description: `Response = ${text}. See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/azurepipelinescredential/troubleshoot`,
|
127
|
+
});
|
104
128
|
}
|
105
129
|
}
|
106
130
|
//# sourceMappingURL=azurePipelinesCredential.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"azurePipelinesCredential.js","sourceRoot":"","sources":["../../../src/credentials/azurePipelinesCredential.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport { ClientAssertionCredential } from \"./clientAssertionCredential\";\nimport { AuthenticationError, CredentialUnavailableError } from \"../errors\";\nimport { credentialLogger } from \"../util/logging\";\nimport { checkTenantId } from \"../util/tenantIdUtils\";\nimport { createHttpHeaders, createPipelineRequest } from \"@azure/core-rest-pipeline\";\nimport { AzurePipelinesCredentialOptions } from \"./azurePipelinesCredentialOptions\";\nimport { IdentityClient } from \"../client/identityClient\";\n\nconst credentialName = \"AzurePipelinesCredential\";\nconst logger = credentialLogger(credentialName);\nconst OIDC_API_VERSION = \"7.1\";\n\n/**\n * This credential is designed to be used in Azure Pipelines with service connections\n * as a setup for workload identity federation.\n */\nexport class AzurePipelinesCredential implements TokenCredential {\n private clientAssertionCredential: ClientAssertionCredential | undefined;\n private identityClient: IdentityClient;\n\n /**\n * AzurePipelinesCredential supports Federated Identity on Azure Pipelines through Service Connections.\n * @param tenantId - tenantId associated with the service connection\n * @param clientId - clientId associated with the service connection\n * @param serviceConnectionId - Unique ID for the service connection, as found in the querystring's resourceId key\n * @param systemAccessToken - The pipeline's <see href=\"https://learn.microsoft.com/azure/devops/pipelines/build/variables?view=azure-devops%26tabs=yaml#systemaccesstoken\">System.AccessToken</see> value.\n * @param options - The identity client options to use for authentication.\n */\n constructor(\n tenantId: string,\n clientId: string,\n serviceConnectionId: string,\n systemAccessToken: string,\n options?: AzurePipelinesCredentialOptions,\n ) {\n if (!clientId || !tenantId || !serviceConnectionId || !systemAccessToken) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. tenantId, clientId, serviceConnectionId, and systemAccessToken are required parameters.`,\n );\n }\n this.identityClient = new IdentityClient(options);\n checkTenantId(logger, tenantId);\n logger.info(\n `Invoking AzurePipelinesCredential with tenant ID: ${tenantId}, client ID: ${clientId}, and service connection ID: ${serviceConnectionId}`,\n );\n if (!process.env.SYSTEM_OIDCREQUESTURI) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. Ensure that you're running this task in an Azure Pipeline, so that following missing system variable(s) can be defined- \"SYSTEM_OIDCREQUESTURI\"`,\n );\n }\n\n const oidcRequestUrl = `${process.env.SYSTEM_OIDCREQUESTURI}?api-version=${OIDC_API_VERSION}&serviceConnectionId=${serviceConnectionId}`;\n logger.info(\n `Invoking ClientAssertionCredential with tenant ID: ${tenantId}, client ID: ${clientId} and service connection ID: ${serviceConnectionId}`,\n );\n this.clientAssertionCredential = new ClientAssertionCredential(\n tenantId,\n clientId,\n this.requestOidcToken.bind(this, oidcRequestUrl, systemAccessToken),\n options,\n );\n }\n\n /**\n * Authenticates with Microsoft Entra ID and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} or {@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 if (!this.clientAssertionCredential) {\n const errorMessage = `${credentialName}: is unavailable. To use Federation Identity in Azure Pipelines, the following parameters are required - \n tenantId,\n clientId,\n serviceConnectionId,\n systemAccessToken,\n \"SYSTEM_OIDCREQUESTURI\". \n See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/azurepipelinescredential/troubleshoot`;\n logger.error(errorMessage);\n throw new CredentialUnavailableError(errorMessage);\n }\n logger.info(\"Invoking getToken() of Client Assertion Credential\");\n return this.clientAssertionCredential.getToken(scopes, options);\n }\n\n /**\n *\n * @param oidcRequestUrl - oidc request url\n * @param systemAccessToken - system access token\n * @returns OIDC token from Azure Pipelines\n */\n private async requestOidcToken(\n oidcRequestUrl: string,\n systemAccessToken: string,\n ): Promise<string> {\n logger.info(\"Requesting OIDC token from Azure Pipelines...\");\n logger.info(oidcRequestUrl);\n const request = createPipelineRequest({\n url: oidcRequestUrl,\n method: \"POST\",\n headers: createHttpHeaders({\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${systemAccessToken}`,\n }),\n });\n const response = await this.identityClient.sendRequest(request);\n const text = response.bodyAsText;\n if (!text) {\n logger.error(\n `${credentialName}: Authenticated Failed. Received null token from OIDC request. Response status- ${\n response.status\n }. Complete response - ${JSON.stringify(response)}`,\n );\n throw new AuthenticationError(\n response.status,\n `${credentialName}: Authenticated Failed. Received null token from OIDC request. Response status- ${\n response.status\n }. Complete response - ${JSON.stringify(response)}`,\n );\n }\n try {\n const result = JSON.parse(text);\n if (result?.oidcToken) {\n return result.oidcToken;\n } else {\n let errorMessage = `${credentialName}: Authentication Failed. oidcToken field not detected in the response.`;\n if (response.status !== 200) {\n errorMessage += `Response = ${JSON.stringify(result)}`;\n }\n logger.error(errorMessage);\n throw new AuthenticationError(response.status, errorMessage);\n }\n } catch (e: any) {\n logger.error(e.message);\n logger.error(\n `${credentialName}: Authentication Failed. oidcToken field not detected in the response. Response = ${text}`,\n );\n throw new AuthenticationError(\n response.status,\n `${credentialName}: Authentication Failed. oidcToken field not detected in the response. Response = ${text}`,\n );\n }\n }\n}\n"]}
|
1
|
+
{"version":3,"file":"azurePipelinesCredential.js","sourceRoot":"","sources":["../../../src/credentials/azurePipelinesCredential.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport { AuthenticationError, CredentialUnavailableError } from \"../errors\";\nimport { createHttpHeaders, createPipelineRequest } from \"@azure/core-rest-pipeline\";\n\nimport { AzurePipelinesCredentialOptions } from \"./azurePipelinesCredentialOptions\";\nimport { ClientAssertionCredential } from \"./clientAssertionCredential\";\nimport { IdentityClient } from \"../client/identityClient\";\nimport { PipelineResponse } from \"@azure/core-rest-pipeline\";\nimport { checkTenantId } from \"../util/tenantIdUtils\";\nimport { credentialLogger } from \"../util/logging\";\n\nconst credentialName = \"AzurePipelinesCredential\";\nconst logger = credentialLogger(credentialName);\nconst OIDC_API_VERSION = \"7.1\";\n\n/**\n * This credential is designed to be used in Azure Pipelines with service connections\n * as a setup for workload identity federation.\n */\nexport class AzurePipelinesCredential implements TokenCredential {\n private clientAssertionCredential: ClientAssertionCredential | undefined;\n private identityClient: IdentityClient;\n\n /**\n * AzurePipelinesCredential supports Federated Identity on Azure Pipelines through Service Connections.\n * @param tenantId - tenantId associated with the service connection\n * @param clientId - clientId associated with the service connection\n * @param serviceConnectionId - Unique ID for the service connection, as found in the querystring's resourceId key\n * @param systemAccessToken - The pipeline's <see href=\"https://learn.microsoft.com/azure/devops/pipelines/build/variables?view=azure-devops%26tabs=yaml#systemaccesstoken\">System.AccessToken</see> value.\n * @param options - The identity client options to use for authentication.\n */\n constructor(\n tenantId: string,\n clientId: string,\n serviceConnectionId: string,\n systemAccessToken: string,\n options?: AzurePipelinesCredentialOptions,\n ) {\n if (!clientId) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. clientId is a required parameter.`,\n );\n }\n if (!tenantId) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. tenantId is a required parameter.`,\n );\n }\n if (!serviceConnectionId) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. serviceConnectionId is a required parameter.`,\n );\n }\n if (!systemAccessToken) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. systemAccessToken is a required parameter.`,\n );\n }\n\n this.identityClient = new IdentityClient(options);\n checkTenantId(logger, tenantId);\n logger.info(\n `Invoking AzurePipelinesCredential with tenant ID: ${tenantId}, client ID: ${clientId}, and service connection ID: ${serviceConnectionId}`,\n );\n if (!process.env.SYSTEM_OIDCREQUESTURI) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. Ensure that you're running this task in an Azure Pipeline, so that following missing system variable(s) can be defined- \"SYSTEM_OIDCREQUESTURI\"`,\n );\n }\n\n const oidcRequestUrl = `${process.env.SYSTEM_OIDCREQUESTURI}?api-version=${OIDC_API_VERSION}&serviceConnectionId=${serviceConnectionId}`;\n logger.info(\n `Invoking ClientAssertionCredential with tenant ID: ${tenantId}, client ID: ${clientId} and service connection ID: ${serviceConnectionId}`,\n );\n this.clientAssertionCredential = new ClientAssertionCredential(\n tenantId,\n clientId,\n this.requestOidcToken.bind(this, oidcRequestUrl, systemAccessToken),\n options,\n );\n }\n\n /**\n * Authenticates with Microsoft Entra ID and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} or {@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 if (!this.clientAssertionCredential) {\n const errorMessage = `${credentialName}: is unavailable. To use Federation Identity in Azure Pipelines, the following parameters are required - \n tenantId,\n clientId,\n serviceConnectionId,\n systemAccessToken,\n \"SYSTEM_OIDCREQUESTURI\". \n See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/azurepipelinescredential/troubleshoot`;\n logger.error(errorMessage);\n throw new CredentialUnavailableError(errorMessage);\n }\n logger.info(\"Invoking getToken() of Client Assertion Credential\");\n return this.clientAssertionCredential.getToken(scopes, options);\n }\n\n /**\n *\n * @param oidcRequestUrl - oidc request url\n * @param systemAccessToken - system access token\n * @returns OIDC token from Azure Pipelines\n */\n private async requestOidcToken(\n oidcRequestUrl: string,\n systemAccessToken: string,\n ): Promise<string> {\n logger.info(\"Requesting OIDC token from Azure Pipelines...\");\n logger.info(oidcRequestUrl);\n const request = createPipelineRequest({\n url: oidcRequestUrl,\n method: \"POST\",\n headers: createHttpHeaders({\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${systemAccessToken}`,\n }),\n });\n const response = await this.identityClient.sendRequest(request);\n return handleOidcResponse(response);\n }\n}\n\nexport function handleOidcResponse(response: PipelineResponse): string {\n const text = response.bodyAsText;\n if (!text) {\n logger.error(\n `${credentialName}: Authentication Failed. Received null token from OIDC request. Response status- ${\n response.status\n }. Complete response - ${JSON.stringify(response)}`,\n );\n throw new AuthenticationError(response.status, {\n error: `${credentialName}: Authentication Failed. Received null token from OIDC request.`,\n error_description: `${JSON.stringify(\n response,\n )}. See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/azurepipelinescredential/troubleshoot`,\n });\n }\n try {\n const result = JSON.parse(text);\n if (result?.oidcToken) {\n return result.oidcToken;\n } else {\n const errorMessage = `${credentialName}: Authentication Failed. oidcToken field not detected in the response.`;\n let errorDescription = ``;\n if (response.status !== 200) {\n errorDescription = `Complete response - ${JSON.stringify(\n result,\n )}. See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/azurepipelinescredential/troubleshoot`;\n }\n logger.error(errorMessage);\n logger.error(errorDescription);\n throw new AuthenticationError(response.status, {\n error: errorMessage,\n error_description: errorDescription,\n });\n }\n } catch (e: any) {\n const errorDetails = `${credentialName}: Authentication Failed. oidcToken field not detected in the response.`;\n logger.error(`Response from service = ${text} and error message = ${e.message}`);\n logger.error(errorDetails);\n throw new AuthenticationError(response.status, {\n error: errorDetails,\n error_description: `Response = ${text}. See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/azurepipelinescredential/troubleshoot`,\n });\n }\n}\n"]}
|
@@ -108,33 +108,45 @@ export class AzurePowerShellCredential {
|
|
108
108
|
commandStack.shift();
|
109
109
|
continue;
|
110
110
|
}
|
111
|
-
let tenantSection = "";
|
112
|
-
if (tenantId) {
|
113
|
-
tenantSection = `-TenantId "${tenantId}"`;
|
114
|
-
}
|
115
111
|
const results = await runCommands([
|
116
112
|
[
|
117
113
|
powerShellCommand,
|
118
114
|
"-NoProfile",
|
119
115
|
"-NonInteractive",
|
120
116
|
"-Command",
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
117
|
+
`
|
118
|
+
$tenantId = "${tenantId !== null && tenantId !== void 0 ? tenantId : ""}"
|
119
|
+
$m = Import-Module Az.Accounts -MinimumVersion 2.2.0 -PassThru
|
120
|
+
$useSecureString = $m.Version -ge [version]'2.17.0'
|
121
|
+
|
122
|
+
$params = @{
|
123
|
+
ResourceUrl = "${resource}"
|
124
|
+
}
|
125
|
+
|
126
|
+
if ($tenantId.Length -gt 0) {
|
127
|
+
$params["TenantId"] = $tenantId
|
128
|
+
}
|
129
|
+
|
130
|
+
if ($useSecureString) {
|
131
|
+
$params["AsSecureString"] = $true
|
132
|
+
}
|
133
|
+
|
134
|
+
$token = Get-AzAccessToken @params
|
135
|
+
|
136
|
+
$result = New-Object -TypeName PSObject
|
137
|
+
$result | Add-Member -MemberType NoteProperty -Name ExpiresOn -Value $token.ExpiresOn
|
138
|
+
if ($useSecureString) {
|
139
|
+
$result | Add-Member -MemberType NoteProperty -Name Token -Value (ConvertFrom-SecureString -AsPlainText $token.Token)
|
140
|
+
} else {
|
141
|
+
$result | Add-Member -MemberType NoteProperty -Name Token -Value $token.Token
|
142
|
+
}
|
143
|
+
|
144
|
+
Write-Output (ConvertTo-Json $result)
|
145
|
+
`,
|
129
146
|
],
|
130
147
|
]);
|
131
|
-
const result = results[
|
132
|
-
|
133
|
-
return JSON.parse(result);
|
134
|
-
}
|
135
|
-
catch (e) {
|
136
|
-
throw new Error(`Unable to parse the output of PowerShell. Received output: ${result}`);
|
137
|
-
}
|
148
|
+
const result = results[0];
|
149
|
+
return parseJsonToken(result);
|
138
150
|
}
|
139
151
|
throw new Error(`Unable to execute PowerShell. Ensure that it is installed in your system`);
|
140
152
|
}
|
@@ -181,4 +193,36 @@ export class AzurePowerShellCredential {
|
|
181
193
|
});
|
182
194
|
}
|
183
195
|
}
|
196
|
+
/**
|
197
|
+
*
|
198
|
+
* @internal
|
199
|
+
*/
|
200
|
+
export async function parseJsonToken(result) {
|
201
|
+
const jsonRegex = /{[^{}]*}/g;
|
202
|
+
const matches = result.match(jsonRegex);
|
203
|
+
let resultWithoutToken = result;
|
204
|
+
if (matches) {
|
205
|
+
try {
|
206
|
+
for (const item of matches) {
|
207
|
+
try {
|
208
|
+
const jsonContent = JSON.parse(item);
|
209
|
+
if (jsonContent === null || jsonContent === void 0 ? void 0 : jsonContent.Token) {
|
210
|
+
resultWithoutToken = resultWithoutToken.replace(item, "");
|
211
|
+
if (resultWithoutToken) {
|
212
|
+
logger.getToken.warning(resultWithoutToken);
|
213
|
+
}
|
214
|
+
return jsonContent;
|
215
|
+
}
|
216
|
+
}
|
217
|
+
catch (e) {
|
218
|
+
continue;
|
219
|
+
}
|
220
|
+
}
|
221
|
+
}
|
222
|
+
catch (e) {
|
223
|
+
throw new Error(`Unable to parse the output of PowerShell. Received output: ${result}`);
|
224
|
+
}
|
225
|
+
}
|
226
|
+
throw new Error(`No access token found in the output. Received output: ${result}`);
|
227
|
+
}
|
184
228
|
//# sourceMappingURL=azurePowerShellCredential.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"azurePowerShellCredential.js","sourceRoot":"","sources":["../../../src/credentials/azurePowerShellCredential.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EACL,aAAa,EACb,yBAAyB,EACzB,mCAAmC,GACpC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EAAE,+BAA+B,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGvF,OAAO,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,MAAM,GAAG,gBAAgB,CAAC,2BAA2B,CAAC,CAAC;AAE7D,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC;AAE/C;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,WAAmB;IAC/C,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,GAAG,WAAW,MAAM,CAAC;IAC9B,CAAC;SAAM,CAAC;QACN,OAAO,WAAW,CAAC;IACrB,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,WAAW,CAAC,QAAoB,EAAE,OAAgB;IAC/D,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,CAAC,IAAI,EAAE,GAAG,UAAU,CAAC,GAAG,OAAO,CAAC;QACtC,MAAM,MAAM,GAAG,CAAC,MAAM,YAAY,CAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE;YAC5D,QAAQ,EAAE,MAAM;YAChB,OAAO;SACR,CAAC,CAAW,CAAC;QACd,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,KAAK,EAAE,gCAAgC;IACvC,SAAS,EACP,uIAAuI;CAC1I,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG;IAC3C,KAAK,EACH,8FAA8F;IAChG,SAAS,EAAE,4KAA4K;IACvL,YAAY,EAAE,4FAA4F;CAC3G,CAAC;AAEF,mDAAmD;AACnD,MAAM,YAAY,GAA4C,CAAC,GAAU,EAAE,EAAE,CAC3E,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,KAAK,MAAM,CAAC,CAAC;AAEzD,qDAAqD;AACrD,MAAM,mBAAmB,GAA4C,CAAC,GAAU,EAAE,EAAE,CAClF,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;AAEhD;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;AAEpD,IAAI,SAAS,EAAE,CAAC;IACd,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC;AACjD,CAAC;AAED;;;;GAIG;AACH,MAAM,OAAO,yBAAyB;IAKpC;;;;;;;;;;OAUG;IACH,YAAY,OAA0C;QACpD,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,QAAQ,EAAE,CAAC;YACtB,aAAa,CAAC,MAAM,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,QAAQ,CAAC,CAAC;YACzC,IAAI,CAAC,QAAQ,GAAG,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,QAAQ,CAAC;QACpC,CAAC;QACD,IAAI,CAAC,4BAA4B,GAAG,mCAAmC,CACrE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,0BAA0B,CACpC,CAAC;QACF,IAAI,CAAC,OAAO,GAAG,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,kBAAkB,CAAC;IAC7C,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,6BAA6B,CACzC,QAAgB,EAChB,QAAiB,EACjB,OAAgB;QAEhB,uDAAuD;QACvD,KAAK,MAAM,iBAAiB,IAAI,CAAC,GAAG,YAAY,CAAC,EAAE,CAAC;YAClD,IAAI,CAAC;gBACH,MAAM,WAAW,CAAC,CAAC,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAC1D,CAAC;YAAC,OAAO,CAAM,EAAE,CAAC;gBAChB,gFAAgF;gBAChF,YAAY,CAAC,KAAK,EAAE,CAAC;gBACrB,SAAS;YACX,CAAC;YAED,IAAI,aAAa,GAAG,EAAE,CAAC;YACvB,IAAI,QAAQ,EAAE,CAAC;gBACb,aAAa,GAAG,cAAc,QAAQ,GAAG,CAAC;YAC5C,CAAC;YAED,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC;gBAChC;oBACE,iBAAiB;oBACjB,YAAY;oBACZ,iBAAiB;oBACjB,UAAU;oBACV,2DAA2D;iBAC5D;gBACD;oBACE,iBAAiB;oBACjB,YAAY;oBACZ,iBAAiB;oBACjB,UAAU;oBACV,qBAAqB,aAAa,kBAAkB,QAAQ,oBAAoB;iBACjF;aACF,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YAC1B,IAAI,CAAC;gBACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAC5B,CAAC;YAAC,OAAO,CAAM,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CAAC,8DAA8D,MAAM,EAAE,CAAC,CAAC;YAC1F,CAAC;QACH,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;IAC9F,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,QAAQ,CACnB,MAAyB,EACzB,UAA2B,EAAE;QAE7B,OAAO,aAAa,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,WAAW,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE;YACrF,MAAM,QAAQ,GAAG,yBAAyB,CACxC,IAAI,CAAC,QAAQ,EACb,OAAO,EACP,IAAI,CAAC,4BAA4B,CAClC,CAAC;YACF,MAAM,KAAK,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC9D,IAAI,QAAQ,EAAE,CAAC;gBACb,aAAa,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAClC,CAAC;YACD,IAAI,CAAC;gBACH,+BAA+B,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;gBAC/C,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,mBAAmB,KAAK,EAAE,CAAC,CAAC;gBACjD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;gBACzC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,6BAA6B,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC5F,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;gBAC5C,OAAO;oBACL,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,kBAAkB,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;iBAC3D,CAAC;YACJ,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,IAAI,mBAAmB,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC7B,MAAM,KAAK,GAAG,IAAI,0BAA0B,CAAC,6BAA6B,CAAC,SAAS,CAAC,CAAC;oBACtF,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;oBAChD,MAAM,KAAK,CAAC;gBACd,CAAC;qBAAM,IAAI,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC7B,MAAM,KAAK,GAAG,IAAI,0BAA0B,CAAC,6BAA6B,CAAC,KAAK,CAAC,CAAC;oBAClF,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;oBAChD,MAAM,KAAK,CAAC;gBACd,CAAC;gBACD,MAAM,KAAK,GAAG,IAAI,0BAA0B,CAC1C,GAAG,GAAG,KAAK,6BAA6B,CAAC,YAAY,EAAE,CACxD,CAAC;gBACF,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;gBAChD,MAAM,KAAK,CAAC;YACd,CAAC;QACH,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\";\nimport {\n checkTenantId,\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n} from \"../util/tenantIdUtils\";\nimport { credentialLogger, formatError, formatSuccess } from \"../util/logging\";\nimport { ensureValidScopeForDevTimeCreds, getScopeResource } from \"../util/scopeUtils\";\n\nimport { AzurePowerShellCredentialOptions } from \"./azurePowerShellCredentialOptions\";\nimport { CredentialUnavailableError } from \"../errors\";\nimport { processUtils } from \"../util/processUtils\";\nimport { tracingClient } from \"../util/tracing\";\n\nconst logger = credentialLogger(\"AzurePowerShellCredential\");\n\nconst isWindows = process.platform === \"win32\";\n\n/**\n * Returns a platform-appropriate command name by appending \".exe\" on Windows.\n *\n * @internal\n */\nexport function formatCommand(commandName: string): string {\n if (isWindows) {\n return `${commandName}.exe`;\n } else {\n return commandName;\n }\n}\n\n/**\n * Receives a list of commands to run, executes them, then returns the outputs.\n * If anything fails, an error is thrown.\n * @internal\n */\nasync function runCommands(commands: string[][], timeout?: number): Promise<string[]> {\n const results: string[] = [];\n\n for (const command of commands) {\n const [file, ...parameters] = command;\n const result = (await processUtils.execFile(file, parameters, {\n encoding: \"utf8\",\n timeout,\n })) as string;\n results.push(result);\n }\n\n return results;\n}\n\n/**\n * Known PowerShell errors\n * @internal\n */\nexport const powerShellErrors = {\n login: \"Run Connect-AzAccount to login\",\n installed:\n \"The specified module 'Az.Accounts' with version '2.2.0' was not loaded because no valid module file was found in any module directory\",\n};\n\n/**\n * Messages to use when throwing in this credential.\n * @internal\n */\nexport const powerShellPublicErrorMessages = {\n login:\n \"Please run 'Connect-AzAccount' from PowerShell to authenticate before using this credential.\",\n installed: `The 'Az.Account' module >= 2.2.0 is not installed. Install the Azure Az PowerShell module with: \"Install-Module -Name Az -Scope CurrentUser -Repository PSGallery -Force\".`,\n troubleshoot: `To troubleshoot, visit https://aka.ms/azsdk/js/identity/powershellcredential/troubleshoot.`,\n};\n\n// PowerShell Azure User not logged in error check.\nconst isLoginError: (err: Error) => RegExpMatchArray | null = (err: Error) =>\n err.message.match(`(.*)${powerShellErrors.login}(.*)`);\n\n// Az Module not Installed in Azure PowerShell check.\nconst isNotInstalledError: (err: Error) => RegExpMatchArray | null = (err: Error) =>\n err.message.match(powerShellErrors.installed);\n\n/**\n * The PowerShell commands to be tried, in order.\n *\n * @internal\n */\nexport const commandStack = [formatCommand(\"pwsh\")];\n\nif (isWindows) {\n commandStack.push(formatCommand(\"powershell\"));\n}\n\n/**\n * This credential will use the currently logged-in user information from the\n * Azure PowerShell module. To do so, it will read the user access token and\n * expire time with Azure PowerShell command `Get-AzAccessToken -ResourceUrl {ResourceScope}`\n */\nexport class AzurePowerShellCredential implements TokenCredential {\n private tenantId?: string;\n private additionallyAllowedTenantIds: string[];\n private timeout?: number;\n\n /**\n * Creates an instance of the {@link AzurePowerShellCredential}.\n *\n * To use this credential:\n * - Install the Azure Az PowerShell module with:\n * `Install-Module -Name Az -Scope CurrentUser -Repository PSGallery -Force`.\n * - You have already logged in to Azure PowerShell using the command\n * `Connect-AzAccount` from the command line.\n *\n * @param options - Options, to optionally allow multi-tenant requests.\n */\n constructor(options?: AzurePowerShellCredentialOptions) {\n if (options?.tenantId) {\n checkTenantId(logger, options?.tenantId);\n this.tenantId = options?.tenantId;\n }\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.additionallyAllowedTenants,\n );\n this.timeout = options?.processTimeoutInMs;\n }\n\n /**\n * Gets the access token from Azure PowerShell\n * @param resource - The resource to use when getting the token\n */\n private async getAzurePowerShellAccessToken(\n resource: string,\n tenantId?: string,\n timeout?: number,\n ): Promise<{ Token: string; ExpiresOn: string }> {\n // Clone the stack to avoid mutating it while iterating\n for (const powerShellCommand of [...commandStack]) {\n try {\n await runCommands([[powerShellCommand, \"/?\"]], timeout);\n } catch (e: any) {\n // Remove this credential from the original stack so that we don't try it again.\n commandStack.shift();\n continue;\n }\n\n let tenantSection = \"\";\n if (tenantId) {\n tenantSection = `-TenantId \"${tenantId}\"`;\n }\n\n const results = await runCommands([\n [\n powerShellCommand,\n \"-NoProfile\",\n \"-NonInteractive\",\n \"-Command\",\n \"Import-Module Az.Accounts -MinimumVersion 2.2.0 -PassThru\",\n ],\n [\n powerShellCommand,\n \"-NoProfile\",\n \"-NonInteractive\",\n \"-Command\",\n `Get-AzAccessToken ${tenantSection} -ResourceUrl \"${resource}\" | ConvertTo-Json`,\n ],\n ]);\n\n const result = results[1];\n try {\n return JSON.parse(result);\n } catch (e: any) {\n throw new Error(`Unable to parse the output of PowerShell. Received output: ${result}`);\n }\n }\n\n throw new Error(`Unable to execute PowerShell. Ensure that it is installed in your system`);\n }\n\n /**\n * Authenticates with Microsoft Entra ID and returns an access token if successful.\n * If the authentication cannot be performed through PowerShell, a {@link CredentialUnavailableError} will be thrown.\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 TokenCredential implementation might make.\n */\n public async getToken(\n scopes: string | string[],\n options: GetTokenOptions = {},\n ): Promise<AccessToken> {\n return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async () => {\n const tenantId = processMultiTenantRequest(\n this.tenantId,\n options,\n this.additionallyAllowedTenantIds,\n );\n const scope = typeof scopes === \"string\" ? scopes : scopes[0];\n if (tenantId) {\n checkTenantId(logger, tenantId);\n }\n try {\n ensureValidScopeForDevTimeCreds(scope, logger);\n logger.getToken.info(`Using the scope ${scope}`);\n const resource = getScopeResource(scope);\n const response = await this.getAzurePowerShellAccessToken(resource, tenantId, this.timeout);\n logger.getToken.info(formatSuccess(scopes));\n return {\n token: response.Token,\n expiresOnTimestamp: new Date(response.ExpiresOn).getTime(),\n };\n } catch (err: any) {\n if (isNotInstalledError(err)) {\n const error = new CredentialUnavailableError(powerShellPublicErrorMessages.installed);\n logger.getToken.info(formatError(scope, error));\n throw error;\n } else if (isLoginError(err)) {\n const error = new CredentialUnavailableError(powerShellPublicErrorMessages.login);\n logger.getToken.info(formatError(scope, error));\n throw error;\n }\n const error = new CredentialUnavailableError(\n `${err}. ${powerShellPublicErrorMessages.troubleshoot}`,\n );\n logger.getToken.info(formatError(scope, error));\n throw error;\n }\n });\n }\n}\n"]}
|
1
|
+
{"version":3,"file":"azurePowerShellCredential.js","sourceRoot":"","sources":["../../../src/credentials/azurePowerShellCredential.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport {\n checkTenantId,\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n} from \"../util/tenantIdUtils\";\nimport { credentialLogger, formatError, formatSuccess } from \"../util/logging\";\nimport { ensureValidScopeForDevTimeCreds, getScopeResource } from \"../util/scopeUtils\";\n\nimport { AzurePowerShellCredentialOptions } from \"./azurePowerShellCredentialOptions\";\nimport { CredentialUnavailableError } from \"../errors\";\nimport { processUtils } from \"../util/processUtils\";\nimport { tracingClient } from \"../util/tracing\";\n\nconst logger = credentialLogger(\"AzurePowerShellCredential\");\n\nconst isWindows = process.platform === \"win32\";\n\n/**\n * Returns a platform-appropriate command name by appending \".exe\" on Windows.\n *\n * @internal\n */\nexport function formatCommand(commandName: string): string {\n if (isWindows) {\n return `${commandName}.exe`;\n } else {\n return commandName;\n }\n}\n\n/**\n * Receives a list of commands to run, executes them, then returns the outputs.\n * If anything fails, an error is thrown.\n * @internal\n */\nasync function runCommands(commands: string[][], timeout?: number): Promise<string[]> {\n const results: string[] = [];\n\n for (const command of commands) {\n const [file, ...parameters] = command;\n const result = (await processUtils.execFile(file, parameters, {\n encoding: \"utf8\",\n timeout,\n })) as string;\n\n results.push(result);\n }\n\n return results;\n}\n\n/**\n * Known PowerShell errors\n * @internal\n */\nexport const powerShellErrors = {\n login: \"Run Connect-AzAccount to login\",\n installed:\n \"The specified module 'Az.Accounts' with version '2.2.0' was not loaded because no valid module file was found in any module directory\",\n};\n\n/**\n * Messages to use when throwing in this credential.\n * @internal\n */\nexport const powerShellPublicErrorMessages = {\n login:\n \"Please run 'Connect-AzAccount' from PowerShell to authenticate before using this credential.\",\n installed: `The 'Az.Account' module >= 2.2.0 is not installed. Install the Azure Az PowerShell module with: \"Install-Module -Name Az -Scope CurrentUser -Repository PSGallery -Force\".`,\n troubleshoot: `To troubleshoot, visit https://aka.ms/azsdk/js/identity/powershellcredential/troubleshoot.`,\n};\n\n// PowerShell Azure User not logged in error check.\nconst isLoginError: (err: Error) => RegExpMatchArray | null = (err: Error) =>\n err.message.match(`(.*)${powerShellErrors.login}(.*)`);\n\n// Az Module not Installed in Azure PowerShell check.\nconst isNotInstalledError: (err: Error) => RegExpMatchArray | null = (err: Error) =>\n err.message.match(powerShellErrors.installed);\n\n/**\n * The PowerShell commands to be tried, in order.\n *\n * @internal\n */\nexport const commandStack = [formatCommand(\"pwsh\")];\n\nif (isWindows) {\n commandStack.push(formatCommand(\"powershell\"));\n}\n\n/**\n * This credential will use the currently logged-in user information from the\n * Azure PowerShell module. To do so, it will read the user access token and\n * expire time with Azure PowerShell command `Get-AzAccessToken -ResourceUrl {ResourceScope}`\n */\nexport class AzurePowerShellCredential implements TokenCredential {\n private tenantId?: string;\n private additionallyAllowedTenantIds: string[];\n private timeout?: number;\n\n /**\n * Creates an instance of the {@link AzurePowerShellCredential}.\n *\n * To use this credential:\n * - Install the Azure Az PowerShell module with:\n * `Install-Module -Name Az -Scope CurrentUser -Repository PSGallery -Force`.\n * - You have already logged in to Azure PowerShell using the command\n * `Connect-AzAccount` from the command line.\n *\n * @param options - Options, to optionally allow multi-tenant requests.\n */\n constructor(options?: AzurePowerShellCredentialOptions) {\n if (options?.tenantId) {\n checkTenantId(logger, options?.tenantId);\n this.tenantId = options?.tenantId;\n }\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.additionallyAllowedTenants,\n );\n this.timeout = options?.processTimeoutInMs;\n }\n\n /**\n * Gets the access token from Azure PowerShell\n * @param resource - The resource to use when getting the token\n */\n private async getAzurePowerShellAccessToken(\n resource: string,\n tenantId?: string,\n timeout?: number,\n ): Promise<{ Token: string; ExpiresOn: string }> {\n // Clone the stack to avoid mutating it while iterating\n for (const powerShellCommand of [...commandStack]) {\n try {\n await runCommands([[powerShellCommand, \"/?\"]], timeout);\n } catch (e: any) {\n // Remove this credential from the original stack so that we don't try it again.\n commandStack.shift();\n continue;\n }\n\n const results = await runCommands([\n [\n powerShellCommand,\n \"-NoProfile\",\n \"-NonInteractive\",\n \"-Command\",\n `\n $tenantId = \"${tenantId ?? \"\"}\"\n $m = Import-Module Az.Accounts -MinimumVersion 2.2.0 -PassThru\n $useSecureString = $m.Version -ge [version]'2.17.0'\n\n $params = @{\n ResourceUrl = \"${resource}\"\n }\n\n if ($tenantId.Length -gt 0) {\n $params[\"TenantId\"] = $tenantId\n }\n\n if ($useSecureString) {\n $params[\"AsSecureString\"] = $true\n }\n\n $token = Get-AzAccessToken @params\n\n $result = New-Object -TypeName PSObject\n $result | Add-Member -MemberType NoteProperty -Name ExpiresOn -Value $token.ExpiresOn\n if ($useSecureString) {\n $result | Add-Member -MemberType NoteProperty -Name Token -Value (ConvertFrom-SecureString -AsPlainText $token.Token)\n } else {\n $result | Add-Member -MemberType NoteProperty -Name Token -Value $token.Token\n }\n\n Write-Output (ConvertTo-Json $result)\n `,\n ],\n ]);\n\n const result = results[0];\n return parseJsonToken(result);\n }\n throw new Error(`Unable to execute PowerShell. Ensure that it is installed in your system`);\n }\n\n /**\n * Authenticates with Microsoft Entra ID and returns an access token if successful.\n * If the authentication cannot be performed through PowerShell, a {@link CredentialUnavailableError} will be thrown.\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 TokenCredential implementation might make.\n */\n public async getToken(\n scopes: string | string[],\n options: GetTokenOptions = {},\n ): Promise<AccessToken> {\n return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async () => {\n const tenantId = processMultiTenantRequest(\n this.tenantId,\n options,\n this.additionallyAllowedTenantIds,\n );\n const scope = typeof scopes === \"string\" ? scopes : scopes[0];\n if (tenantId) {\n checkTenantId(logger, tenantId);\n }\n try {\n ensureValidScopeForDevTimeCreds(scope, logger);\n logger.getToken.info(`Using the scope ${scope}`);\n const resource = getScopeResource(scope);\n const response = await this.getAzurePowerShellAccessToken(resource, tenantId, this.timeout);\n logger.getToken.info(formatSuccess(scopes));\n return {\n token: response.Token,\n expiresOnTimestamp: new Date(response.ExpiresOn).getTime(),\n };\n } catch (err: any) {\n if (isNotInstalledError(err)) {\n const error = new CredentialUnavailableError(powerShellPublicErrorMessages.installed);\n logger.getToken.info(formatError(scope, error));\n throw error;\n } else if (isLoginError(err)) {\n const error = new CredentialUnavailableError(powerShellPublicErrorMessages.login);\n logger.getToken.info(formatError(scope, error));\n throw error;\n }\n const error = new CredentialUnavailableError(\n `${err}. ${powerShellPublicErrorMessages.troubleshoot}`,\n );\n logger.getToken.info(formatError(scope, error));\n throw error;\n }\n });\n }\n}\n\n/**\n *\n * @internal\n */\nexport async function parseJsonToken(\n result: string,\n): Promise<{ Token: string; ExpiresOn: string }> {\n const jsonRegex = /{[^{}]*}/g;\n const matches = result.match(jsonRegex);\n let resultWithoutToken = result;\n if (matches) {\n try {\n for (const item of matches) {\n try {\n const jsonContent = JSON.parse(item);\n if (jsonContent?.Token) {\n resultWithoutToken = resultWithoutToken.replace(item, \"\");\n if (resultWithoutToken) {\n logger.getToken.warning(resultWithoutToken);\n }\n return jsonContent;\n }\n } catch (e) {\n continue;\n }\n }\n } catch (e: any) {\n throw new Error(`Unable to parse the output of PowerShell. Received output: ${result}`);\n }\n }\n throw new Error(`No access token found in the output. Received output: ${result}`);\n}\n"]}
|
@@ -2,6 +2,7 @@
|
|
2
2
|
// Licensed under the MIT license.
|
3
3
|
import { createMsalClient } from "../msal/nodeFlows/msalClient";
|
4
4
|
import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, } from "../util/tenantIdUtils";
|
5
|
+
import { CredentialUnavailableError } from "../errors";
|
5
6
|
import { credentialLogger } from "../util/logging";
|
6
7
|
import { tracingClient } from "../util/tracing";
|
7
8
|
const logger = credentialLogger("ClientAssertionCredential");
|
@@ -20,8 +21,14 @@ export class ClientAssertionCredential {
|
|
20
21
|
* @param options - Options for configuring the client which makes the authentication request.
|
21
22
|
*/
|
22
23
|
constructor(tenantId, clientId, getAssertion, options = {}) {
|
23
|
-
if (!tenantId
|
24
|
-
throw new
|
24
|
+
if (!tenantId) {
|
25
|
+
throw new CredentialUnavailableError("ClientAssertionCredential: tenantId is a required parameter.");
|
26
|
+
}
|
27
|
+
if (!clientId) {
|
28
|
+
throw new CredentialUnavailableError("ClientAssertionCredential: clientId is a required parameter.");
|
29
|
+
}
|
30
|
+
if (!getAssertion) {
|
31
|
+
throw new CredentialUnavailableError("ClientAssertionCredential: clientAssertion is a required parameter.");
|
25
32
|
}
|
26
33
|
this.tenantId = tenantId;
|
27
34
|
this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants);
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"clientAssertionCredential.js","sourceRoot":"","sources":["../../../src/credentials/clientAssertionCredential.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EAAc,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EACL,yBAAyB,EACzB,mCAAmC,GACpC,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,MAAM,GAAG,gBAAgB,CAAC,2BAA2B,CAAC,CAAC;AAE7D;;GAEG;AACH,MAAM,OAAO,yBAAyB;IAOpC;;;;;;;;;OASG;IACH,YACE,QAAgB,EAChB,QAAgB,EAChB,YAAmC,EACnC,UAA4C,EAAE;QAE9C,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAY,EAAE,CAAC;
|
1
|
+
{"version":3,"file":"clientAssertionCredential.js","sourceRoot":"","sources":["../../../src/credentials/clientAssertionCredential.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EAAc,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EACL,yBAAyB,EACzB,mCAAmC,GACpC,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,MAAM,GAAG,gBAAgB,CAAC,2BAA2B,CAAC,CAAC;AAE7D;;GAEG;AACH,MAAM,OAAO,yBAAyB;IAOpC;;;;;;;;;OASG;IACH,YACE,QAAgB,EAChB,QAAgB,EAChB,YAAmC,EACnC,UAA4C,EAAE;QAE9C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,0BAA0B,CAClC,8DAA8D,CAC/D,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,0BAA0B,CAClC,8DAA8D,CAC/D,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,0BAA0B,CAClC,qEAAqE,CACtE,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,4BAA4B,GAAG,mCAAmC,CACrE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,0BAA0B,CACpC,CAAC;QAEF,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,UAAU,GAAG,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,kCAChD,OAAO,KACV,MAAM,EACN,sBAAsB,EAAE,IAAI,CAAC,OAAO,IACpC,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,QAAQ,CAAC,MAAyB,EAAE,UAA2B,EAAE;QACrE,OAAO,aAAa,CAAC,QAAQ,CAC3B,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,WAAW,EACnC,OAAO,EACP,KAAK,EAAE,UAAU,EAAE,EAAE;YACnB,UAAU,CAAC,QAAQ,GAAG,yBAAyB,CAC7C,IAAI,CAAC,QAAQ,EACb,UAAU,EACV,IAAI,CAAC,4BAA4B,EACjC,MAAM,CACP,CAAC;YAEF,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC9D,OAAO,IAAI,CAAC,UAAU,CAAC,yBAAyB,CAC9C,WAAW,EACX,IAAI,CAAC,YAAY,EACjB,UAAU,CACX,CAAC;QACJ,CAAC,CACF,CAAC;IACJ,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport { MsalClient, createMsalClient } from \"../msal/nodeFlows/msalClient\";\nimport {\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n} from \"../util/tenantIdUtils\";\n\nimport { ClientAssertionCredentialOptions } from \"./clientAssertionCredentialOptions\";\nimport { CredentialUnavailableError } from \"../errors\";\nimport { credentialLogger } from \"../util/logging\";\nimport { tracingClient } from \"../util/tracing\";\n\nconst logger = credentialLogger(\"ClientAssertionCredential\");\n\n/**\n * Authenticates a service principal with a JWT assertion.\n */\nexport class ClientAssertionCredential implements TokenCredential {\n private msalClient: MsalClient;\n private tenantId: string;\n private additionallyAllowedTenantIds: string[];\n private getAssertion: () => Promise<string>;\n private options: ClientAssertionCredentialOptions;\n\n /**\n * Creates an instance of the ClientAssertionCredential with the details\n * needed to authenticate against Microsoft Entra ID with a client\n * assertion provided by the developer through the `getAssertion` function parameter.\n *\n * @param tenantId - The Microsoft Entra tenant (directory) ID.\n * @param clientId - The client (application) ID of an App Registration in the tenant.\n * @param getAssertion - A function that retrieves the assertion for the credential to use.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n getAssertion: () => Promise<string>,\n options: ClientAssertionCredentialOptions = {},\n ) {\n if (!tenantId) {\n throw new CredentialUnavailableError(\n \"ClientAssertionCredential: tenantId is a required parameter.\",\n );\n }\n\n if (!clientId) {\n throw new CredentialUnavailableError(\n \"ClientAssertionCredential: clientId is a required parameter.\",\n );\n }\n\n if (!getAssertion) {\n throw new CredentialUnavailableError(\n \"ClientAssertionCredential: clientAssertion is a required parameter.\",\n );\n }\n this.tenantId = tenantId;\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.additionallyAllowedTenants,\n );\n\n this.options = options;\n this.getAssertion = getAssertion;\n this.msalClient = createMsalClient(clientId, tenantId, {\n ...options,\n logger,\n tokenCredentialOptions: this.options,\n });\n }\n\n /**\n * Authenticates with Microsoft Entra ID 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 any requests this\n * TokenCredential implementation might make.\n */\n async getToken(scopes: string | string[], options: GetTokenOptions = {}): Promise<AccessToken> {\n return tracingClient.withSpan(\n `${this.constructor.name}.getToken`,\n options,\n async (newOptions) => {\n newOptions.tenantId = processMultiTenantRequest(\n this.tenantId,\n newOptions,\n this.additionallyAllowedTenantIds,\n logger,\n );\n\n const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];\n return this.msalClient.getTokenByClientAssertion(\n arrayScopes,\n this.getAssertion,\n newOptions,\n );\n },\n );\n }\n}\n"]}
|
@@ -56,7 +56,8 @@ export class ClientCertificateCredential {
|
|
56
56
|
});
|
57
57
|
}
|
58
58
|
async buildClientCertificate() {
|
59
|
-
|
59
|
+
var _a;
|
60
|
+
const parts = await parseCertificate(this.certificateConfiguration, (_a = this.sendCertificateChain) !== null && _a !== void 0 ? _a : false);
|
60
61
|
let privateKey;
|
61
62
|
if (this.certificateConfiguration.certificatePassword !== undefined) {
|
62
63
|
privateKey = createPrivateKey({
|
@@ -79,33 +80,40 @@ export class ClientCertificateCredential {
|
|
79
80
|
x5c: parts.x5c,
|
80
81
|
};
|
81
82
|
}
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
83
|
+
}
|
84
|
+
/**
|
85
|
+
* Parses a certificate into its relevant parts
|
86
|
+
*
|
87
|
+
* @param certificateConfiguration - The certificate contents or path to the certificate
|
88
|
+
* @param sendCertificateChain - true if the entire certificate chain should be sent for SNI, false otherwise
|
89
|
+
* @returns The parsed certificate parts and the certificate contents
|
90
|
+
*/
|
91
|
+
export async function parseCertificate(certificateConfiguration, sendCertificateChain) {
|
92
|
+
const certificate = certificateConfiguration.certificate;
|
93
|
+
const certificatePath = certificateConfiguration.certificatePath;
|
94
|
+
const certificateContents = certificate || (await readFile(certificatePath, "utf8"));
|
95
|
+
const x5c = sendCertificateChain ? certificateContents : undefined;
|
96
|
+
const certificatePattern = /(-+BEGIN CERTIFICATE-+)(\n\r?|\r\n?)([A-Za-z0-9+/\n\r]+=*)(\n\r?|\r\n?)(-+END CERTIFICATE-+)/g;
|
97
|
+
const publicKeys = [];
|
98
|
+
// Match all possible certificates, in the order they are in the file. These will form the chain that is used for x5c
|
99
|
+
let match;
|
100
|
+
do {
|
101
|
+
match = certificatePattern.exec(certificateContents);
|
102
|
+
if (match) {
|
103
|
+
publicKeys.push(match[3]);
|
99
104
|
}
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
.toUpperCase();
|
104
|
-
return {
|
105
|
-
certificateContents,
|
106
|
-
thumbprint,
|
107
|
-
x5c,
|
108
|
-
};
|
105
|
+
} while (match);
|
106
|
+
if (publicKeys.length === 0) {
|
107
|
+
throw new Error("The file at the specified path does not contain a PEM-encoded certificate.");
|
109
108
|
}
|
109
|
+
const thumbprint = createHash("sha1")
|
110
|
+
.update(Buffer.from(publicKeys[0], "base64"))
|
111
|
+
.digest("hex")
|
112
|
+
.toUpperCase();
|
113
|
+
return {
|
114
|
+
certificateContents,
|
115
|
+
thumbprint,
|
116
|
+
x5c,
|
117
|
+
};
|
110
118
|
}
|
111
119
|
//# sourceMappingURL=clientCertificateCredential.js.map
|