@azure/identity 4.5.0-beta.1 → 4.5.0-beta.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -1,12 +1,13 @@
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
2
2
|
// Licensed under the MIT license.
|
3
|
-
import {
|
3
|
+
import { createMsalClient } from "../msal/nodeFlows/msalClient";
|
4
4
|
import { credentialLogger, formatError } from "../util/logging";
|
5
|
+
import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, } from "../util/tenantIdUtils";
|
6
|
+
import { CredentialUnavailableError } from "../errors";
|
7
|
+
import { createHash } from "node:crypto";
|
5
8
|
import { ensureScopes } from "../util/scopeUtils";
|
6
|
-
import { tracingClient } from "../util/tracing";
|
7
|
-
import { createMsalClient } from "../msal/nodeFlows/msalClient";
|
8
9
|
import { readFile } from "node:fs/promises";
|
9
|
-
import {
|
10
|
+
import { tracingClient } from "../util/tracing";
|
10
11
|
const credentialName = "OnBehalfOfCredential";
|
11
12
|
const logger = credentialLogger(credentialName);
|
12
13
|
/**
|
@@ -18,11 +19,17 @@ export class OnBehalfOfCredential {
|
|
18
19
|
const { certificatePath, sendCertificateChain } = options;
|
19
20
|
const { getAssertion } = options;
|
20
21
|
const { tenantId, clientId, userAssertionToken, additionallyAllowedTenants: additionallyAllowedTenantIds, } = options;
|
21
|
-
if (!tenantId
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
throw new
|
22
|
+
if (!tenantId) {
|
23
|
+
throw new CredentialUnavailableError(`${credentialName}: tenantId is a required parameter. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`);
|
24
|
+
}
|
25
|
+
if (!clientId) {
|
26
|
+
throw new CredentialUnavailableError(`${credentialName}: clientId is a required parameter. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`);
|
27
|
+
}
|
28
|
+
if (!clientSecret && !certificatePath && !getAssertion) {
|
29
|
+
throw new CredentialUnavailableError(`${credentialName}: You must provide one of clientSecret, certificatePath, or a getAssertion callback but none were provided. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`);
|
30
|
+
}
|
31
|
+
if (!userAssertionToken) {
|
32
|
+
throw new CredentialUnavailableError(`${credentialName}: userAssertionToken is a required parameter. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`);
|
26
33
|
}
|
27
34
|
this.certificatePath = certificatePath;
|
28
35
|
this.clientSecret = clientSecret;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"onBehalfOfCredential.js","sourceRoot":"","sources":["../../../src/credentials/onBehalfOfCredential.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 OnBehalfOfCredentialAssertionOptions,\n OnBehalfOfCredentialCertificateOptions,\n OnBehalfOfCredentialOptions,\n OnBehalfOfCredentialSecretOptions,\n} from \"./onBehalfOfCredentialOptions\";\nimport {\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n} from \"../util/tenantIdUtils\";\nimport { CredentialPersistenceOptions } from \"./credentialPersistenceOptions\";\nimport { MultiTenantTokenCredentialOptions } from \"./multiTenantTokenCredentialOptions\";\nimport { credentialLogger, formatError } from \"../util/logging\";\nimport { ensureScopes } from \"../util/scopeUtils\";\nimport { tracingClient } from \"../util/tracing\";\nimport { MsalClient, createMsalClient } from \"../msal/nodeFlows/msalClient\";\nimport { CertificateParts } from \"../msal/types\";\nimport { ClientCertificatePEMCertificatePath } from \"./clientCertificateCredential\";\nimport { readFile } from \"node:fs/promises\";\nimport { createHash } from \"node:crypto\";\n\nconst credentialName = \"OnBehalfOfCredential\";\nconst logger = credentialLogger(credentialName);\n\n/**\n * Enables authentication to Microsoft Entra ID using the [On Behalf Of flow](https://learn.microsoft.com/entra/identity-platform/v2-oauth2-on-behalf-of-flow).\n */\nexport class OnBehalfOfCredential implements TokenCredential {\n private tenantId: string;\n private additionallyAllowedTenantIds: string[];\n private msalClient: MsalClient;\n private sendCertificateChain?: boolean;\n private certificatePath?: string;\n private clientSecret?: string;\n private userAssertionToken: string;\n private clientAssertion?: () => Promise<string>;\n\n /**\n * Creates an instance of the {@link OnBehalfOfCredential} with the details\n * needed to authenticate against Microsoft Entra ID with path to a PEM certificate,\n * 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 * 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(\n options: OnBehalfOfCredentialCertificateOptions &\n MultiTenantTokenCredentialOptions &\n CredentialPersistenceOptions,\n );\n /**\n * Creates an instance of the {@link OnBehalfOfCredential} with the details\n * needed to authenticate against Microsoft Entra ID with a client\n * secret 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,\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(\n options: OnBehalfOfCredentialSecretOptions &\n MultiTenantTokenCredentialOptions &\n CredentialPersistenceOptions,\n );\n\n /**\n * Creates an instance of the {@link OnBehalfOfCredential} with the details\n * needed to authenticate against Microsoft Entra ID with a client `getAssertion`\n * 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 * getAssertion: () => { return Promise.resolve(\"my-jwt\")},\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(\n options: OnBehalfOfCredentialAssertionOptions &\n MultiTenantTokenCredentialOptions &\n CredentialPersistenceOptions,\n );\n\n constructor(options: OnBehalfOfCredentialOptions) {\n const { clientSecret } = options as OnBehalfOfCredentialSecretOptions;\n const { certificatePath, sendCertificateChain } =\n options as OnBehalfOfCredentialCertificateOptions;\n const { getAssertion } = options as OnBehalfOfCredentialAssertionOptions;\n const {\n tenantId,\n clientId,\n userAssertionToken,\n additionallyAllowedTenants: additionallyAllowedTenantIds,\n } = options;\n if (\n !tenantId ||\n !clientId ||\n !(clientSecret || certificatePath || getAssertion) ||\n !userAssertionToken\n ) {\n throw new Error(\n `${credentialName}: tenantId, clientId, clientSecret (or certificatePath or getAssertion) and userAssertionToken are required parameters.`,\n );\n }\n this.certificatePath = certificatePath;\n this.clientSecret = clientSecret;\n this.userAssertionToken = userAssertionToken;\n this.sendCertificateChain = sendCertificateChain;\n this.clientAssertion = getAssertion;\n\n this.tenantId = tenantId;\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n additionallyAllowedTenantIds,\n );\n\n this.msalClient = createMsalClient(clientId, this.tenantId, {\n ...options,\n logger,\n tokenCredentialOptions: 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 the underlying network requests.\n */\n async getToken(scopes: string | string[], options: GetTokenOptions = {}): Promise<AccessToken> {\n return tracingClient.withSpan(`${credentialName}.getToken`, options, async (newOptions) => {\n newOptions.tenantId = processMultiTenantRequest(\n this.tenantId,\n newOptions,\n this.additionallyAllowedTenantIds,\n logger,\n );\n\n const arrayScopes = ensureScopes(scopes);\n if (this.certificatePath) {\n const clientCertificate = await this.buildClientCertificate(this.certificatePath);\n\n return this.msalClient.getTokenOnBehalfOf(\n arrayScopes,\n this.userAssertionToken,\n clientCertificate,\n newOptions,\n );\n } else if (this.clientSecret) {\n return this.msalClient.getTokenOnBehalfOf(\n arrayScopes,\n this.userAssertionToken,\n this.clientSecret,\n options,\n );\n } else if (this.clientAssertion) {\n return this.msalClient.getTokenOnBehalfOf(\n arrayScopes,\n this.userAssertionToken,\n this.clientAssertion,\n options,\n );\n } else {\n // this is an invalid scenario and is a bug, as the constructor should have thrown an error if neither clientSecret nor certificatePath nor clientAssertion were provided\n throw new Error(\n \"Expected either clientSecret or certificatePath or clientAssertion to be defined.\",\n );\n }\n });\n }\n\n private async buildClientCertificate(certificatePath: string): Promise<CertificateParts> {\n try {\n const parts = await this.parseCertificate({ certificatePath }, this.sendCertificateChain);\n return {\n thumbprint: parts.thumbprint,\n privateKey: parts.certificateContents,\n x5c: parts.x5c,\n };\n } catch (error: any) {\n logger.info(formatError(\"\", error));\n throw error;\n }\n }\n\n private async parseCertificate(\n configuration: ClientCertificatePEMCertificatePath,\n sendCertificateChain?: boolean,\n ): Promise<Omit<CertificateParts, \"privateKey\"> & { certificateContents: string }> {\n const certificatePath = configuration.certificatePath;\n const certificateContents = await readFile(certificatePath, \"utf8\");\n const x5c = sendCertificateChain ? certificateContents : undefined;\n\n const certificatePattern =\n /(-+BEGIN CERTIFICATE-+)(\\n\\r?|\\r\\n?)([A-Za-z0-9+/\\n\\r]+=*)(\\n\\r?|\\r\\n?)(-+END CERTIFICATE-+)/g;\n const publicKeys: string[] = [];\n\n // Match all possible certificates, in the order they are in the file. These will form the chain that is used for x5c\n let match;\n do {\n match = certificatePattern.exec(certificateContents);\n if (match) {\n publicKeys.push(match[3]);\n }\n } while (match);\n\n if (publicKeys.length === 0) {\n throw new Error(\"The file at the specified path does not contain a PEM-encoded certificate.\");\n }\n\n const thumbprint = createHash(\"sha1\")\n .update(Buffer.from(publicKeys[0], \"base64\"))\n .digest(\"hex\")\n .toUpperCase();\n\n return {\n certificateContents,\n thumbprint,\n x5c,\n };\n }\n}\n"]}
|
1
|
+
{"version":3,"file":"onBehalfOfCredential.js","sourceRoot":"","sources":["../../../src/credentials/onBehalfOfCredential.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 { MsalClient, createMsalClient } from \"../msal/nodeFlows/msalClient\";\nimport {\n OnBehalfOfCredentialAssertionOptions,\n OnBehalfOfCredentialCertificateOptions,\n OnBehalfOfCredentialOptions,\n OnBehalfOfCredentialSecretOptions,\n} from \"./onBehalfOfCredentialOptions\";\nimport { credentialLogger, formatError } from \"../util/logging\";\nimport {\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n} from \"../util/tenantIdUtils\";\n\nimport { CertificateParts } from \"../msal/types\";\nimport { ClientCertificatePEMCertificatePath } from \"./clientCertificateCredential\";\nimport { CredentialPersistenceOptions } from \"./credentialPersistenceOptions\";\nimport { CredentialUnavailableError } from \"../errors\";\nimport { MultiTenantTokenCredentialOptions } from \"./multiTenantTokenCredentialOptions\";\nimport { createHash } from \"node:crypto\";\nimport { ensureScopes } from \"../util/scopeUtils\";\nimport { readFile } from \"node:fs/promises\";\nimport { tracingClient } from \"../util/tracing\";\n\nconst credentialName = \"OnBehalfOfCredential\";\nconst logger = credentialLogger(credentialName);\n\n/**\n * Enables authentication to Microsoft Entra ID using the [On Behalf Of flow](https://learn.microsoft.com/entra/identity-platform/v2-oauth2-on-behalf-of-flow).\n */\nexport class OnBehalfOfCredential implements TokenCredential {\n private tenantId: string;\n private additionallyAllowedTenantIds: string[];\n private msalClient: MsalClient;\n private sendCertificateChain?: boolean;\n private certificatePath?: string;\n private clientSecret?: string;\n private userAssertionToken: string;\n private clientAssertion?: () => Promise<string>;\n\n /**\n * Creates an instance of the {@link OnBehalfOfCredential} with the details\n * needed to authenticate against Microsoft Entra ID with path to a PEM certificate,\n * 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 * 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(\n options: OnBehalfOfCredentialCertificateOptions &\n MultiTenantTokenCredentialOptions &\n CredentialPersistenceOptions,\n );\n /**\n * Creates an instance of the {@link OnBehalfOfCredential} with the details\n * needed to authenticate against Microsoft Entra ID with a client\n * secret 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,\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(\n options: OnBehalfOfCredentialSecretOptions &\n MultiTenantTokenCredentialOptions &\n CredentialPersistenceOptions,\n );\n\n /**\n * Creates an instance of the {@link OnBehalfOfCredential} with the details\n * needed to authenticate against Microsoft Entra ID with a client `getAssertion`\n * 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 * getAssertion: () => { return Promise.resolve(\"my-jwt\")},\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(\n options: OnBehalfOfCredentialAssertionOptions &\n MultiTenantTokenCredentialOptions &\n CredentialPersistenceOptions,\n );\n\n constructor(options: OnBehalfOfCredentialOptions) {\n const { clientSecret } = options as OnBehalfOfCredentialSecretOptions;\n const { certificatePath, sendCertificateChain } =\n options as OnBehalfOfCredentialCertificateOptions;\n const { getAssertion } = options as OnBehalfOfCredentialAssertionOptions;\n const {\n tenantId,\n clientId,\n userAssertionToken,\n additionallyAllowedTenants: additionallyAllowedTenantIds,\n } = options;\n if (!tenantId) {\n throw new CredentialUnavailableError(\n `${credentialName}: tenantId is a required parameter. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`,\n );\n }\n\n if (!clientId) {\n throw new CredentialUnavailableError(\n `${credentialName}: clientId is a required parameter. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`,\n );\n }\n\n if (!clientSecret && !certificatePath && !getAssertion) {\n throw new CredentialUnavailableError(\n `${credentialName}: You must provide one of clientSecret, certificatePath, or a getAssertion callback but none were provided. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`,\n );\n }\n\n if (!userAssertionToken) {\n throw new CredentialUnavailableError(\n `${credentialName}: userAssertionToken is a required parameter. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`,\n );\n }\n this.certificatePath = certificatePath;\n this.clientSecret = clientSecret;\n this.userAssertionToken = userAssertionToken;\n this.sendCertificateChain = sendCertificateChain;\n this.clientAssertion = getAssertion;\n\n this.tenantId = tenantId;\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n additionallyAllowedTenantIds,\n );\n\n this.msalClient = createMsalClient(clientId, this.tenantId, {\n ...options,\n logger,\n tokenCredentialOptions: 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 the underlying network requests.\n */\n async getToken(scopes: string | string[], options: GetTokenOptions = {}): Promise<AccessToken> {\n return tracingClient.withSpan(`${credentialName}.getToken`, options, async (newOptions) => {\n newOptions.tenantId = processMultiTenantRequest(\n this.tenantId,\n newOptions,\n this.additionallyAllowedTenantIds,\n logger,\n );\n\n const arrayScopes = ensureScopes(scopes);\n if (this.certificatePath) {\n const clientCertificate = await this.buildClientCertificate(this.certificatePath);\n\n return this.msalClient.getTokenOnBehalfOf(\n arrayScopes,\n this.userAssertionToken,\n clientCertificate,\n newOptions,\n );\n } else if (this.clientSecret) {\n return this.msalClient.getTokenOnBehalfOf(\n arrayScopes,\n this.userAssertionToken,\n this.clientSecret,\n options,\n );\n } else if (this.clientAssertion) {\n return this.msalClient.getTokenOnBehalfOf(\n arrayScopes,\n this.userAssertionToken,\n this.clientAssertion,\n options,\n );\n } else {\n // this is an invalid scenario and is a bug, as the constructor should have thrown an error if neither clientSecret nor certificatePath nor clientAssertion were provided\n throw new Error(\n \"Expected either clientSecret or certificatePath or clientAssertion to be defined.\",\n );\n }\n });\n }\n\n private async buildClientCertificate(certificatePath: string): Promise<CertificateParts> {\n try {\n const parts = await this.parseCertificate({ certificatePath }, this.sendCertificateChain);\n return {\n thumbprint: parts.thumbprint,\n privateKey: parts.certificateContents,\n x5c: parts.x5c,\n };\n } catch (error: any) {\n logger.info(formatError(\"\", error));\n throw error;\n }\n }\n\n private async parseCertificate(\n configuration: ClientCertificatePEMCertificatePath,\n sendCertificateChain?: boolean,\n ): Promise<Omit<CertificateParts, \"privateKey\"> & { certificateContents: string }> {\n const certificatePath = configuration.certificatePath;\n const certificateContents = await readFile(certificatePath, \"utf8\");\n const x5c = sendCertificateChain ? certificateContents : undefined;\n\n const certificatePattern =\n /(-+BEGIN CERTIFICATE-+)(\\n\\r?|\\r\\n?)([A-Za-z0-9+/\\n\\r]+=*)(\\n\\r?|\\r\\n?)(-+END CERTIFICATE-+)/g;\n const publicKeys: string[] = [];\n\n // Match all possible certificates, in the order they are in the file. These will form the chain that is used for x5c\n let match;\n do {\n match = certificatePattern.exec(certificateContents);\n if (match) {\n publicKeys.push(match[3]);\n }\n } while (match);\n\n if (publicKeys.length === 0) {\n throw new Error(\"The file at the specified path does not contain a PEM-encoded certificate.\");\n }\n\n const thumbprint = createHash(\"sha1\")\n .update(Buffer.from(publicKeys[0], \"base64\"))\n .digest(\"hex\")\n .toUpperCase();\n\n return {\n certificateContents,\n thumbprint,\n x5c,\n };\n }\n}\n"]}
|
@@ -1,10 +1,11 @@
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
2
2
|
// Licensed under the MIT license.
|
3
|
+
import { createMsalClient } from "../msal/nodeFlows/msalClient";
|
3
4
|
import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, } from "../util/tenantIdUtils";
|
5
|
+
import { CredentialUnavailableError } from "../errors";
|
4
6
|
import { credentialLogger } from "../util/logging";
|
5
7
|
import { ensureScopes } from "../util/scopeUtils";
|
6
8
|
import { tracingClient } from "../util/tracing";
|
7
|
-
import { createMsalClient } from "../msal/nodeFlows/msalClient";
|
8
9
|
const logger = credentialLogger("UsernamePasswordCredential");
|
9
10
|
/**
|
10
11
|
* Enables authentication to Microsoft Entra ID with a user's
|
@@ -25,8 +26,17 @@ export class UsernamePasswordCredential {
|
|
25
26
|
* @param options - Options for configuring the client which makes the authentication request.
|
26
27
|
*/
|
27
28
|
constructor(tenantId, clientId, username, password, options = {}) {
|
28
|
-
if (!tenantId
|
29
|
-
throw new
|
29
|
+
if (!tenantId) {
|
30
|
+
throw new CredentialUnavailableError("UsernamePasswordCredential: tenantId is a required parameter. To troubleshoot, visit https://aka.ms/azsdk/js/identity/usernamepasswordcredential/troubleshoot.");
|
31
|
+
}
|
32
|
+
if (!clientId) {
|
33
|
+
throw new CredentialUnavailableError("UsernamePasswordCredential: clientId is a required parameter. To troubleshoot, visit https://aka.ms/azsdk/js/identity/usernamepasswordcredential/troubleshoot.");
|
34
|
+
}
|
35
|
+
if (!username) {
|
36
|
+
throw new CredentialUnavailableError("UsernamePasswordCredential: username is a required parameter. To troubleshoot, visit https://aka.ms/azsdk/js/identity/usernamepasswordcredential/troubleshoot.");
|
37
|
+
}
|
38
|
+
if (!password) {
|
39
|
+
throw new CredentialUnavailableError("UsernamePasswordCredential: password is a required parameter. To troubleshoot, visit https://aka.ms/azsdk/js/identity/usernamepasswordcredential/troubleshoot.");
|
30
40
|
}
|
31
41
|
this.tenantId = tenantId;
|
32
42
|
this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants);
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"usernamePasswordCredential.js","sourceRoot":"","sources":["../../../src/credentials/usernamePasswordCredential.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EACL,yBAAyB,EACzB,mCAAmC,GACpC,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,
|
1
|
+
{"version":3,"file":"usernamePasswordCredential.js","sourceRoot":"","sources":["../../../src/credentials/usernamePasswordCredential.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;AAE/B,OAAO,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AAEvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,MAAM,GAAG,gBAAgB,CAAC,4BAA4B,CAAC,CAAC;AAE9D;;;;;GAKG;AACH,MAAM,OAAO,0BAA0B;IAOrC;;;;;;;;;;OAUG;IACH,YACE,QAAgB,EAChB,QAAgB,EAChB,QAAgB,EAChB,QAAgB,EAChB,UAA6C,EAAE;QAE/C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,0BAA0B,CAClC,gKAAgK,CACjK,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,0BAA0B,CAClC,gKAAgK,CACjK,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,0BAA0B,CAClC,gKAAgK,CACjK,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,0BAA0B,CAClC,gKAAgK,CACjK,CAAC;QACJ,CAAC;QAED,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,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAEzB,IAAI,CAAC,UAAU,GAAG,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,kCACrD,OAAO,KACV,sBAAsB,EAAE,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,EAAE,IACrC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;OAWG;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,YAAY,CAAC,MAAM,CAAC,CAAC;YACzC,OAAO,IAAI,CAAC,UAAU,CAAC,0BAA0B,CAC/C,WAAW,EACX,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,QAAQ,EACb,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 { CredentialUnavailableError } from \"../errors\";\nimport { UsernamePasswordCredentialOptions } from \"./usernamePasswordCredentialOptions\";\nimport { credentialLogger } from \"../util/logging\";\nimport { ensureScopes } from \"../util/scopeUtils\";\nimport { tracingClient } from \"../util/tracing\";\n\nconst logger = credentialLogger(\"UsernamePasswordCredential\");\n\n/**\n * Enables authentication to Microsoft Entra ID with a user's\n * username and password. This credential requires a high degree of\n * trust so you should only use it when other, more secure credential\n * types can't be used.\n */\nexport class UsernamePasswordCredential implements TokenCredential {\n private tenantId: string;\n private additionallyAllowedTenantIds: string[];\n private msalClient: MsalClient;\n private username: string;\n private password: string;\n\n /**\n * Creates an instance of the UsernamePasswordCredential with the details\n * needed to authenticate against Microsoft Entra ID with a username\n * and password.\n *\n * @param tenantId - The Microsoft Entra tenant (directory).\n * @param clientId - The client (application) ID of an App Registration in the tenant.\n * @param username - The user account's e-mail address (user name).\n * @param password - The user account's account password\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n username: string,\n password: string,\n options: UsernamePasswordCredentialOptions = {},\n ) {\n if (!tenantId) {\n throw new CredentialUnavailableError(\n \"UsernamePasswordCredential: tenantId is a required parameter. To troubleshoot, visit https://aka.ms/azsdk/js/identity/usernamepasswordcredential/troubleshoot.\",\n );\n }\n\n if (!clientId) {\n throw new CredentialUnavailableError(\n \"UsernamePasswordCredential: clientId is a required parameter. To troubleshoot, visit https://aka.ms/azsdk/js/identity/usernamepasswordcredential/troubleshoot.\",\n );\n }\n\n if (!username) {\n throw new CredentialUnavailableError(\n \"UsernamePasswordCredential: username is a required parameter. To troubleshoot, visit https://aka.ms/azsdk/js/identity/usernamepasswordcredential/troubleshoot.\",\n );\n }\n\n if (!password) {\n throw new CredentialUnavailableError(\n \"UsernamePasswordCredential: password is a required parameter. To troubleshoot, visit https://aka.ms/azsdk/js/identity/usernamepasswordcredential/troubleshoot.\",\n );\n }\n\n this.tenantId = tenantId;\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.additionallyAllowedTenants,\n );\n\n this.username = username;\n this.password = password;\n\n this.msalClient = createMsalClient(clientId, this.tenantId, {\n ...options,\n tokenCredentialOptions: 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 * 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 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 = ensureScopes(scopes);\n return this.msalClient.getTokenByUsernamePassword(\n arrayScopes,\n this.username,\n this.password,\n newOptions,\n );\n },\n );\n }\n}\n"]}
|
@@ -1,10 +1,10 @@
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
2
2
|
// Licensed under the MIT license.
|
3
|
+
import { credentialLogger, processEnvVars } from "../util/logging";
|
3
4
|
import { ClientAssertionCredential } from "./clientAssertionCredential";
|
4
|
-
import { readFile } from "fs/promises";
|
5
5
|
import { CredentialUnavailableError } from "../errors";
|
6
|
-
import { credentialLogger, processEnvVars } from "../util/logging";
|
7
6
|
import { checkTenantId } from "../util/tenantIdUtils";
|
7
|
+
import { readFile } from "fs/promises";
|
8
8
|
const credentialName = "WorkloadIdentityCredential";
|
9
9
|
/**
|
10
10
|
* Contains the list of all supported environment variable names so that an
|
@@ -53,10 +53,20 @@ export class WorkloadIdentityCredential {
|
|
53
53
|
if (tenantId) {
|
54
54
|
checkTenantId(logger, tenantId);
|
55
55
|
}
|
56
|
-
if (clientId
|
57
|
-
|
58
|
-
|
56
|
+
if (!clientId) {
|
57
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. clientId is a required parameter. In DefaultAzureCredential and ManagedIdentityCredential, this can be provided as an environment variable - "AZURE_CLIENT_ID".
|
58
|
+
See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`);
|
59
|
+
}
|
60
|
+
if (!tenantId) {
|
61
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. tenantId is a required parameter. In DefaultAzureCredential and ManagedIdentityCredential, this can be provided as an environment variable - "AZURE_TENANT_ID".
|
62
|
+
See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`);
|
63
|
+
}
|
64
|
+
if (!this.federatedTokenFilePath) {
|
65
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. federatedTokenFilePath is a required parameter. In DefaultAzureCredential and ManagedIdentityCredential, this can be provided as an environment variable - "AZURE_FEDERATED_TOKEN_FILE".
|
66
|
+
See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`);
|
59
67
|
}
|
68
|
+
logger.info(`Invoking ClientAssertionCredential with tenant ID: ${tenantId}, clientId: ${workloadIdentityCredentialOptions.clientId} and federated token path: [REDACTED]`);
|
69
|
+
this.client = new ClientAssertionCredential(tenantId, clientId, this.readFileContents.bind(this), options);
|
60
70
|
}
|
61
71
|
/**
|
62
72
|
* Authenticates with Microsoft Entra ID and returns an access token if successful.
|
@@ -72,7 +82,7 @@ export class WorkloadIdentityCredential {
|
|
72
82
|
In DefaultAzureCredential and ManagedIdentityCredential, these can be provided as environment variables -
|
73
83
|
"AZURE_TENANT_ID",
|
74
84
|
"AZURE_CLIENT_ID",
|
75
|
-
"AZURE_FEDERATED_TOKEN_FILE". See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot
|
85
|
+
"AZURE_FEDERATED_TOKEN_FILE". See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`;
|
76
86
|
logger.info(errorMessage);
|
77
87
|
throw new CredentialUnavailableError(errorMessage);
|
78
88
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"workloadIdentityCredential.js","sourceRoot":"","sources":["../../../src/credentials/workloadIdentityCredential.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 { WorkloadIdentityCredentialOptions } from \"./workloadIdentityCredentialOptions\";\nimport { readFile } from \"fs/promises\";\nimport { CredentialUnavailableError } from \"../errors\";\nimport { credentialLogger, processEnvVars } from \"../util/logging\";\nimport { checkTenantId } from \"../util/tenantIdUtils\";\n\nconst credentialName = \"WorkloadIdentityCredential\";\n/**\n * Contains the list of all supported environment variable names so that an\n * appropriate error message can be generated when no credentials can be\n * configured.\n *\n * @internal\n */\nexport const SupportedWorkloadEnvironmentVariables = [\n \"AZURE_TENANT_ID\",\n \"AZURE_CLIENT_ID\",\n \"AZURE_FEDERATED_TOKEN_FILE\",\n];\nconst logger = credentialLogger(credentialName);\n/**\n * Workload Identity authentication is a feature in Azure that allows applications running on virtual machines (VMs)\n * to access other Azure resources without the need for a service principal or managed identity. With Workload Identity\n * authentication, applications authenticate themselves using their own identity, rather than using a shared service\n * principal or managed identity. Under the hood, Workload Identity authentication uses the concept of Service Account\n * Credentials (SACs), which are automatically created by Azure and stored securely in the VM. By using Workload\n * Identity authentication, you can avoid the need to manage and rotate service principals or managed identities for\n * each application on each VM. Additionally, because SACs are created automatically and managed by Azure, you don't\n * need to worry about storing and securing sensitive credentials themselves.\n * The WorkloadIdentityCredential supports Microsoft Entra Workload ID authentication on Azure Kubernetes and acquires\n * a token using the SACs available in the Azure Kubernetes environment.\n * Refer to <a href=\"https://learn.microsoft.com/azure/aks/workload-identity-overview\">Microsoft Entra\n * Workload ID</a> for more information.\n */\nexport class WorkloadIdentityCredential implements TokenCredential {\n private client: ClientAssertionCredential | undefined;\n private azureFederatedTokenFileContent: string | undefined = undefined;\n private cacheDate: number | undefined = undefined;\n private federatedTokenFilePath: string | undefined;\n\n /**\n * WorkloadIdentityCredential supports Microsoft Entra Workload ID on Kubernetes.\n *\n * @param options - The identity client options to use for authentication.\n */\n constructor(options?: WorkloadIdentityCredentialOptions) {\n // Logging environment variables for error details\n const assignedEnv = processEnvVars(SupportedWorkloadEnvironmentVariables).assigned.join(\", \");\n logger.info(`Found the following environment variables: ${assignedEnv}`);\n\n const workloadIdentityCredentialOptions = options ?? {};\n const tenantId = workloadIdentityCredentialOptions.tenantId || process.env.AZURE_TENANT_ID;\n const clientId = workloadIdentityCredentialOptions.clientId || process.env.AZURE_CLIENT_ID;\n this.federatedTokenFilePath =\n workloadIdentityCredentialOptions.tokenFilePath || process.env.AZURE_FEDERATED_TOKEN_FILE;\n if (tenantId) {\n checkTenantId(logger, tenantId);\n }\n if (clientId && tenantId && this.federatedTokenFilePath) {\n logger.info(\n `Invoking ClientAssertionCredential with tenant ID: ${tenantId}, clientId: ${workloadIdentityCredentialOptions.clientId} and federated token path: [REDACTED]`,\n );\n this.client = new ClientAssertionCredential(\n tenantId,\n clientId,\n this.readFileContents.bind(this),\n options,\n );\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 public async getToken(\n scopes: string | string[],\n options?: GetTokenOptions,\n ): Promise<AccessToken | null> {\n if (!this.client) {\n const errorMessage = `${credentialName}: is unavailable. tenantId, clientId, and federatedTokenFilePath are required parameters. \n In DefaultAzureCredential and ManagedIdentityCredential, these can be provided as environment variables - \n \"AZURE_TENANT_ID\",\n \"AZURE_CLIENT_ID\",\n \"AZURE_FEDERATED_TOKEN_FILE\". See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot `;\n logger.info(errorMessage);\n throw new CredentialUnavailableError(errorMessage);\n }\n logger.info(\"Invoking getToken() of Client Assertion Credential\");\n return this.client.getToken(scopes, options);\n }\n\n private async readFileContents(): Promise<string> {\n // Cached assertions expire after 5 minutes\n if (this.cacheDate !== undefined && Date.now() - this.cacheDate >= 1000 * 60 * 5) {\n this.azureFederatedTokenFileContent = undefined;\n }\n if (!this.federatedTokenFilePath) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. Invalid file path provided ${this.federatedTokenFilePath}.`,\n );\n }\n if (!this.azureFederatedTokenFileContent) {\n const file = await readFile(this.federatedTokenFilePath, \"utf8\");\n const value = file.trim();\n if (!value) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. No content on the file ${this.federatedTokenFilePath}.`,\n );\n } else {\n this.azureFederatedTokenFileContent = value;\n this.cacheDate = Date.now();\n }\n }\n return this.azureFederatedTokenFileContent;\n }\n}\n"]}
|
1
|
+
{"version":3,"file":"workloadIdentityCredential.js","sourceRoot":"","sources":["../../../src/credentials/workloadIdentityCredential.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 { credentialLogger, processEnvVars } from \"../util/logging\";\n\nimport { ClientAssertionCredential } from \"./clientAssertionCredential\";\nimport { CredentialUnavailableError } from \"../errors\";\nimport { WorkloadIdentityCredentialOptions } from \"./workloadIdentityCredentialOptions\";\nimport { checkTenantId } from \"../util/tenantIdUtils\";\nimport { readFile } from \"fs/promises\";\n\nconst credentialName = \"WorkloadIdentityCredential\";\n/**\n * Contains the list of all supported environment variable names so that an\n * appropriate error message can be generated when no credentials can be\n * configured.\n *\n * @internal\n */\nexport const SupportedWorkloadEnvironmentVariables = [\n \"AZURE_TENANT_ID\",\n \"AZURE_CLIENT_ID\",\n \"AZURE_FEDERATED_TOKEN_FILE\",\n];\nconst logger = credentialLogger(credentialName);\n/**\n * Workload Identity authentication is a feature in Azure that allows applications running on virtual machines (VMs)\n * to access other Azure resources without the need for a service principal or managed identity. With Workload Identity\n * authentication, applications authenticate themselves using their own identity, rather than using a shared service\n * principal or managed identity. Under the hood, Workload Identity authentication uses the concept of Service Account\n * Credentials (SACs), which are automatically created by Azure and stored securely in the VM. By using Workload\n * Identity authentication, you can avoid the need to manage and rotate service principals or managed identities for\n * each application on each VM. Additionally, because SACs are created automatically and managed by Azure, you don't\n * need to worry about storing and securing sensitive credentials themselves.\n * The WorkloadIdentityCredential supports Microsoft Entra Workload ID authentication on Azure Kubernetes and acquires\n * a token using the SACs available in the Azure Kubernetes environment.\n * Refer to <a href=\"https://learn.microsoft.com/azure/aks/workload-identity-overview\">Microsoft Entra\n * Workload ID</a> for more information.\n */\nexport class WorkloadIdentityCredential implements TokenCredential {\n private client: ClientAssertionCredential | undefined;\n private azureFederatedTokenFileContent: string | undefined = undefined;\n private cacheDate: number | undefined = undefined;\n private federatedTokenFilePath: string | undefined;\n\n /**\n * WorkloadIdentityCredential supports Microsoft Entra Workload ID on Kubernetes.\n *\n * @param options - The identity client options to use for authentication.\n */\n constructor(options?: WorkloadIdentityCredentialOptions) {\n // Logging environment variables for error details\n const assignedEnv = processEnvVars(SupportedWorkloadEnvironmentVariables).assigned.join(\", \");\n logger.info(`Found the following environment variables: ${assignedEnv}`);\n\n const workloadIdentityCredentialOptions = options ?? {};\n const tenantId = workloadIdentityCredentialOptions.tenantId || process.env.AZURE_TENANT_ID;\n const clientId = workloadIdentityCredentialOptions.clientId || process.env.AZURE_CLIENT_ID;\n this.federatedTokenFilePath =\n workloadIdentityCredentialOptions.tokenFilePath || process.env.AZURE_FEDERATED_TOKEN_FILE;\n if (tenantId) {\n checkTenantId(logger, tenantId);\n }\n if (!clientId) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. clientId is a required parameter. In DefaultAzureCredential and ManagedIdentityCredential, this can be provided as an environment variable - \"AZURE_CLIENT_ID\".\n See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`,\n );\n }\n\n if (!tenantId) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. tenantId is a required parameter. In DefaultAzureCredential and ManagedIdentityCredential, this can be provided as an environment variable - \"AZURE_TENANT_ID\".\n See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`,\n );\n }\n\n if (!this.federatedTokenFilePath) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. federatedTokenFilePath is a required parameter. In DefaultAzureCredential and ManagedIdentityCredential, this can be provided as an environment variable - \"AZURE_FEDERATED_TOKEN_FILE\".\n See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`,\n );\n }\n\n logger.info(\n `Invoking ClientAssertionCredential with tenant ID: ${tenantId}, clientId: ${workloadIdentityCredentialOptions.clientId} and federated token path: [REDACTED]`,\n );\n this.client = new ClientAssertionCredential(\n tenantId,\n clientId,\n this.readFileContents.bind(this),\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} 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 | null> {\n if (!this.client) {\n const errorMessage = `${credentialName}: is unavailable. tenantId, clientId, and federatedTokenFilePath are required parameters. \n In DefaultAzureCredential and ManagedIdentityCredential, these can be provided as environment variables - \n \"AZURE_TENANT_ID\",\n \"AZURE_CLIENT_ID\",\n \"AZURE_FEDERATED_TOKEN_FILE\". See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot`;\n logger.info(errorMessage);\n throw new CredentialUnavailableError(errorMessage);\n }\n logger.info(\"Invoking getToken() of Client Assertion Credential\");\n return this.client.getToken(scopes, options);\n }\n\n private async readFileContents(): Promise<string> {\n // Cached assertions expire after 5 minutes\n if (this.cacheDate !== undefined && Date.now() - this.cacheDate >= 1000 * 60 * 5) {\n this.azureFederatedTokenFileContent = undefined;\n }\n if (!this.federatedTokenFilePath) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. Invalid file path provided ${this.federatedTokenFilePath}.`,\n );\n }\n if (!this.azureFederatedTokenFileContent) {\n const file = await readFile(this.federatedTokenFilePath, \"utf8\");\n const value = file.trim();\n if (!value) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. No content on the file ${this.federatedTokenFilePath}.`,\n );\n } else {\n this.azureFederatedTokenFileContent = value;\n this.cacheDate = Date.now();\n }\n }\n return this.azureFederatedTokenFileContent;\n }\n}\n"]}
|
package/dist-esm/src/errors.js
CHANGED
@@ -15,8 +15,9 @@ export const CredentialUnavailableErrorName = "CredentialUnavailableError";
|
|
15
15
|
* an error that should halt the chain, it's caught and the chain continues
|
16
16
|
*/
|
17
17
|
export class CredentialUnavailableError extends Error {
|
18
|
-
constructor(message) {
|
19
|
-
|
18
|
+
constructor(message, options) {
|
19
|
+
// @ts-expect-error - TypeScript does not recognize this until we use ES2022 as the target; however, all our major runtimes do support the `cause` property
|
20
|
+
super(message, options);
|
20
21
|
this.name = CredentialUnavailableErrorName;
|
21
22
|
}
|
22
23
|
}
|
@@ -31,7 +32,7 @@ export const AuthenticationErrorName = "AuthenticationError";
|
|
31
32
|
*/
|
32
33
|
export class AuthenticationError extends Error {
|
33
34
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
34
|
-
constructor(statusCode, errorBody) {
|
35
|
+
constructor(statusCode, errorBody, options) {
|
35
36
|
let errorResponse = {
|
36
37
|
error: "unknown",
|
37
38
|
errorDescription: "An unknown error occurred and no additional details are available.",
|
@@ -49,8 +50,8 @@ export class AuthenticationError extends Error {
|
|
49
50
|
catch (e) {
|
50
51
|
if (statusCode === 400) {
|
51
52
|
errorResponse = {
|
52
|
-
error: "
|
53
|
-
errorDescription:
|
53
|
+
error: "invalid_request",
|
54
|
+
errorDescription: `The service indicated that the request was invalid.\n\n${errorBody}`,
|
54
55
|
};
|
55
56
|
}
|
56
57
|
else {
|
@@ -67,7 +68,9 @@ export class AuthenticationError extends Error {
|
|
67
68
|
errorDescription: "An unknown error occurred and no additional details are available.",
|
68
69
|
};
|
69
70
|
}
|
70
|
-
super(`${errorResponse.error} Status code: ${statusCode}\nMore details:\n${errorResponse.errorDescription}
|
71
|
+
super(`${errorResponse.error} Status code: ${statusCode}\nMore details:\n${errorResponse.errorDescription},`,
|
72
|
+
// @ts-expect-error - TypeScript does not recognize this until we use ES2022 as the target; however, all our major runtimes do support the `cause` property
|
73
|
+
options);
|
71
74
|
this.statusCode = statusCode;
|
72
75
|
this.errorResponse = errorResponse;
|
73
76
|
// Ensure that this type reports the correct name
|
@@ -110,7 +113,9 @@ export class AuthenticationRequiredError extends Error {
|
|
110
113
|
* Optional parameters. A message can be specified. The {@link GetTokenOptions} of the request can also be specified to more easily associate the error with the received parameters.
|
111
114
|
*/
|
112
115
|
options) {
|
113
|
-
super(options.message
|
116
|
+
super(options.message,
|
117
|
+
// @ts-expect-error - TypeScript does not recognize this until we use ES2022 as the target; however, all our major runtimes do support the `cause` property
|
118
|
+
options.cause ? { cause: options.cause } : undefined);
|
114
119
|
this.scopes = options.scopes;
|
115
120
|
this.getTokenOptions = options.getTokenOptions;
|
116
121
|
this.name = "AuthenticationRequiredError";
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { GetTokenOptions } from \"@azure/core-auth\";\n\n/**\n * See the official documentation for more details:\n *\n * https://learn.microsoft.com/en-us/azure/active-directory/develop/v1-protocols-oauth-code#error-response-1\n *\n * NOTE: This documentation is for v1 OAuth support but the same error\n * response details still apply to v2.\n */\nexport interface ErrorResponse {\n /**\n * The string identifier for the error.\n */\n error: string;\n\n /**\n * The error's description.\n */\n errorDescription: string;\n\n /**\n * An array of codes pertaining to the error(s) that occurred.\n */\n errorCodes?: number[];\n\n /**\n * The timestamp at which the error occurred.\n */\n timestamp?: string;\n\n /**\n * The trace identifier for this error occurrence.\n */\n traceId?: string;\n\n /**\n * The correlation ID to be used for tracking the source of the error.\n */\n correlationId?: string;\n}\n\n/**\n * Used for internal deserialization of OAuth responses. Public model is ErrorResponse\n * @internal\n */\nexport interface OAuthErrorResponse {\n error: string;\n error_description: string;\n error_codes?: number[];\n timestamp?: string;\n trace_id?: string;\n correlation_id?: string;\n}\n\nfunction isErrorResponse(errorResponse: any): errorResponse is OAuthErrorResponse {\n return (\n errorResponse &&\n typeof errorResponse.error === \"string\" &&\n typeof errorResponse.error_description === \"string\"\n );\n}\n\n/**\n * The Error.name value of an CredentialUnavailable\n */\nexport const CredentialUnavailableErrorName = \"CredentialUnavailableError\";\n\n/**\n * This signifies that the credential that was tried in a chained credential\n * was not available to be used as the credential. Rather than treating this as\n * an error that should halt the chain, it's caught and the chain continues\n */\nexport class CredentialUnavailableError extends Error {\n constructor(message?: string) {\n super(message);\n this.name = CredentialUnavailableErrorName;\n }\n}\n\n/**\n * The Error.name value of an AuthenticationError\n */\nexport const AuthenticationErrorName = \"AuthenticationError\";\n\n/**\n * Provides details about a failure to authenticate with Azure Active\n * Directory. The `errorResponse` field contains more details about\n * the specific failure.\n */\nexport class AuthenticationError extends Error {\n /**\n * The HTTP status code returned from the authentication request.\n */\n public readonly statusCode: number;\n\n /**\n * The error response details.\n */\n public readonly errorResponse: ErrorResponse;\n\n // eslint-disable-next-line @typescript-eslint/ban-types\n constructor(statusCode: number, errorBody: object | string | undefined | null) {\n let errorResponse: ErrorResponse = {\n error: \"unknown\",\n errorDescription: \"An unknown error occurred and no additional details are available.\",\n };\n\n if (isErrorResponse(errorBody)) {\n errorResponse = convertOAuthErrorResponseToErrorResponse(errorBody);\n } else if (typeof errorBody === \"string\") {\n try {\n // Most error responses will contain JSON-formatted error details\n // in the response body\n const oauthErrorResponse: OAuthErrorResponse = JSON.parse(errorBody);\n errorResponse = convertOAuthErrorResponseToErrorResponse(oauthErrorResponse);\n } catch (e: any) {\n if (statusCode === 400) {\n errorResponse = {\n error: \"authority_not_found\",\n errorDescription: \"The specified authority URL was not found.\",\n };\n } else {\n errorResponse = {\n error: \"unknown_error\",\n errorDescription: `An unknown error has occurred. Response body:\\n\\n${errorBody}`,\n };\n }\n }\n } else {\n errorResponse = {\n error: \"unknown_error\",\n errorDescription: \"An unknown error occurred and no additional details are available.\",\n };\n }\n\n super(\n `${errorResponse.error} Status code: ${statusCode}\\nMore details:\\n${errorResponse.errorDescription}`,\n );\n this.statusCode = statusCode;\n this.errorResponse = errorResponse;\n\n // Ensure that this type reports the correct name\n this.name = AuthenticationErrorName;\n }\n}\n\n/**\n * The Error.name value of an AggregateAuthenticationError\n */\nexport const AggregateAuthenticationErrorName = \"AggregateAuthenticationError\";\n\n/**\n * Provides an `errors` array containing {@link AuthenticationError} instance\n * for authentication failures from credentials in a {@link ChainedTokenCredential}.\n */\nexport class AggregateAuthenticationError extends Error {\n /**\n * The array of error objects that were thrown while trying to authenticate\n * with the credentials in a {@link ChainedTokenCredential}.\n */\n public errors: any[];\n\n constructor(errors: any[], errorMessage?: string) {\n const errorDetail = errors.join(\"\\n\");\n super(`${errorMessage}\\n${errorDetail}`);\n this.errors = errors;\n\n // Ensure that this type reports the correct name\n this.name = AggregateAuthenticationErrorName;\n }\n}\n\nfunction convertOAuthErrorResponseToErrorResponse(errorBody: OAuthErrorResponse): ErrorResponse {\n return {\n error: errorBody.error,\n errorDescription: errorBody.error_description,\n correlationId: errorBody.correlation_id,\n errorCodes: errorBody.error_codes,\n timestamp: errorBody.timestamp,\n traceId: errorBody.trace_id,\n };\n}\n\n/**\n * Optional parameters to the {@link AuthenticationRequiredError}\n */\nexport interface AuthenticationRequiredErrorOptions {\n /**\n * The list of scopes for which the token will have access.\n */\n scopes: string[];\n /**\n * The options passed to the getToken request.\n */\n getTokenOptions?: GetTokenOptions;\n /**\n * The message of the error.\n */\n message?: string;\n}\n\n/**\n * Error used to enforce authentication after trying to retrieve a token silently.\n */\nexport class AuthenticationRequiredError extends Error {\n /**\n * The list of scopes for which the token will have access.\n */\n public scopes: string[];\n /**\n * The options passed to the getToken request.\n */\n public getTokenOptions?: GetTokenOptions;\n\n constructor(\n /**\n * Optional parameters. A message can be specified. The {@link GetTokenOptions} of the request can also be specified to more easily associate the error with the received parameters.\n */\n options: AuthenticationRequiredErrorOptions,\n ) {\n super(options.message);\n this.scopes = options.scopes;\n this.getTokenOptions = options.getTokenOptions;\n this.name = \"AuthenticationRequiredError\";\n }\n}\n"]}
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { GetTokenOptions } from \"@azure/core-auth\";\n\n/**\n * See the official documentation for more details:\n *\n * https://learn.microsoft.com/en-us/azure/active-directory/develop/v1-protocols-oauth-code#error-response-1\n *\n * NOTE: This documentation is for v1 OAuth support but the same error\n * response details still apply to v2.\n */\nexport interface ErrorResponse {\n /**\n * The string identifier for the error.\n */\n error: string;\n\n /**\n * The error's description.\n */\n errorDescription: string;\n\n /**\n * An array of codes pertaining to the error(s) that occurred.\n */\n errorCodes?: number[];\n\n /**\n * The timestamp at which the error occurred.\n */\n timestamp?: string;\n\n /**\n * The trace identifier for this error occurrence.\n */\n traceId?: string;\n\n /**\n * The correlation ID to be used for tracking the source of the error.\n */\n correlationId?: string;\n}\n\n/**\n * Used for internal deserialization of OAuth responses. Public model is ErrorResponse\n * @internal\n */\nexport interface OAuthErrorResponse {\n error: string;\n error_description: string;\n error_codes?: number[];\n timestamp?: string;\n trace_id?: string;\n correlation_id?: string;\n}\n\nfunction isErrorResponse(errorResponse: any): errorResponse is OAuthErrorResponse {\n return (\n errorResponse &&\n typeof errorResponse.error === \"string\" &&\n typeof errorResponse.error_description === \"string\"\n );\n}\n\n/**\n * The Error.name value of an CredentialUnavailable\n */\nexport const CredentialUnavailableErrorName = \"CredentialUnavailableError\";\n\n/**\n * This signifies that the credential that was tried in a chained credential\n * was not available to be used as the credential. Rather than treating this as\n * an error that should halt the chain, it's caught and the chain continues\n */\nexport class CredentialUnavailableError extends Error {\n constructor(message?: string, options?: { cause?: unknown }) {\n // @ts-expect-error - TypeScript does not recognize this until we use ES2022 as the target; however, all our major runtimes do support the `cause` property\n super(message, options);\n this.name = CredentialUnavailableErrorName;\n }\n}\n\n/**\n * The Error.name value of an AuthenticationError\n */\nexport const AuthenticationErrorName = \"AuthenticationError\";\n\n/**\n * Provides details about a failure to authenticate with Azure Active\n * Directory. The `errorResponse` field contains more details about\n * the specific failure.\n */\nexport class AuthenticationError extends Error {\n /**\n * The HTTP status code returned from the authentication request.\n */\n public readonly statusCode: number;\n\n /**\n * The error response details.\n */\n public readonly errorResponse: ErrorResponse;\n\n // eslint-disable-next-line @typescript-eslint/ban-types\n constructor(\n statusCode: number,\n errorBody: object | string | undefined | null,\n options?: { cause?: unknown },\n ) {\n let errorResponse: ErrorResponse = {\n error: \"unknown\",\n errorDescription: \"An unknown error occurred and no additional details are available.\",\n };\n\n if (isErrorResponse(errorBody)) {\n errorResponse = convertOAuthErrorResponseToErrorResponse(errorBody);\n } else if (typeof errorBody === \"string\") {\n try {\n // Most error responses will contain JSON-formatted error details\n // in the response body\n const oauthErrorResponse: OAuthErrorResponse = JSON.parse(errorBody);\n errorResponse = convertOAuthErrorResponseToErrorResponse(oauthErrorResponse);\n } catch (e: any) {\n if (statusCode === 400) {\n errorResponse = {\n error: \"invalid_request\",\n errorDescription: `The service indicated that the request was invalid.\\n\\n${errorBody}`,\n };\n } else {\n errorResponse = {\n error: \"unknown_error\",\n errorDescription: `An unknown error has occurred. Response body:\\n\\n${errorBody}`,\n };\n }\n }\n } else {\n errorResponse = {\n error: \"unknown_error\",\n errorDescription: \"An unknown error occurred and no additional details are available.\",\n };\n }\n\n super(\n `${errorResponse.error} Status code: ${statusCode}\\nMore details:\\n${errorResponse.errorDescription},`,\n // @ts-expect-error - TypeScript does not recognize this until we use ES2022 as the target; however, all our major runtimes do support the `cause` property\n options,\n );\n this.statusCode = statusCode;\n this.errorResponse = errorResponse;\n\n // Ensure that this type reports the correct name\n this.name = AuthenticationErrorName;\n }\n}\n\n/**\n * The Error.name value of an AggregateAuthenticationError\n */\nexport const AggregateAuthenticationErrorName = \"AggregateAuthenticationError\";\n\n/**\n * Provides an `errors` array containing {@link AuthenticationError} instance\n * for authentication failures from credentials in a {@link ChainedTokenCredential}.\n */\nexport class AggregateAuthenticationError extends Error {\n /**\n * The array of error objects that were thrown while trying to authenticate\n * with the credentials in a {@link ChainedTokenCredential}.\n */\n public errors: any[];\n\n constructor(errors: any[], errorMessage?: string) {\n const errorDetail = errors.join(\"\\n\");\n super(`${errorMessage}\\n${errorDetail}`);\n this.errors = errors;\n\n // Ensure that this type reports the correct name\n this.name = AggregateAuthenticationErrorName;\n }\n}\n\nfunction convertOAuthErrorResponseToErrorResponse(errorBody: OAuthErrorResponse): ErrorResponse {\n return {\n error: errorBody.error,\n errorDescription: errorBody.error_description,\n correlationId: errorBody.correlation_id,\n errorCodes: errorBody.error_codes,\n timestamp: errorBody.timestamp,\n traceId: errorBody.trace_id,\n };\n}\n\n/**\n * Optional parameters to the {@link AuthenticationRequiredError}\n */\nexport interface AuthenticationRequiredErrorOptions {\n /**\n * The list of scopes for which the token will have access.\n */\n scopes: string[];\n /**\n * The options passed to the getToken request.\n */\n getTokenOptions?: GetTokenOptions;\n /**\n * The message of the error.\n */\n message?: string;\n /**\n * The underlying cause, if any, that caused the authentication to fail.\n */\n cause?: unknown;\n}\n\n/**\n * Error used to enforce authentication after trying to retrieve a token silently.\n */\nexport class AuthenticationRequiredError extends Error {\n /**\n * The list of scopes for which the token will have access.\n */\n public scopes: string[];\n /**\n * The options passed to the getToken request.\n */\n public getTokenOptions?: GetTokenOptions;\n\n constructor(\n /**\n * Optional parameters. A message can be specified. The {@link GetTokenOptions} of the request can also be specified to more easily associate the error with the received parameters.\n */\n options: AuthenticationRequiredErrorOptions,\n ) {\n super(\n options.message,\n // @ts-expect-error - TypeScript does not recognize this until we use ES2022 as the target; however, all our major runtimes do support the `cause` property\n options.cause ? { cause: options.cause } : undefined,\n );\n this.scopes = options.scopes;\n this.getTokenOptions = options.getTokenOptions;\n this.name = \"AuthenticationRequiredError\";\n }\n}\n"]}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"flows.js","sourceRoot":"","sources":["../../../../src/msal/browserFlows/flows.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken } from \"@azure/core-auth\";\nimport { AuthenticationRecord } from \"../types\";\nimport { CredentialFlowGetTokenOptions } from \"../credentials\";\nimport { CredentialLogger } from \"../../util/logging\";\n\n/**\n * Union of the constructor parameters that all MSAL flow types take.\n * @internal\n */\nexport interface MsalFlowOptions {\n logger: CredentialLogger;\n clientId?: string;\n tenantId?: string;\n authorityHost?: string;\n authenticationRecord?: AuthenticationRecord;\n disableAutomaticAuthentication?: boolean;\n disableInstanceDiscovery?: boolean;\n getAssertion?: () => Promise<string>;\n enableMsaPassthrough?: boolean;\n}\n\n/**\n * The common methods we use to work with the MSAL flows.\n * @internal\n */\nexport interface MsalFlow {\n /**\n * Allows for any setup before any request is processed.\n */\n init(options?: CredentialFlowGetTokenOptions): Promise<void>;\n /**\n * Tries to load the active account, either from memory or from MSAL.\n */\n getActiveAccount(): Promise<AuthenticationRecord | undefined>;\n /**\n * Tries to retrieve the token silently using MSAL.\n */\n getTokenSilent(scopes?: string[], options?: CredentialFlowGetTokenOptions): Promise<AccessToken>;\n /**\n * Calls to the implementation's doGetToken method.\n */\n getToken(scopes?: string[], options?: CredentialFlowGetTokenOptions): Promise<AccessToken>;\n}\n"]}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"msalBrowserCommon.js","sourceRoot":"","sources":["../../../../src/msal/browserFlows/msalBrowserCommon.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport * as msalBrowser from \"@azure/msal-browser\";\n\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { AuthenticationRecord, MsalResult } from \"../types\";\nimport { AuthenticationRequiredError, CredentialUnavailableError } from \"../../errors\";\nimport { CredentialLogger, formatSuccess } from \"../../util/logging\";\nimport { MsalFlow, MsalFlowOptions } from \"../flows\";\nimport { ensureValidMsalToken, getAuthority, getKnownAuthorities, msalToPublic } from \"../utils\";\nimport {\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n resolveTenantId,\n} from \"../../util/tenantIdUtils\";\n\nimport { BrowserLoginStyle } from \"../../credentials/interactiveBrowserCredentialOptions\";\nimport { CredentialFlowGetTokenOptions } from \"../credentials\";\nimport { DefaultTenantId } from \"../../constants\";\nimport { LogPolicyOptions } from \"@azure/core-rest-pipeline\";\nimport { MultiTenantTokenCredentialOptions } from \"../../credentials/multiTenantTokenCredentialOptions\";\n\n/**\n * Union of the constructor parameters that all MSAL flow types take.\n * Some properties might not be used by some flow types.\n */\nexport interface MsalBrowserFlowOptions extends MsalFlowOptions {\n tokenCredentialOptions: MultiTenantTokenCredentialOptions;\n redirectUri?: string;\n loginStyle: BrowserLoginStyle;\n loginHint?: string;\n /**\n * Allows users to configure settings for logging policy options, allow logging account information and personally identifiable information for customer support.\n */\n loggingOptions?: LogPolicyOptions & {\n /**\n * Allows logging account information once the authentication flow succeeds.\n */\n allowLoggingAccountIdentifiers?: boolean;\n /**\n * Allows logging personally identifiable information for customer support.\n */\n enableUnsafeSupportLogging?: boolean;\n };\n}\n\n/**\n * The common methods we use to work with the MSAL browser flows.\n * @internal\n */\nexport interface MsalBrowserFlow extends MsalFlow {\n login(scopes?: string[]): Promise<AuthenticationRecord | undefined>;\n handleRedirect(): Promise<AuthenticationRecord | undefined>;\n}\n\n/**\n * Generates a MSAL configuration that generally works for browsers\n * @internal\n */\nexport function defaultBrowserMsalConfig(\n options: MsalBrowserFlowOptions,\n): msalBrowser.Configuration {\n const tenantId = options.tenantId || DefaultTenantId;\n const authority = getAuthority(tenantId, options.authorityHost);\n return {\n auth: {\n clientId: options.clientId!,\n authority,\n knownAuthorities: getKnownAuthorities(tenantId, authority, options.disableInstanceDiscovery),\n // If the users picked redirect as their login style,\n // but they didn't provide a redirectUri,\n // we can try to use the current page we're in as a default value.\n redirectUri: options.redirectUri || self.location.origin,\n },\n };\n}\n\n/**\n * MSAL partial base client for the browsers.\n *\n * It completes the input configuration with some default values.\n * It also provides with utility protected methods that can be used from any of the clients,\n * which includes handlers for successful responses and errors.\n *\n * @internal\n */\nexport abstract class MsalBrowser implements MsalBrowserFlow {\n protected loginStyle: BrowserLoginStyle;\n protected clientId: string;\n protected tenantId: string;\n protected additionallyAllowedTenantIds: string[];\n protected authorityHost?: string;\n protected account: AuthenticationRecord | undefined;\n protected msalConfig: msalBrowser.Configuration;\n protected disableAutomaticAuthentication?: boolean;\n protected app?: msalBrowser.IPublicClientApplication;\n protected logger: CredentialLogger;\n\n constructor(options: MsalBrowserFlowOptions) {\n this.logger = options.logger;\n this.loginStyle = options.loginStyle;\n if (!options.clientId) {\n throw new CredentialUnavailableError(\"A client ID is required in browsers\");\n }\n this.clientId = options.clientId;\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.tokenCredentialOptions?.additionallyAllowedTenants,\n );\n this.tenantId = resolveTenantId(this.logger, options.tenantId, options.clientId);\n this.authorityHost = options.authorityHost;\n this.msalConfig = defaultBrowserMsalConfig(options);\n this.disableAutomaticAuthentication = options.disableAutomaticAuthentication;\n\n if (options.authenticationRecord) {\n this.account = {\n ...options.authenticationRecord,\n tenantId: this.tenantId,\n };\n }\n }\n\n /**\n * In the browsers we don't need to init()\n */\n async init(): Promise<void> {\n // Nothing to do here.\n }\n\n /**\n * Attempts to handle a redirection request the least amount of times possible.\n */\n public abstract handleRedirect(): Promise<AuthenticationRecord | undefined>;\n\n /**\n * Clears MSAL's cache.\n */\n async logout(): Promise<void> {\n this.app?.logout();\n }\n\n /**\n * Uses MSAL to retrieve the active account.\n */\n public abstract getActiveAccount(): Promise<AuthenticationRecord | undefined>;\n\n /**\n * Uses MSAL to trigger a redirect or a popup login.\n */\n public abstract login(scopes?: string | string[]): Promise<AuthenticationRecord | undefined>;\n\n /**\n * Attempts to retrieve a token from cache.\n */\n public abstract getTokenSilent(scopes: string[]): Promise<AccessToken>;\n\n /**\n * Attempts to retrieve the token in the browser.\n */\n protected abstract doGetToken(scopes: string[]): Promise<AccessToken>;\n\n /**\n * Attempts to retrieve an authenticated token from MSAL.\n */\n public async getToken(\n scopes: string[],\n options: CredentialFlowGetTokenOptions = {},\n ): Promise<AccessToken> {\n const tenantId =\n processMultiTenantRequest(this.tenantId, options, this.additionallyAllowedTenantIds) ||\n this.tenantId;\n\n if (!options.authority) {\n options.authority = getAuthority(tenantId, this.authorityHost);\n }\n\n // We ensure that redirection is handled at this point.\n await this.handleRedirect();\n\n if (!(await this.getActiveAccount()) && !this.disableAutomaticAuthentication) {\n await this.login(scopes);\n }\n return this.getTokenSilent(scopes).catch((err) => {\n if (err.name !== \"AuthenticationRequiredError\") {\n throw err;\n }\n if (options?.disableAutomaticAuthentication) {\n throw new AuthenticationRequiredError({\n scopes,\n getTokenOptions: options,\n message:\n \"Automatic authentication has been disabled. You may call the authentication() method.\",\n });\n }\n this.logger.info(\n `Silent authentication failed, falling back to interactive method ${this.loginStyle}`,\n );\n return this.doGetToken(scopes);\n });\n }\n\n /**\n * Handles the MSAL authentication result.\n * If the result has an account, we update the local account reference.\n * If the token received is invalid, an error will be thrown depending on what's missing.\n */\n protected handleResult(\n scopes: string | string[],\n result?: MsalResult,\n getTokenOptions?: GetTokenOptions,\n ): AccessToken {\n if (result?.account) {\n this.account = msalToPublic(this.clientId, result.account);\n }\n ensureValidMsalToken(scopes, result, getTokenOptions);\n this.logger.getToken.info(formatSuccess(scopes));\n return {\n token: result.accessToken,\n expiresOnTimestamp: result.expiresOn.getTime(),\n };\n }\n}\n"]}
|
1
|
+
{"version":3,"file":"msalBrowserCommon.js","sourceRoot":"","sources":["../../../../src/msal/browserFlows/msalBrowserCommon.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport * as msalBrowser from \"@azure/msal-browser\";\n\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { AuthenticationRecord, MsalResult } from \"../types\";\nimport { AuthenticationRequiredError, CredentialUnavailableError } from \"../../errors\";\nimport { CredentialLogger, formatSuccess } from \"../../util/logging\";\nimport { MsalFlow, MsalFlowOptions } from \"./flows\";\nimport { ensureValidMsalToken, getAuthority, getKnownAuthorities, msalToPublic } from \"../utils\";\nimport {\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n resolveTenantId,\n} from \"../../util/tenantIdUtils\";\n\nimport { BrowserLoginStyle } from \"../../credentials/interactiveBrowserCredentialOptions\";\nimport { CredentialFlowGetTokenOptions } from \"../credentials\";\nimport { DefaultTenantId } from \"../../constants\";\nimport { LogPolicyOptions } from \"@azure/core-rest-pipeline\";\nimport { MultiTenantTokenCredentialOptions } from \"../../credentials/multiTenantTokenCredentialOptions\";\n\n/**\n * Union of the constructor parameters that all MSAL flow types take.\n * Some properties might not be used by some flow types.\n */\nexport interface MsalBrowserFlowOptions extends MsalFlowOptions {\n tokenCredentialOptions: MultiTenantTokenCredentialOptions;\n redirectUri?: string;\n loginStyle: BrowserLoginStyle;\n loginHint?: string;\n /**\n * Allows users to configure settings for logging policy options, allow logging account information and personally identifiable information for customer support.\n */\n loggingOptions?: LogPolicyOptions & {\n /**\n * Allows logging account information once the authentication flow succeeds.\n */\n allowLoggingAccountIdentifiers?: boolean;\n /**\n * Allows logging personally identifiable information for customer support.\n */\n enableUnsafeSupportLogging?: boolean;\n };\n}\n\n/**\n * The common methods we use to work with the MSAL browser flows.\n * @internal\n */\nexport interface MsalBrowserFlow extends MsalFlow {\n login(scopes?: string[]): Promise<AuthenticationRecord | undefined>;\n handleRedirect(): Promise<AuthenticationRecord | undefined>;\n}\n\n/**\n * Generates a MSAL configuration that generally works for browsers\n * @internal\n */\nexport function defaultBrowserMsalConfig(\n options: MsalBrowserFlowOptions,\n): msalBrowser.Configuration {\n const tenantId = options.tenantId || DefaultTenantId;\n const authority = getAuthority(tenantId, options.authorityHost);\n return {\n auth: {\n clientId: options.clientId!,\n authority,\n knownAuthorities: getKnownAuthorities(tenantId, authority, options.disableInstanceDiscovery),\n // If the users picked redirect as their login style,\n // but they didn't provide a redirectUri,\n // we can try to use the current page we're in as a default value.\n redirectUri: options.redirectUri || self.location.origin,\n },\n };\n}\n\n/**\n * MSAL partial base client for the browsers.\n *\n * It completes the input configuration with some default values.\n * It also provides with utility protected methods that can be used from any of the clients,\n * which includes handlers for successful responses and errors.\n *\n * @internal\n */\nexport abstract class MsalBrowser implements MsalBrowserFlow {\n protected loginStyle: BrowserLoginStyle;\n protected clientId: string;\n protected tenantId: string;\n protected additionallyAllowedTenantIds: string[];\n protected authorityHost?: string;\n protected account: AuthenticationRecord | undefined;\n protected msalConfig: msalBrowser.Configuration;\n protected disableAutomaticAuthentication?: boolean;\n protected app?: msalBrowser.IPublicClientApplication;\n protected logger: CredentialLogger;\n\n constructor(options: MsalBrowserFlowOptions) {\n this.logger = options.logger;\n this.loginStyle = options.loginStyle;\n if (!options.clientId) {\n throw new CredentialUnavailableError(\"A client ID is required in browsers\");\n }\n this.clientId = options.clientId;\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.tokenCredentialOptions?.additionallyAllowedTenants,\n );\n this.tenantId = resolveTenantId(this.logger, options.tenantId, options.clientId);\n this.authorityHost = options.authorityHost;\n this.msalConfig = defaultBrowserMsalConfig(options);\n this.disableAutomaticAuthentication = options.disableAutomaticAuthentication;\n\n if (options.authenticationRecord) {\n this.account = {\n ...options.authenticationRecord,\n tenantId: this.tenantId,\n };\n }\n }\n\n /**\n * In the browsers we don't need to init()\n */\n async init(): Promise<void> {\n // Nothing to do here.\n }\n\n /**\n * Attempts to handle a redirection request the least amount of times possible.\n */\n public abstract handleRedirect(): Promise<AuthenticationRecord | undefined>;\n\n /**\n * Clears MSAL's cache.\n */\n async logout(): Promise<void> {\n this.app?.logout();\n }\n\n /**\n * Uses MSAL to retrieve the active account.\n */\n public abstract getActiveAccount(): Promise<AuthenticationRecord | undefined>;\n\n /**\n * Uses MSAL to trigger a redirect or a popup login.\n */\n public abstract login(scopes?: string | string[]): Promise<AuthenticationRecord | undefined>;\n\n /**\n * Attempts to retrieve a token from cache.\n */\n public abstract getTokenSilent(scopes: string[]): Promise<AccessToken>;\n\n /**\n * Attempts to retrieve the token in the browser.\n */\n protected abstract doGetToken(scopes: string[]): Promise<AccessToken>;\n\n /**\n * Attempts to retrieve an authenticated token from MSAL.\n */\n public async getToken(\n scopes: string[],\n options: CredentialFlowGetTokenOptions = {},\n ): Promise<AccessToken> {\n const tenantId =\n processMultiTenantRequest(this.tenantId, options, this.additionallyAllowedTenantIds) ||\n this.tenantId;\n\n if (!options.authority) {\n options.authority = getAuthority(tenantId, this.authorityHost);\n }\n\n // We ensure that redirection is handled at this point.\n await this.handleRedirect();\n\n if (!(await this.getActiveAccount()) && !this.disableAutomaticAuthentication) {\n await this.login(scopes);\n }\n return this.getTokenSilent(scopes).catch((err) => {\n if (err.name !== \"AuthenticationRequiredError\") {\n throw err;\n }\n if (options?.disableAutomaticAuthentication) {\n throw new AuthenticationRequiredError({\n scopes,\n getTokenOptions: options,\n message:\n \"Automatic authentication has been disabled. You may call the authentication() method.\",\n });\n }\n this.logger.info(\n `Silent authentication failed, falling back to interactive method ${this.loginStyle}`,\n );\n return this.doGetToken(scopes);\n });\n }\n\n /**\n * Handles the MSAL authentication result.\n * If the result has an account, we update the local account reference.\n * If the token received is invalid, an error will be thrown depending on what's missing.\n */\n protected handleResult(\n scopes: string | string[],\n result?: MsalResult,\n getTokenOptions?: GetTokenOptions,\n ): AccessToken {\n if (result?.account) {\n this.account = msalToPublic(this.clientId, result.account);\n }\n ensureValidMsalToken(scopes, result, getTokenOptions);\n this.logger.getToken.info(formatSuccess(scopes));\n return {\n token: result.accessToken,\n expiresOnTimestamp: result.expiresOn.getTime(),\n };\n }\n}\n"]}
|
@@ -8,12 +8,19 @@ import { AuthenticationRequiredError } from "../../errors";
|
|
8
8
|
import { IdentityClient } from "../../client/identityClient";
|
9
9
|
import { calculateRegionalAuthority } from "../../regionalAuthority";
|
10
10
|
import { getLogLevel } from "@azure/logger";
|
11
|
+
import open from "open";
|
11
12
|
import { resolveTenantId } from "../../util/tenantIdUtils";
|
12
|
-
import { interactiveBrowserMockable } from "./msalOpenBrowser";
|
13
13
|
/**
|
14
14
|
* The default logger used if no logger was passed in by the credential.
|
15
15
|
*/
|
16
16
|
const msalLogger = credentialLogger("MsalClient");
|
17
|
+
/**
|
18
|
+
* A call to open(), but mockable
|
19
|
+
* @internal
|
20
|
+
*/
|
21
|
+
export const interactiveBrowserMockable = {
|
22
|
+
open,
|
23
|
+
};
|
17
24
|
/**
|
18
25
|
* Generates the configuration for MSAL (Microsoft Authentication Library).
|
19
26
|
*
|