@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
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"clientCertificateCredential.js","sourceRoot":"","sources":["../../../src/credentials/clientCertificateCredential.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 { createHash, createPrivateKey } from \"crypto\";\nimport {\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n} from \"../util/tenantIdUtils\";\n\nimport { CertificateParts } from \"../msal/types\";\nimport { ClientCertificateCredentialOptions } from \"./clientCertificateCredentialOptions\";\nimport { credentialLogger } from \"../util/logging\";\nimport { readFile } from \"fs/promises\";\nimport { tracingClient } from \"../util/tracing\";\n\nconst credentialName = \"ClientCertificateCredential\";\nconst logger = credentialLogger(credentialName);\n\n/**\n * Required configuration options for the {@link ClientCertificateCredential}, with the string contents of a PEM certificate\n */\nexport interface ClientCertificatePEMCertificate {\n /**\n * The PEM-encoded public/private key certificate on the filesystem.\n */\n certificate: string;\n\n /**\n * The password for the certificate file.\n */\n certificatePassword?: string;\n}\n/**\n * Required configuration options for the {@link ClientCertificateCredential}, with the path to a PEM certificate.\n */\nexport interface ClientCertificatePEMCertificatePath {\n /**\n * The path to the PEM-encoded public/private key certificate on the filesystem.\n */\n certificatePath: string;\n\n /**\n * The password for the certificate file.\n */\n certificatePassword?: string;\n}\n/**\n * Required configuration options for the {@link ClientCertificateCredential}, with either the string contents of a PEM certificate, or the path to a PEM certificate.\n */\nexport type ClientCertificateCredentialPEMConfiguration =\n | ClientCertificatePEMCertificate\n | ClientCertificatePEMCertificatePath;\n\n/**\n * Enables authentication to Microsoft Entra ID using a PEM-encoded\n * certificate that is assigned to an App Registration. More information\n * on how to configure certificate authentication can be found here:\n *\n * https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-certificate-credentials#register-your-certificate-with-azure-ad\n *\n */\nexport class ClientCertificateCredential implements TokenCredential {\n private tenantId: string;\n private additionallyAllowedTenantIds: string[];\n private certificateConfiguration: ClientCertificateCredentialPEMConfiguration;\n private sendCertificateChain?: boolean;\n private msalClient: MsalClient;\n\n /**\n * Creates an instance of the ClientCertificateCredential with the details\n * needed to authenticate against Microsoft Entra ID with a certificate.\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 certificatePath - The path to a PEM-encoded public/private key certificate on the filesystem.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n certificatePath: string,\n options?: ClientCertificateCredentialOptions,\n );\n /**\n * Creates an instance of the ClientCertificateCredential with the details\n * needed to authenticate against Microsoft Entra ID with a certificate.\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 configuration - Other parameters required, including the path of the certificate on the filesystem.\n * If the type is ignored, we will throw the value of the path to a PEM certificate.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n configuration: ClientCertificatePEMCertificatePath,\n options?: ClientCertificateCredentialOptions,\n );\n /**\n * Creates an instance of the ClientCertificateCredential with the details\n * needed to authenticate against Microsoft Entra ID with a certificate.\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 configuration - Other parameters required, including the PEM-encoded certificate as a string.\n * If the type is ignored, we will throw the value of the PEM-encoded certificate.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n configuration: ClientCertificatePEMCertificate,\n options?: ClientCertificateCredentialOptions,\n );\n constructor(\n tenantId: string,\n clientId: string,\n certificatePathOrConfiguration: string | ClientCertificateCredentialPEMConfiguration,\n options: ClientCertificateCredentialOptions = {},\n ) {\n if (!tenantId || !clientId) {\n throw new Error(`${credentialName}: tenantId and clientId are required parameters.`);\n }\n\n this.tenantId = tenantId;\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.additionallyAllowedTenants,\n );\n\n this.sendCertificateChain = options.sendCertificateChain;\n\n this.certificateConfiguration = {\n ...(typeof certificatePathOrConfiguration === \"string\"\n ? {\n certificatePath: certificatePathOrConfiguration,\n }\n : certificatePathOrConfiguration),\n };\n const certificate: string | undefined = (\n this.certificateConfiguration as ClientCertificatePEMCertificate\n ).certificate;\n const certificatePath: string | undefined = (\n this.certificateConfiguration as ClientCertificatePEMCertificatePath\n ).certificatePath;\n if (!this.certificateConfiguration || !(certificate || certificatePath)) {\n throw new Error(\n `${credentialName}: Provide either a PEM certificate in string form, or the path to that certificate in the filesystem. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`,\n );\n }\n if (certificate && certificatePath) {\n throw new Error(\n `${credentialName}: To avoid unexpected behaviors, providing both the contents of a PEM certificate and the path to a PEM certificate is forbidden. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`,\n );\n }\n this.msalClient = createMsalClient(clientId, 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 any requests this\n * TokenCredential implementation might make.\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 = Array.isArray(scopes) ? scopes : [scopes];\n const certificate = await this.buildClientCertificate();\n return this.msalClient.getTokenByClientCertificate(arrayScopes, certificate, newOptions);\n });\n }\n\n private async buildClientCertificate(): Promise<CertificateParts> {\n const parts = await this.parseCertificate();\n\n let privateKey: string;\n if (this.certificateConfiguration.certificatePassword !== undefined) {\n privateKey = createPrivateKey({\n key: parts.certificateContents,\n passphrase: this.certificateConfiguration.certificatePassword,\n format: \"pem\",\n })\n .export({\n format: \"pem\",\n type: \"pkcs8\",\n })\n .toString();\n } else {\n privateKey = parts.certificateContents;\n }\n\n return {\n thumbprint: parts.thumbprint,\n privateKey,\n x5c: parts.x5c,\n };\n }\n\n private async parseCertificate(): Promise<\n Omit<CertificateParts, \"privateKey\"> & { certificateContents: string }\n > {\n const certificate: string | undefined = (\n this.certificateConfiguration as ClientCertificatePEMCertificate\n ).certificate;\n const certificatePath: string | undefined = (\n this.certificateConfiguration as ClientCertificatePEMCertificatePath\n ).certificatePath;\n const certificateContents = certificate || (await readFile(certificatePath!, \"utf8\"));\n const x5c = this.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":"clientCertificateCredential.js","sourceRoot":"","sources":["../../../src/credentials/clientCertificateCredential.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 { createHash, createPrivateKey } from \"crypto\";\nimport {\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n} from \"../util/tenantIdUtils\";\n\nimport { CertificateParts } from \"../msal/types\";\nimport { ClientCertificateCredentialOptions } from \"./clientCertificateCredentialOptions\";\nimport { credentialLogger } from \"../util/logging\";\nimport { readFile } from \"fs/promises\";\nimport { tracingClient } from \"../util/tracing\";\n\nconst credentialName = \"ClientCertificateCredential\";\nconst logger = credentialLogger(credentialName);\n\n/**\n * Required configuration options for the {@link ClientCertificateCredential}, with the string contents of a PEM certificate\n */\nexport interface ClientCertificatePEMCertificate {\n /**\n * The PEM-encoded public/private key certificate on the filesystem.\n */\n certificate: string;\n\n /**\n * The password for the certificate file.\n */\n certificatePassword?: string;\n}\n/**\n * Required configuration options for the {@link ClientCertificateCredential}, with the path to a PEM certificate.\n */\nexport interface ClientCertificatePEMCertificatePath {\n /**\n * The path to the PEM-encoded public/private key certificate on the filesystem.\n */\n certificatePath: string;\n\n /**\n * The password for the certificate file.\n */\n certificatePassword?: string;\n}\n/**\n * Required configuration options for the {@link ClientCertificateCredential}, with either the string contents of a PEM certificate, or the path to a PEM certificate.\n */\nexport type ClientCertificateCredentialPEMConfiguration =\n | ClientCertificatePEMCertificate\n | ClientCertificatePEMCertificatePath;\n\n/**\n * Enables authentication to Microsoft Entra ID using a PEM-encoded\n * certificate that is assigned to an App Registration. More information\n * on how to configure certificate authentication can be found here:\n *\n * https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-certificate-credentials#register-your-certificate-with-azure-ad\n *\n */\nexport class ClientCertificateCredential implements TokenCredential {\n private tenantId: string;\n private additionallyAllowedTenantIds: string[];\n private certificateConfiguration: ClientCertificateCredentialPEMConfiguration;\n private sendCertificateChain?: boolean;\n private msalClient: MsalClient;\n\n /**\n * Creates an instance of the ClientCertificateCredential with the details\n * needed to authenticate against Microsoft Entra ID with a certificate.\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 certificatePath - The path to a PEM-encoded public/private key certificate on the filesystem.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n certificatePath: string,\n options?: ClientCertificateCredentialOptions,\n );\n /**\n * Creates an instance of the ClientCertificateCredential with the details\n * needed to authenticate against Microsoft Entra ID with a certificate.\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 configuration - Other parameters required, including the path of the certificate on the filesystem.\n * If the type is ignored, we will throw the value of the path to a PEM certificate.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n configuration: ClientCertificatePEMCertificatePath,\n options?: ClientCertificateCredentialOptions,\n );\n /**\n * Creates an instance of the ClientCertificateCredential with the details\n * needed to authenticate against Microsoft Entra ID with a certificate.\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 configuration - Other parameters required, including the PEM-encoded certificate as a string.\n * If the type is ignored, we will throw the value of the PEM-encoded certificate.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n configuration: ClientCertificatePEMCertificate,\n options?: ClientCertificateCredentialOptions,\n );\n constructor(\n tenantId: string,\n clientId: string,\n certificatePathOrConfiguration: string | ClientCertificateCredentialPEMConfiguration,\n options: ClientCertificateCredentialOptions = {},\n ) {\n if (!tenantId || !clientId) {\n throw new Error(`${credentialName}: tenantId and clientId are required parameters.`);\n }\n\n this.tenantId = tenantId;\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.additionallyAllowedTenants,\n );\n\n this.sendCertificateChain = options.sendCertificateChain;\n\n this.certificateConfiguration = {\n ...(typeof certificatePathOrConfiguration === \"string\"\n ? {\n certificatePath: certificatePathOrConfiguration,\n }\n : certificatePathOrConfiguration),\n };\n const certificate: string | undefined = (\n this.certificateConfiguration as ClientCertificatePEMCertificate\n ).certificate;\n const certificatePath: string | undefined = (\n this.certificateConfiguration as ClientCertificatePEMCertificatePath\n ).certificatePath;\n if (!this.certificateConfiguration || !(certificate || certificatePath)) {\n throw new Error(\n `${credentialName}: Provide either a PEM certificate in string form, or the path to that certificate in the filesystem. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`,\n );\n }\n if (certificate && certificatePath) {\n throw new Error(\n `${credentialName}: To avoid unexpected behaviors, providing both the contents of a PEM certificate and the path to a PEM certificate is forbidden. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`,\n );\n }\n this.msalClient = createMsalClient(clientId, 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 any requests this\n * TokenCredential implementation might make.\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 = Array.isArray(scopes) ? scopes : [scopes];\n const certificate = await this.buildClientCertificate();\n return this.msalClient.getTokenByClientCertificate(arrayScopes, certificate, newOptions);\n });\n }\n\n private async buildClientCertificate(): Promise<CertificateParts> {\n const parts = await parseCertificate(\n this.certificateConfiguration,\n this.sendCertificateChain ?? false,\n );\n\n let privateKey: string;\n if (this.certificateConfiguration.certificatePassword !== undefined) {\n privateKey = createPrivateKey({\n key: parts.certificateContents,\n passphrase: this.certificateConfiguration.certificatePassword,\n format: \"pem\",\n })\n .export({\n format: \"pem\",\n type: \"pkcs8\",\n })\n .toString();\n } else {\n privateKey = parts.certificateContents;\n }\n\n return {\n thumbprint: parts.thumbprint,\n privateKey,\n x5c: parts.x5c,\n };\n }\n}\n\n/**\n * Parses a certificate into its relevant parts\n *\n * @param certificateConfiguration - The certificate contents or path to the certificate\n * @param sendCertificateChain - true if the entire certificate chain should be sent for SNI, false otherwise\n * @returns The parsed certificate parts and the certificate contents\n */\nexport async function parseCertificate(\n certificateConfiguration: ClientCertificateCredentialPEMConfiguration,\n sendCertificateChain: boolean,\n): Promise<Omit<CertificateParts, \"privateKey\"> & { certificateContents: string }> {\n const certificate: string | undefined = (\n certificateConfiguration as ClientCertificatePEMCertificate\n ).certificate;\n const certificatePath: string | undefined = (\n certificateConfiguration as ClientCertificatePEMCertificatePath\n ).certificatePath;\n const certificateContents = certificate || (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"]}
|
@@ -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 { ensureScopes } from "../util/scopeUtils";
|
7
8
|
import { tracingClient } from "../util/tracing";
|
@@ -26,8 +27,14 @@ export class ClientSecretCredential {
|
|
26
27
|
* @param options - Options for configuring the client which makes the authentication request.
|
27
28
|
*/
|
28
29
|
constructor(tenantId, clientId, clientSecret, options = {}) {
|
29
|
-
if (!tenantId
|
30
|
-
throw new
|
30
|
+
if (!tenantId) {
|
31
|
+
throw new CredentialUnavailableError("ClientSecretCredential: tenantId is a required parameter. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.");
|
32
|
+
}
|
33
|
+
if (!clientId) {
|
34
|
+
throw new CredentialUnavailableError("ClientSecretCredential: clientId is a required parameter. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.");
|
35
|
+
}
|
36
|
+
if (!clientSecret) {
|
37
|
+
throw new CredentialUnavailableError("ClientSecretCredential: clientSecret is a required parameter. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.");
|
31
38
|
}
|
32
39
|
this.clientSecret = clientSecret;
|
33
40
|
this.tenantId = tenantId;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"clientSecretCredential.js","sourceRoot":"","sources":["../../../src/credentials/clientSecretCredential.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,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,MAAM,GAAG,gBAAgB,CAAC,wBAAwB,CAAC,CAAC;AAE1D;;;;;;;GAOG;AACH,MAAM,OAAO,sBAAsB;IAMjC;;;;;;;;;OASG;IACH,YACE,QAAgB,EAChB,QAAgB,EAChB,YAAoB,EACpB,UAAyC,EAAE;QAE3C,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAY,EAAE,CAAC;
|
1
|
+
{"version":3,"file":"clientSecretCredential.js","sourceRoot":"","sources":["../../../src/credentials/clientSecretCredential.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,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,MAAM,GAAG,gBAAgB,CAAC,wBAAwB,CAAC,CAAC;AAE1D;;;;;;;GAOG;AACH,MAAM,OAAO,sBAAsB;IAMjC;;;;;;;;;OASG;IACH,YACE,QAAgB,EAChB,QAAgB,EAChB,YAAoB,EACpB,UAAyC,EAAE;QAE3C,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,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,0BAA0B,CAClC,oKAAoK,CACrK,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,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,UAAU,GAAG,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,kCAChD,OAAO,KACV,MAAM,EACN,sBAAsB,EAAE,OAAO,IAC/B,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,YAAY,CAAC,MAAM,CAAC,CAAC;YACzC,OAAO,IAAI,CAAC,UAAU,CAAC,sBAAsB,CAAC,WAAW,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QAC5F,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 { ClientSecretCredentialOptions } from \"./clientSecretCredentialOptions\";\nimport { CredentialUnavailableError } from \"../errors\";\nimport { credentialLogger } from \"../util/logging\";\nimport { ensureScopes } from \"../util/scopeUtils\";\nimport { tracingClient } from \"../util/tracing\";\n\nconst logger = credentialLogger(\"ClientSecretCredential\");\n\n/**\n * Enables authentication to Microsoft Entra ID using a client secret\n * that was generated for an App Registration. More information on how\n * to configure a client secret can be found here:\n *\n * https://learn.microsoft.com/entra/identity-platform/quickstart-configure-app-access-web-apis#add-credentials-to-your-web-application\n *\n */\nexport class ClientSecretCredential implements TokenCredential {\n private tenantId: string;\n private additionallyAllowedTenantIds: string[];\n private msalClient: MsalClient;\n private clientSecret: string;\n\n /**\n * Creates an instance of the ClientSecretCredential with the details\n * needed to authenticate against Microsoft Entra ID with a client\n * secret.\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 clientSecret - A client secret that was generated for the App Registration.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n clientSecret: string,\n options: ClientSecretCredentialOptions = {},\n ) {\n if (!tenantId) {\n throw new CredentialUnavailableError(\n \"ClientSecretCredential: 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 \"ClientSecretCredential: clientId is a required parameter. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.\",\n );\n }\n\n if (!clientSecret) {\n throw new CredentialUnavailableError(\n \"ClientSecretCredential: clientSecret is a required parameter. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.\",\n );\n }\n\n this.clientSecret = clientSecret;\n this.tenantId = tenantId;\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.additionallyAllowedTenants,\n );\n\n this.msalClient = createMsalClient(clientId, 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 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.getTokenByClientSecret(arrayScopes, this.clientSecret, newOptions);\n },\n );\n }\n}\n"]}
|
@@ -72,7 +72,7 @@ export class DeviceCodeCredential {
|
|
72
72
|
* Authenticates with Microsoft Entra ID and returns an access token if successful.
|
73
73
|
* If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.
|
74
74
|
*
|
75
|
-
* If the token can't be retrieved silently, this method will
|
75
|
+
* If the token can't be retrieved silently, this method will always generate a challenge for the user.
|
76
76
|
*
|
77
77
|
* @param scopes - The list of scopes for which the token will have access.
|
78
78
|
* @param options - The options used to configure any requests this
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"deviceCodeCredential.js","sourceRoot":"","sources":["../../../src/credentials/deviceCodeCredential.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 processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n resolveTenantId,\n} from \"../util/tenantIdUtils\";\nimport {\n DeviceCodeCredentialOptions,\n DeviceCodeInfo,\n DeviceCodePromptCallback,\n} from \"./deviceCodeCredentialOptions\";\nimport { AuthenticationRecord } from \"../msal/types\";\nimport { credentialLogger } from \"../util/logging\";\nimport { ensureScopes } from \"../util/scopeUtils\";\nimport { tracingClient } from \"../util/tracing\";\nimport { MsalClient, createMsalClient } from \"../msal/nodeFlows/msalClient\";\nimport { DeveloperSignOnClientId } from \"../constants\";\n\nconst logger = credentialLogger(\"DeviceCodeCredential\");\n\n/**\n * Method that logs the user code from the DeviceCodeCredential.\n * @param deviceCodeInfo - The device code.\n */\nexport function defaultDeviceCodePromptCallback(deviceCodeInfo: DeviceCodeInfo): void {\n console.log(deviceCodeInfo.message);\n}\n\n/**\n * Enables authentication to Microsoft Entra ID using a device code\n * that the user can enter into https://microsoft.com/devicelogin.\n */\nexport class DeviceCodeCredential implements TokenCredential {\n private tenantId?: string;\n private additionallyAllowedTenantIds: string[];\n private disableAutomaticAuthentication?: boolean;\n private msalClient: MsalClient;\n private userPromptCallback: DeviceCodePromptCallback;\n\n /**\n * Creates an instance of DeviceCodeCredential with the details needed\n * to initiate the device code authorization flow with Microsoft Entra ID.\n *\n * A message will be logged, giving users a code that they can use to authenticate once they go to https://microsoft.com/devicelogin\n *\n * Developers can configure how this message is shown by passing a custom `userPromptCallback`:\n *\n * ```js\n * const credential = new DeviceCodeCredential({\n * tenantId: env.AZURE_TENANT_ID,\n * clientId: env.AZURE_CLIENT_ID,\n * userPromptCallback: (info) => {\n * console.log(\"CUSTOMIZED PROMPT CALLBACK\", info.message);\n * }\n * });\n * ```\n *\n * @param options - Options for configuring the client which makes the authentication requests.\n */\n constructor(options?: DeviceCodeCredentialOptions) {\n this.tenantId = options?.tenantId;\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.additionallyAllowedTenants,\n );\n const clientId = options?.clientId ?? DeveloperSignOnClientId;\n const tenantId = resolveTenantId(logger, options?.tenantId, clientId);\n this.userPromptCallback = options?.userPromptCallback ?? defaultDeviceCodePromptCallback;\n this.msalClient = createMsalClient(clientId, tenantId, {\n ...options,\n logger,\n tokenCredentialOptions: options || {},\n });\n this.disableAutomaticAuthentication = options?.disableAutomaticAuthentication;\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.getTokenByDeviceCode(arrayScopes, this.userPromptCallback, {\n ...newOptions,\n disableAutomaticAuthentication: this.disableAutomaticAuthentication,\n });\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 * If the token can't be retrieved silently, this method will
|
1
|
+
{"version":3,"file":"deviceCodeCredential.js","sourceRoot":"","sources":["../../../src/credentials/deviceCodeCredential.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EACL,yBAAyB,EACzB,mCAAmC,EACnC,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAO/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAc,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAEvD,MAAM,MAAM,GAAG,gBAAgB,CAAC,sBAAsB,CAAC,CAAC;AAExD;;;GAGG;AACH,MAAM,UAAU,+BAA+B,CAAC,cAA8B;IAC5E,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;AACtC,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,oBAAoB;IAO/B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,YAAY,OAAqC;;QAC/C,IAAI,CAAC,QAAQ,GAAG,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,QAAQ,CAAC;QAClC,IAAI,CAAC,4BAA4B,GAAG,mCAAmC,CACrE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,0BAA0B,CACpC,CAAC;QACF,MAAM,QAAQ,GAAG,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,QAAQ,mCAAI,uBAAuB,CAAC;QAC9D,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACtE,IAAI,CAAC,kBAAkB,GAAG,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,kBAAkB,mCAAI,+BAA+B,CAAC;QACzF,IAAI,CAAC,UAAU,GAAG,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,kCAChD,OAAO,KACV,MAAM,EACN,sBAAsB,EAAE,OAAO,IAAI,EAAE,IACrC,CAAC;QACH,IAAI,CAAC,8BAA8B,GAAG,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,8BAA8B,CAAC;IAChF,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,QAAQ,CAAC,MAAyB,EAAE,UAA2B,EAAE;QACrE,OAAO,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,oBAAoB,CAAC,WAAW,EAAE,IAAI,CAAC,kBAAkB,kCAC3E,UAAU,KACb,8BAA8B,EAAE,IAAI,CAAC,8BAA8B,IACnE,CAAC;QACL,CAAC,CACF,CAAC;IACJ,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,YAAY,CAChB,MAAyB,EACzB,UAA2B,EAAE;QAE7B,OAAO,aAAa,CAAC,QAAQ,CAC3B,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,eAAe,EACvC,OAAO,EACP,KAAK,EAAE,UAAU,EAAE,EAAE;YACnB,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC9D,MAAM,IAAI,CAAC,UAAU,CAAC,oBAAoB,CAAC,WAAW,EAAE,IAAI,CAAC,kBAAkB,kCAC1E,UAAU,KACb,8BAA8B,EAAE,KAAK,IACrC,CAAC;YACH,OAAO,IAAI,CAAC,UAAU,CAAC,gBAAgB,EAAE,CAAC;QAC5C,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 {\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n resolveTenantId,\n} from \"../util/tenantIdUtils\";\nimport {\n DeviceCodeCredentialOptions,\n DeviceCodeInfo,\n DeviceCodePromptCallback,\n} from \"./deviceCodeCredentialOptions\";\nimport { AuthenticationRecord } from \"../msal/types\";\nimport { credentialLogger } from \"../util/logging\";\nimport { ensureScopes } from \"../util/scopeUtils\";\nimport { tracingClient } from \"../util/tracing\";\nimport { MsalClient, createMsalClient } from \"../msal/nodeFlows/msalClient\";\nimport { DeveloperSignOnClientId } from \"../constants\";\n\nconst logger = credentialLogger(\"DeviceCodeCredential\");\n\n/**\n * Method that logs the user code from the DeviceCodeCredential.\n * @param deviceCodeInfo - The device code.\n */\nexport function defaultDeviceCodePromptCallback(deviceCodeInfo: DeviceCodeInfo): void {\n console.log(deviceCodeInfo.message);\n}\n\n/**\n * Enables authentication to Microsoft Entra ID using a device code\n * that the user can enter into https://microsoft.com/devicelogin.\n */\nexport class DeviceCodeCredential implements TokenCredential {\n private tenantId?: string;\n private additionallyAllowedTenantIds: string[];\n private disableAutomaticAuthentication?: boolean;\n private msalClient: MsalClient;\n private userPromptCallback: DeviceCodePromptCallback;\n\n /**\n * Creates an instance of DeviceCodeCredential with the details needed\n * to initiate the device code authorization flow with Microsoft Entra ID.\n *\n * A message will be logged, giving users a code that they can use to authenticate once they go to https://microsoft.com/devicelogin\n *\n * Developers can configure how this message is shown by passing a custom `userPromptCallback`:\n *\n * ```js\n * const credential = new DeviceCodeCredential({\n * tenantId: env.AZURE_TENANT_ID,\n * clientId: env.AZURE_CLIENT_ID,\n * userPromptCallback: (info) => {\n * console.log(\"CUSTOMIZED PROMPT CALLBACK\", info.message);\n * }\n * });\n * ```\n *\n * @param options - Options for configuring the client which makes the authentication requests.\n */\n constructor(options?: DeviceCodeCredentialOptions) {\n this.tenantId = options?.tenantId;\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.additionallyAllowedTenants,\n );\n const clientId = options?.clientId ?? DeveloperSignOnClientId;\n const tenantId = resolveTenantId(logger, options?.tenantId, clientId);\n this.userPromptCallback = options?.userPromptCallback ?? defaultDeviceCodePromptCallback;\n this.msalClient = createMsalClient(clientId, tenantId, {\n ...options,\n logger,\n tokenCredentialOptions: options || {},\n });\n this.disableAutomaticAuthentication = options?.disableAutomaticAuthentication;\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.getTokenByDeviceCode(arrayScopes, this.userPromptCallback, {\n ...newOptions,\n disableAutomaticAuthentication: this.disableAutomaticAuthentication,\n });\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 * If the token can't be retrieved silently, this method will always generate a challenge for the user.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n async authenticate(\n scopes: string | string[],\n options: GetTokenOptions = {},\n ): Promise<AuthenticationRecord | undefined> {\n return tracingClient.withSpan(\n `${this.constructor.name}.authenticate`,\n options,\n async (newOptions) => {\n const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];\n await this.msalClient.getTokenByDeviceCode(arrayScopes, this.userPromptCallback, {\n ...newOptions,\n disableAutomaticAuthentication: false, // this method should always allow user interaction\n });\n return this.msalClient.getActiveAccount();\n },\n );\n }\n}\n"]}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"deviceCodeCredentialOptions.js","sourceRoot":"","sources":["../../../src/credentials/deviceCodeCredentialOptions.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { CredentialPersistenceOptions } from \"./credentialPersistenceOptions\";\nimport { InteractiveCredentialOptions } from \"./interactiveCredentialOptions\";\n\n/**\n * Provides the user code and verification URI where the code must be\n * entered. Also provides a message to display to the user which\n * contains an instruction with these details.\n */\nexport interface DeviceCodeInfo {\n /**\n * The device code that the user must enter into the verification page.\n */\n userCode: string;\n\n /**\n * The verification URI to which the user must navigate to enter the device\n * code.\n */\n verificationUri: string;\n\n /**\n * A message that may be shown to the user to instruct them on how to enter\n * the device code in the page specified by the verification URI.\n */\n message: string;\n}\n\n/**\n * Defines the signature of a callback which will be passed to\n * DeviceCodeCredential for the purpose of displaying authentication\n * details to the user.\n */\nexport type DeviceCodePromptCallback = (deviceCodeInfo: DeviceCodeInfo) => void;\n\n/**\n * Defines options for the InteractiveBrowserCredential class for Node.js.\n */\nexport interface DeviceCodeCredentialOptions\n extends InteractiveCredentialOptions,\n CredentialPersistenceOptions {\n /**\n * The Microsoft Entra tenant (directory) ID.\n */\n tenantId?: string;\n /**\n *
|
1
|
+
{"version":3,"file":"deviceCodeCredentialOptions.js","sourceRoot":"","sources":["../../../src/credentials/deviceCodeCredentialOptions.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { CredentialPersistenceOptions } from \"./credentialPersistenceOptions\";\nimport { InteractiveCredentialOptions } from \"./interactiveCredentialOptions\";\n\n/**\n * Provides the user code and verification URI where the code must be\n * entered. Also provides a message to display to the user which\n * contains an instruction with these details.\n */\nexport interface DeviceCodeInfo {\n /**\n * The device code that the user must enter into the verification page.\n */\n userCode: string;\n\n /**\n * The verification URI to which the user must navigate to enter the device\n * code.\n */\n verificationUri: string;\n\n /**\n * A message that may be shown to the user to instruct them on how to enter\n * the device code in the page specified by the verification URI.\n */\n message: string;\n}\n\n/**\n * Defines the signature of a callback which will be passed to\n * DeviceCodeCredential for the purpose of displaying authentication\n * details to the user.\n */\nexport type DeviceCodePromptCallback = (deviceCodeInfo: DeviceCodeInfo) => void;\n\n/**\n * Defines options for the InteractiveBrowserCredential class for Node.js.\n */\nexport interface DeviceCodeCredentialOptions\n extends InteractiveCredentialOptions,\n CredentialPersistenceOptions {\n /**\n * The Microsoft Entra tenant (directory) ID.\n */\n tenantId?: string;\n /**\n * Client ID of the Microsoft Entra application that users will sign into.\n * It is recommended that developers register their applications and assign appropriate roles.\n * For more information, visit https://aka.ms/identity/AppRegistrationAndRoleAssignment.\n * If not specified, users will authenticate to an Azure development application,\n * which is not recommended for production scenarios.\n */\n clientId?: string;\n /**\n * A callback function that will be invoked to show {@link DeviceCodeInfo} to the user.\n * If left unassigned, we will automatically log the device code information\n * and the authentication instructions in the console.\n */\n userPromptCallback?: DeviceCodePromptCallback;\n}\n"]}
|
@@ -23,6 +23,7 @@ export const AllSupportedEnvironmentVariables = [
|
|
23
23
|
"AZURE_USERNAME",
|
24
24
|
"AZURE_PASSWORD",
|
25
25
|
"AZURE_ADDITIONALLY_ALLOWED_TENANTS",
|
26
|
+
"AZURE_CLIENT_SEND_CERTIFICATE_CHAIN",
|
26
27
|
];
|
27
28
|
function getAdditionallyAllowedTenants() {
|
28
29
|
var _a;
|
@@ -31,6 +32,13 @@ function getAdditionallyAllowedTenants() {
|
|
31
32
|
}
|
32
33
|
const credentialName = "EnvironmentCredential";
|
33
34
|
const logger = credentialLogger(credentialName);
|
35
|
+
export function getSendCertificateChain() {
|
36
|
+
var _a;
|
37
|
+
const sendCertificateChain = ((_a = process.env.AZURE_CLIENT_SEND_CERTIFICATE_CHAIN) !== null && _a !== void 0 ? _a : "").toLowerCase();
|
38
|
+
const result = sendCertificateChain === "true" || sendCertificateChain === "1";
|
39
|
+
logger.verbose(`AZURE_CLIENT_SEND_CERTIFICATE_CHAIN: ${process.env.AZURE_CLIENT_SEND_CERTIFICATE_CHAIN}; sendCertificateChain: ${result}`);
|
40
|
+
return result;
|
41
|
+
}
|
34
42
|
/**
|
35
43
|
* Enables authentication to Microsoft Entra ID using a client secret or certificate, or as a user
|
36
44
|
* with a username and password.
|
@@ -50,6 +58,7 @@ export class EnvironmentCredential {
|
|
50
58
|
* - `AZURE_CLIENT_SECRET`: A client secret that was generated for the App Registration.
|
51
59
|
* - `AZURE_CLIENT_CERTIFICATE_PATH`: The path to a PEM certificate to use during the authentication, instead of the client secret.
|
52
60
|
* - `AZURE_CLIENT_CERTIFICATE_PASSWORD`: (optional) password for the certificate file.
|
61
|
+
* - `AZURE_CLIENT_SEND_CERTIFICATE_CHAIN`: (optional) indicates that the certificate chain should be set in x5c header to support subject name / issuer based authentication.
|
53
62
|
*
|
54
63
|
* Alternatively, users can provide environment variables for username and password authentication:
|
55
64
|
* - `AZURE_USERNAME`: Username to authenticate with.
|
@@ -67,7 +76,8 @@ export class EnvironmentCredential {
|
|
67
76
|
logger.info(`Found the following environment variables: ${assigned}`);
|
68
77
|
const tenantId = process.env.AZURE_TENANT_ID, clientId = process.env.AZURE_CLIENT_ID, clientSecret = process.env.AZURE_CLIENT_SECRET;
|
69
78
|
const additionallyAllowedTenantIds = getAdditionallyAllowedTenants();
|
70
|
-
const
|
79
|
+
const sendCertificateChain = getSendCertificateChain();
|
80
|
+
const newOptions = Object.assign(Object.assign({}, options), { additionallyAllowedTenantIds, sendCertificateChain });
|
71
81
|
if (tenantId) {
|
72
82
|
checkTenantId(logger, tenantId);
|
73
83
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"environmentCredential.js","sourceRoot":"","sources":["../../../src/credentials/environmentCredential.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport { AuthenticationError, CredentialUnavailableError } from \"../errors\";\nimport { credentialLogger, formatError, formatSuccess, processEnvVars } from \"../util/logging\";\n\nimport { ClientCertificateCredential } from \"./clientCertificateCredential\";\nimport { ClientSecretCredential } from \"./clientSecretCredential\";\nimport { EnvironmentCredentialOptions } from \"./environmentCredentialOptions\";\nimport { UsernamePasswordCredential } from \"./usernamePasswordCredential\";\nimport { checkTenantId } from \"../util/tenantIdUtils\";\nimport { tracingClient } from \"../util/tracing\";\n\n/**\n * Contains the list of all supported environment variable names so that an\n * appropriate error message can be generated when no credentials can be\n * configured.\n *\n * @internal\n */\nexport const AllSupportedEnvironmentVariables = [\n \"AZURE_TENANT_ID\",\n \"AZURE_CLIENT_ID\",\n \"AZURE_CLIENT_SECRET\",\n \"AZURE_CLIENT_CERTIFICATE_PATH\",\n \"AZURE_CLIENT_CERTIFICATE_PASSWORD\",\n \"AZURE_USERNAME\",\n \"AZURE_PASSWORD\",\n \"AZURE_ADDITIONALLY_ALLOWED_TENANTS\",\n];\n\nfunction getAdditionallyAllowedTenants(): string[] {\n const additionallyAllowedValues = process.env.AZURE_ADDITIONALLY_ALLOWED_TENANTS ?? \"\";\n return additionallyAllowedValues.split(\";\");\n}\n\nconst credentialName = \"EnvironmentCredential\";\nconst logger = credentialLogger(credentialName);\n\n/**\n * Enables authentication to Microsoft Entra ID using a client secret or certificate, or as a user\n * with a username and password.\n */\nexport class EnvironmentCredential implements TokenCredential {\n private _credential?:\n | ClientSecretCredential\n | ClientCertificateCredential\n | UsernamePasswordCredential = undefined;\n /**\n * Creates an instance of the EnvironmentCredential class and decides what credential to use depending on the available environment variables.\n *\n * Required environment variables:\n * - `AZURE_TENANT_ID`: The Microsoft Entra tenant (directory) ID.\n * - `AZURE_CLIENT_ID`: The client (application) ID of an App Registration in the tenant.\n *\n * If setting the AZURE_TENANT_ID, then you can also set the additionally allowed tenants\n * - `AZURE_ADDITIONALLY_ALLOWED_TENANTS`: For multi-tenant applications, specifies additional tenants for which the credential may acquire tokens with a single semicolon delimited string. Use * to allow all tenants.\n *\n * Environment variables used for client credential authentication:\n * - `AZURE_CLIENT_SECRET`: A client secret that was generated for the App Registration.\n * - `AZURE_CLIENT_CERTIFICATE_PATH`: The path to a PEM certificate to use during the authentication, instead of the client secret.\n * - `AZURE_CLIENT_CERTIFICATE_PASSWORD`: (optional) password for the certificate file.\n *\n * Alternatively, users can provide environment variables for username and password authentication:\n * - `AZURE_USERNAME`: Username to authenticate with.\n * - `AZURE_PASSWORD`: Password to authenticate with.\n *\n * If the environment variables required to perform the authentication are missing, a {@link CredentialUnavailableError} will be thrown.\n * If the authentication fails, or if there's an unknown error, an {@link AuthenticationError} will be thrown.\n *\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(options?: EnvironmentCredentialOptions) {\n // Keep track of any missing environment variables for error details\n\n const assigned = processEnvVars(AllSupportedEnvironmentVariables).assigned.join(\", \");\n logger.info(`Found the following environment variables: ${assigned}`);\n\n const tenantId = process.env.AZURE_TENANT_ID,\n clientId = process.env.AZURE_CLIENT_ID,\n clientSecret = process.env.AZURE_CLIENT_SECRET;\n\n const additionallyAllowedTenantIds = getAdditionallyAllowedTenants();\n const newOptions = { ...options, additionallyAllowedTenantIds };\n\n if (tenantId) {\n checkTenantId(logger, tenantId);\n }\n\n if (tenantId && clientId && clientSecret) {\n logger.info(\n `Invoking ClientSecretCredential with tenant ID: ${tenantId}, clientId: ${clientId} and clientSecret: [REDACTED]`,\n );\n this._credential = new ClientSecretCredential(tenantId, clientId, clientSecret, newOptions);\n return;\n }\n\n const certificatePath = process.env.AZURE_CLIENT_CERTIFICATE_PATH;\n const certificatePassword = process.env.AZURE_CLIENT_CERTIFICATE_PASSWORD;\n if (tenantId && clientId && certificatePath) {\n logger.info(\n `Invoking ClientCertificateCredential with tenant ID: ${tenantId}, clientId: ${clientId} and certificatePath: ${certificatePath}`,\n );\n this._credential = new ClientCertificateCredential(\n tenantId,\n clientId,\n { certificatePath, certificatePassword },\n newOptions,\n );\n return;\n }\n\n const username = process.env.AZURE_USERNAME;\n const password = process.env.AZURE_PASSWORD;\n if (tenantId && clientId && username && password) {\n logger.info(\n `Invoking UsernamePasswordCredential with tenant ID: ${tenantId}, clientId: ${clientId} and username: ${username}`,\n );\n this._credential = new UsernamePasswordCredential(\n tenantId,\n clientId,\n username,\n password,\n newOptions,\n );\n }\n }\n\n /**\n * Authenticates with Microsoft Entra ID and returns an access token if successful.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - Optional parameters. See {@link GetTokenOptions}.\n */\n async getToken(scopes: string | string[], options: GetTokenOptions = {}): Promise<AccessToken> {\n return tracingClient.withSpan(`${credentialName}.getToken`, options, async (newOptions) => {\n if (this._credential) {\n try {\n const result = await this._credential.getToken(scopes, newOptions);\n logger.getToken.info(formatSuccess(scopes));\n return result;\n } catch (err: any) {\n const authenticationError = new AuthenticationError(400, {\n error: `${credentialName} authentication failed. To troubleshoot, visit https://aka.ms/azsdk/js/identity/environmentcredential/troubleshoot.`,\n error_description: err.message.toString().split(\"More details:\").join(\"\"),\n });\n logger.getToken.info(formatError(scopes, authenticationError));\n throw authenticationError;\n }\n }\n throw new CredentialUnavailableError(\n `${credentialName} is unavailable. No underlying credential could be used. To troubleshoot, visit https://aka.ms/azsdk/js/identity/environmentcredential/troubleshoot.`,\n );\n });\n }\n}\n"]}
|
1
|
+
{"version":3,"file":"environmentCredential.js","sourceRoot":"","sources":["../../../src/credentials/environmentCredential.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport { AuthenticationError, CredentialUnavailableError } from \"../errors\";\nimport { credentialLogger, formatError, formatSuccess, processEnvVars } from \"../util/logging\";\n\nimport { ClientCertificateCredential } from \"./clientCertificateCredential\";\nimport { ClientSecretCredential } from \"./clientSecretCredential\";\nimport { EnvironmentCredentialOptions } from \"./environmentCredentialOptions\";\nimport { UsernamePasswordCredential } from \"./usernamePasswordCredential\";\nimport { checkTenantId } from \"../util/tenantIdUtils\";\nimport { tracingClient } from \"../util/tracing\";\n\n/**\n * Contains the list of all supported environment variable names so that an\n * appropriate error message can be generated when no credentials can be\n * configured.\n *\n * @internal\n */\nexport const AllSupportedEnvironmentVariables = [\n \"AZURE_TENANT_ID\",\n \"AZURE_CLIENT_ID\",\n \"AZURE_CLIENT_SECRET\",\n \"AZURE_CLIENT_CERTIFICATE_PATH\",\n \"AZURE_CLIENT_CERTIFICATE_PASSWORD\",\n \"AZURE_USERNAME\",\n \"AZURE_PASSWORD\",\n \"AZURE_ADDITIONALLY_ALLOWED_TENANTS\",\n \"AZURE_CLIENT_SEND_CERTIFICATE_CHAIN\",\n];\n\nfunction getAdditionallyAllowedTenants(): string[] {\n const additionallyAllowedValues = process.env.AZURE_ADDITIONALLY_ALLOWED_TENANTS ?? \"\";\n return additionallyAllowedValues.split(\";\");\n}\n\nconst credentialName = \"EnvironmentCredential\";\nconst logger = credentialLogger(credentialName);\n\nexport function getSendCertificateChain(): boolean {\n const sendCertificateChain = (\n process.env.AZURE_CLIENT_SEND_CERTIFICATE_CHAIN ?? \"\"\n ).toLowerCase();\n const result = sendCertificateChain === \"true\" || sendCertificateChain === \"1\";\n logger.verbose(\n `AZURE_CLIENT_SEND_CERTIFICATE_CHAIN: ${process.env.AZURE_CLIENT_SEND_CERTIFICATE_CHAIN}; sendCertificateChain: ${result}`,\n );\n return result;\n}\n\n/**\n * Enables authentication to Microsoft Entra ID using a client secret or certificate, or as a user\n * with a username and password.\n */\nexport class EnvironmentCredential implements TokenCredential {\n private _credential?:\n | ClientSecretCredential\n | ClientCertificateCredential\n | UsernamePasswordCredential = undefined;\n /**\n * Creates an instance of the EnvironmentCredential class and decides what credential to use depending on the available environment variables.\n *\n * Required environment variables:\n * - `AZURE_TENANT_ID`: The Microsoft Entra tenant (directory) ID.\n * - `AZURE_CLIENT_ID`: The client (application) ID of an App Registration in the tenant.\n *\n * If setting the AZURE_TENANT_ID, then you can also set the additionally allowed tenants\n * - `AZURE_ADDITIONALLY_ALLOWED_TENANTS`: For multi-tenant applications, specifies additional tenants for which the credential may acquire tokens with a single semicolon delimited string. Use * to allow all tenants.\n *\n * Environment variables used for client credential authentication:\n * - `AZURE_CLIENT_SECRET`: A client secret that was generated for the App Registration.\n * - `AZURE_CLIENT_CERTIFICATE_PATH`: The path to a PEM certificate to use during the authentication, instead of the client secret.\n * - `AZURE_CLIENT_CERTIFICATE_PASSWORD`: (optional) password for the certificate file.\n * - `AZURE_CLIENT_SEND_CERTIFICATE_CHAIN`: (optional) indicates that the certificate chain should be set in x5c header to support subject name / issuer based authentication.\n *\n * Alternatively, users can provide environment variables for username and password authentication:\n * - `AZURE_USERNAME`: Username to authenticate with.\n * - `AZURE_PASSWORD`: Password to authenticate with.\n *\n * If the environment variables required to perform the authentication are missing, a {@link CredentialUnavailableError} will be thrown.\n * If the authentication fails, or if there's an unknown error, an {@link AuthenticationError} will be thrown.\n *\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(options?: EnvironmentCredentialOptions) {\n // Keep track of any missing environment variables for error details\n\n const assigned = processEnvVars(AllSupportedEnvironmentVariables).assigned.join(\", \");\n logger.info(`Found the following environment variables: ${assigned}`);\n\n const tenantId = process.env.AZURE_TENANT_ID,\n clientId = process.env.AZURE_CLIENT_ID,\n clientSecret = process.env.AZURE_CLIENT_SECRET;\n\n const additionallyAllowedTenantIds = getAdditionallyAllowedTenants();\n const sendCertificateChain = getSendCertificateChain();\n const newOptions = { ...options, additionallyAllowedTenantIds, sendCertificateChain };\n\n if (tenantId) {\n checkTenantId(logger, tenantId);\n }\n\n if (tenantId && clientId && clientSecret) {\n logger.info(\n `Invoking ClientSecretCredential with tenant ID: ${tenantId}, clientId: ${clientId} and clientSecret: [REDACTED]`,\n );\n this._credential = new ClientSecretCredential(tenantId, clientId, clientSecret, newOptions);\n return;\n }\n\n const certificatePath = process.env.AZURE_CLIENT_CERTIFICATE_PATH;\n const certificatePassword = process.env.AZURE_CLIENT_CERTIFICATE_PASSWORD;\n if (tenantId && clientId && certificatePath) {\n logger.info(\n `Invoking ClientCertificateCredential with tenant ID: ${tenantId}, clientId: ${clientId} and certificatePath: ${certificatePath}`,\n );\n this._credential = new ClientCertificateCredential(\n tenantId,\n clientId,\n { certificatePath, certificatePassword },\n newOptions,\n );\n return;\n }\n\n const username = process.env.AZURE_USERNAME;\n const password = process.env.AZURE_PASSWORD;\n if (tenantId && clientId && username && password) {\n logger.info(\n `Invoking UsernamePasswordCredential with tenant ID: ${tenantId}, clientId: ${clientId} and username: ${username}`,\n );\n this._credential = new UsernamePasswordCredential(\n tenantId,\n clientId,\n username,\n password,\n newOptions,\n );\n }\n }\n\n /**\n * Authenticates with Microsoft Entra ID and returns an access token if successful.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - Optional parameters. See {@link GetTokenOptions}.\n */\n async getToken(scopes: string | string[], options: GetTokenOptions = {}): Promise<AccessToken> {\n return tracingClient.withSpan(`${credentialName}.getToken`, options, async (newOptions) => {\n if (this._credential) {\n try {\n const result = await this._credential.getToken(scopes, newOptions);\n logger.getToken.info(formatSuccess(scopes));\n return result;\n } catch (err: any) {\n const authenticationError = new AuthenticationError(400, {\n error: `${credentialName} authentication failed. To troubleshoot, visit https://aka.ms/azsdk/js/identity/environmentcredential/troubleshoot.`,\n error_description: err.message.toString().split(\"More details:\").join(\"\"),\n });\n logger.getToken.info(formatError(scopes, authenticationError));\n throw authenticationError;\n }\n }\n throw new CredentialUnavailableError(\n `${credentialName} is unavailable. No underlying credential could be used. To troubleshoot, visit https://aka.ms/azsdk/js/identity/environmentcredential/troubleshoot.`,\n );\n });\n }\n}\n"]}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"interactiveBrowserCredential.browser.js","sourceRoot":"","sources":["../../../src/credentials/interactiveBrowserCredential.browser.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAOlC,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EACL,yBAAyB,EACzB,mCAAmC,GACpC,MAAM,uBAAuB,CAAC;
|
1
|
+
{"version":3,"file":"interactiveBrowserCredential.browser.js","sourceRoot":"","sources":["../../../src/credentials/interactiveBrowserCredential.browser.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 InteractiveBrowserCredentialInBrowserOptions,\n InteractiveBrowserCredentialNodeOptions,\n} from \"./interactiveBrowserCredentialOptions\";\nimport { credentialLogger, formatError } from \"../util/logging\";\nimport {\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n} from \"../util/tenantIdUtils\";\n\nimport { AuthenticationRecord } from \"../msal/types\";\nimport { MSALAuthCode } from \"../msal/browserFlows/msalAuthCode\";\nimport { MsalBrowserFlowOptions } from \"../msal/browserFlows/msalBrowserCommon\";\nimport { MsalFlow } from \"../msal/browserFlows/flows\";\nimport { ensureScopes } from \"../util/scopeUtils\";\nimport { tracingClient } from \"../util/tracing\";\n\nconst logger = credentialLogger(\"InteractiveBrowserCredential\");\n\n/**\n * Enables authentication to Microsoft Entra ID inside of the web browser\n * using the interactive login flow.\n */\nexport class InteractiveBrowserCredential implements TokenCredential {\n private tenantId?: string;\n private additionallyAllowedTenantIds: string[];\n private msalFlow: MsalFlow;\n private disableAutomaticAuthentication?: boolean;\n\n /**\n * Creates an instance of the InteractiveBrowserCredential with the\n * details needed to authenticate against Microsoft Entra ID with\n * a user identity.\n *\n * This credential uses the [Authorization Code Flow](https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow).\n * On Node.js, it will open a browser window while it listens for a redirect response from the authentication service.\n * On browsers, it authenticates via popups. The `loginStyle` optional parameter can be set to `redirect` to authenticate by redirecting the user to an Azure secure login page, which then will redirect the user back to the web application where the authentication started.\n *\n * It's recommended that the Microsoft Entra Applications used are configured to authenticate using Single Page Applications.\n * More information here: [link](https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-spa-app-registration#redirect-uri-msaljs-20-with-auth-code-flow).\n *\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n options: InteractiveBrowserCredentialInBrowserOptions | InteractiveBrowserCredentialNodeOptions,\n ) {\n if (!options?.clientId) {\n const error = new Error(\n \"The parameter `clientId` cannot be left undefined for the `InteractiveBrowserCredential`\",\n );\n logger.info(formatError(\"\", error));\n throw error;\n }\n\n this.tenantId = options?.tenantId;\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.additionallyAllowedTenants,\n );\n\n const browserOptions = options as InteractiveBrowserCredentialInBrowserOptions;\n const loginStyle = browserOptions.loginStyle || \"popup\";\n const loginStyles = [\"redirect\", \"popup\"];\n\n if (loginStyles.indexOf(loginStyle) === -1) {\n const error = new Error(\n `Invalid loginStyle: ${\n browserOptions.loginStyle\n }. Should be any of the following: ${loginStyles.join(\", \")}.`,\n );\n logger.info(formatError(\"\", error));\n throw error;\n }\n\n const msalOptions: MsalBrowserFlowOptions = {\n ...options,\n tokenCredentialOptions: options,\n logger,\n loginStyle: loginStyle,\n redirectUri:\n typeof options.redirectUri === \"function\" ? options.redirectUri() : options.redirectUri,\n };\n\n this.msalFlow = new MSALAuthCode(msalOptions);\n this.disableAutomaticAuthentication = options?.disableAutomaticAuthentication;\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 const tenantId = processMultiTenantRequest(\n this.tenantId,\n newOptions,\n this.additionallyAllowedTenantIds,\n );\n newOptions.tenantId = tenantId;\n\n const arrayScopes = ensureScopes(scopes);\n return this.msalFlow.getToken(arrayScopes, {\n ...newOptions,\n disableAutomaticAuthentication: this.disableAutomaticAuthentication,\n });\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 * If the token can't be retrieved silently, this method will require 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 authenticate(\n scopes: string | string[],\n options: GetTokenOptions = {},\n ): Promise<AuthenticationRecord | undefined> {\n return tracingClient.withSpan(\n `${this.constructor.name}.authenticate`,\n options,\n async (newOptions) => {\n const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];\n await this.msalFlow.getToken(arrayScopes, newOptions);\n return this.msalFlow.getActiveAccount();\n },\n );\n }\n}\n"]}
|
@@ -71,7 +71,7 @@ export class InteractiveBrowserCredential {
|
|
71
71
|
* Authenticates with Microsoft Entra ID and returns an access token if successful.
|
72
72
|
* If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.
|
73
73
|
*
|
74
|
-
* If the token can't be retrieved silently, this method will
|
74
|
+
* If the token can't be retrieved silently, this method will always generate a challenge for the user.
|
75
75
|
*
|
76
76
|
* On Node.js, this credential has [Proof Key for Code Exchange (PKCE)](https://datatracker.ietf.org/doc/html/rfc7636) enabled by default.
|
77
77
|
* PKCE is a security feature that mitigates authentication code interception attacks.
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"interactiveBrowserCredential.js","sourceRoot":"","sources":["../../../src/credentials/interactiveBrowserCredential.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/* eslint-disable @typescript-eslint/no-unused-vars */\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport {\n InteractiveBrowserCredentialInBrowserOptions,\n InteractiveBrowserCredentialNodeOptions,\n} from \"./interactiveBrowserCredentialOptions\";\nimport {\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n resolveTenantId,\n} from \"../util/tenantIdUtils\";\n\nimport { AuthenticationRecord } from \"../msal/types\";\nimport { credentialLogger } from \"../util/logging\";\nimport { ensureScopes } from \"../util/scopeUtils\";\nimport { tracingClient } from \"../util/tracing\";\nimport { MsalClient, MsalClientOptions, createMsalClient } from \"../msal/nodeFlows/msalClient\";\nimport { DeveloperSignOnClientId } from \"../constants\";\n\nconst logger = credentialLogger(\"InteractiveBrowserCredential\");\n\n/**\n * Enables authentication to Microsoft Entra ID inside of the web browser\n * using the interactive login flow.\n */\nexport class InteractiveBrowserCredential implements TokenCredential {\n private tenantId?: string;\n private additionallyAllowedTenantIds: string[];\n private msalClient: MsalClient;\n private disableAutomaticAuthentication?: boolean;\n private browserCustomizationOptions: InteractiveBrowserCredentialNodeOptions[\"browserCustomizationOptions\"];\n private loginHint?: string;\n\n /**\n * Creates an instance of InteractiveBrowserCredential with the details needed.\n *\n * This credential uses the [Authorization Code Flow](https://learn.microsoft.com/entra/identity-platform/v2-oauth2-auth-code-flow).\n * On Node.js, it will open a browser window while it listens for a redirect response from the authentication service.\n * On browsers, it authenticates via popups. The `loginStyle` optional parameter can be set to `redirect` to authenticate by redirecting the user to an Azure secure login page, which then will redirect the user back to the web application where the authentication started.\n *\n * For Node.js, if a `clientId` is provided, the Microsoft Entra application will need to be configured to have a \"Mobile and desktop applications\" redirect endpoint.\n * Follow our guide on [setting up Redirect URIs for Desktop apps that calls to web APIs](https://learn.microsoft.com/entra/identity-platform/scenario-desktop-app-registration#redirect-uris).\n *\n * @param options - Options for configuring the client which makes the authentication requests.\n */\n constructor(\n options: InteractiveBrowserCredentialNodeOptions | InteractiveBrowserCredentialInBrowserOptions,\n ) {\n this.tenantId = resolveTenantId(logger, options.tenantId, options.clientId);\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.additionallyAllowedTenants,\n );\n\n const msalClientOptions: MsalClientOptions = {\n ...options,\n tokenCredentialOptions: options,\n logger,\n };\n const ibcNodeOptions = options as InteractiveBrowserCredentialNodeOptions;\n this.browserCustomizationOptions = ibcNodeOptions.browserCustomizationOptions;\n this.loginHint = ibcNodeOptions.loginHint;\n if (ibcNodeOptions?.brokerOptions?.enabled) {\n if (!ibcNodeOptions?.brokerOptions?.parentWindowHandle) {\n throw new Error(\n \"In order to do WAM authentication, `parentWindowHandle` under `brokerOptions` is a required parameter\",\n );\n } else {\n msalClientOptions.brokerOptions = {\n enabled: true,\n parentWindowHandle: ibcNodeOptions.brokerOptions.parentWindowHandle,\n legacyEnableMsaPassthrough: ibcNodeOptions.brokerOptions?.legacyEnableMsaPassthrough,\n useDefaultBrokerAccount: ibcNodeOptions.brokerOptions?.useDefaultBrokerAccount,\n };\n }\n }\n this.msalClient = createMsalClient(\n options.clientId ?? DeveloperSignOnClientId,\n this.tenantId,\n msalClientOptions,\n );\n this.disableAutomaticAuthentication = options?.disableAutomaticAuthentication;\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.getTokenByInteractiveRequest(arrayScopes, {\n ...newOptions,\n disableAutomaticAuthentication: this.disableAutomaticAuthentication,\n browserCustomizationOptions: this.browserCustomizationOptions,\n loginHint: this.loginHint,\n });\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 * If the token can't be retrieved silently, this method will
|
1
|
+
{"version":3,"file":"interactiveBrowserCredential.js","sourceRoot":"","sources":["../../../src/credentials/interactiveBrowserCredential.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/* eslint-disable @typescript-eslint/no-unused-vars */\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport {\n InteractiveBrowserCredentialInBrowserOptions,\n InteractiveBrowserCredentialNodeOptions,\n} from \"./interactiveBrowserCredentialOptions\";\nimport {\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n resolveTenantId,\n} from \"../util/tenantIdUtils\";\n\nimport { AuthenticationRecord } from \"../msal/types\";\nimport { credentialLogger } from \"../util/logging\";\nimport { ensureScopes } from \"../util/scopeUtils\";\nimport { tracingClient } from \"../util/tracing\";\nimport { MsalClient, MsalClientOptions, createMsalClient } from \"../msal/nodeFlows/msalClient\";\nimport { DeveloperSignOnClientId } from \"../constants\";\n\nconst logger = credentialLogger(\"InteractiveBrowserCredential\");\n\n/**\n * Enables authentication to Microsoft Entra ID inside of the web browser\n * using the interactive login flow.\n */\nexport class InteractiveBrowserCredential implements TokenCredential {\n private tenantId?: string;\n private additionallyAllowedTenantIds: string[];\n private msalClient: MsalClient;\n private disableAutomaticAuthentication?: boolean;\n private browserCustomizationOptions: InteractiveBrowserCredentialNodeOptions[\"browserCustomizationOptions\"];\n private loginHint?: string;\n\n /**\n * Creates an instance of InteractiveBrowserCredential with the details needed.\n *\n * This credential uses the [Authorization Code Flow](https://learn.microsoft.com/entra/identity-platform/v2-oauth2-auth-code-flow).\n * On Node.js, it will open a browser window while it listens for a redirect response from the authentication service.\n * On browsers, it authenticates via popups. The `loginStyle` optional parameter can be set to `redirect` to authenticate by redirecting the user to an Azure secure login page, which then will redirect the user back to the web application where the authentication started.\n *\n * For Node.js, if a `clientId` is provided, the Microsoft Entra application will need to be configured to have a \"Mobile and desktop applications\" redirect endpoint.\n * Follow our guide on [setting up Redirect URIs for Desktop apps that calls to web APIs](https://learn.microsoft.com/entra/identity-platform/scenario-desktop-app-registration#redirect-uris).\n *\n * @param options - Options for configuring the client which makes the authentication requests.\n */\n constructor(\n options: InteractiveBrowserCredentialNodeOptions | InteractiveBrowserCredentialInBrowserOptions,\n ) {\n this.tenantId = resolveTenantId(logger, options.tenantId, options.clientId);\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.additionallyAllowedTenants,\n );\n\n const msalClientOptions: MsalClientOptions = {\n ...options,\n tokenCredentialOptions: options,\n logger,\n };\n const ibcNodeOptions = options as InteractiveBrowserCredentialNodeOptions;\n this.browserCustomizationOptions = ibcNodeOptions.browserCustomizationOptions;\n this.loginHint = ibcNodeOptions.loginHint;\n if (ibcNodeOptions?.brokerOptions?.enabled) {\n if (!ibcNodeOptions?.brokerOptions?.parentWindowHandle) {\n throw new Error(\n \"In order to do WAM authentication, `parentWindowHandle` under `brokerOptions` is a required parameter\",\n );\n } else {\n msalClientOptions.brokerOptions = {\n enabled: true,\n parentWindowHandle: ibcNodeOptions.brokerOptions.parentWindowHandle,\n legacyEnableMsaPassthrough: ibcNodeOptions.brokerOptions?.legacyEnableMsaPassthrough,\n useDefaultBrokerAccount: ibcNodeOptions.brokerOptions?.useDefaultBrokerAccount,\n };\n }\n }\n this.msalClient = createMsalClient(\n options.clientId ?? DeveloperSignOnClientId,\n this.tenantId,\n msalClientOptions,\n );\n this.disableAutomaticAuthentication = options?.disableAutomaticAuthentication;\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.getTokenByInteractiveRequest(arrayScopes, {\n ...newOptions,\n disableAutomaticAuthentication: this.disableAutomaticAuthentication,\n browserCustomizationOptions: this.browserCustomizationOptions,\n loginHint: this.loginHint,\n });\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 * If the token can't be retrieved silently, this method will always generate a challenge for the user.\n *\n * On Node.js, this credential has [Proof Key for Code Exchange (PKCE)](https://datatracker.ietf.org/doc/html/rfc7636) enabled by default.\n * PKCE is a security feature that mitigates authentication code interception attacks.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n async authenticate(\n scopes: string | string[],\n options: GetTokenOptions = {},\n ): Promise<AuthenticationRecord | undefined> {\n return tracingClient.withSpan(\n `${this.constructor.name}.authenticate`,\n options,\n async (newOptions) => {\n const arrayScopes = ensureScopes(scopes);\n await this.msalClient.getTokenByInteractiveRequest(arrayScopes, {\n ...newOptions,\n disableAutomaticAuthentication: false, // this method should always allow user interaction\n browserCustomizationOptions: this.browserCustomizationOptions,\n loginHint: this.loginHint,\n });\n return this.msalClient.getActiveAccount();\n },\n );\n }\n}\n"]}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"interactiveBrowserCredentialOptions.js","sourceRoot":"","sources":["../../../src/credentials/interactiveBrowserCredentialOptions.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { BrowserCustomizationOptions } from \"./browserCustomizationOptions\";\nimport { BrokerAuthOptions } from \"./brokerAuthOptions\";\nimport { CredentialPersistenceOptions } from \"./credentialPersistenceOptions\";\nimport { InteractiveCredentialOptions } from \"./interactiveCredentialOptions\";\n\n/**\n * (Browser-only feature)\n * The \"login style\" to use in the authentication flow:\n * - \"redirect\" redirects the user to the authentication page and then\n * redirects them back to the page once authentication is completed.\n * - \"popup\" opens a new browser window through with the redirect flow\n * is initiated. The user's existing browser window does not leave\n * the current page\n */\nexport type BrowserLoginStyle = \"redirect\" | \"popup\";\n\n/**\n * Defines the common options for the InteractiveBrowserCredential class.\n */\nexport interface InteractiveBrowserCredentialNodeOptions\n extends InteractiveCredentialOptions,\n CredentialPersistenceOptions,\n BrowserCustomizationOptions,\n BrokerAuthOptions {\n /**\n * Gets the redirect URI of the application. This should be same as the value\n * in the application registration portal. Defaults to `window.location.href`.\n * This field is no longer required for Node.js.\n */\n redirectUri?: string | (() => string);\n\n /**\n * The Microsoft Entra tenant (directory) ID.\n */\n tenantId?: string;\n\n /**\n * The
|
1
|
+
{"version":3,"file":"interactiveBrowserCredentialOptions.js","sourceRoot":"","sources":["../../../src/credentials/interactiveBrowserCredentialOptions.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { BrowserCustomizationOptions } from \"./browserCustomizationOptions\";\nimport { BrokerAuthOptions } from \"./brokerAuthOptions\";\nimport { CredentialPersistenceOptions } from \"./credentialPersistenceOptions\";\nimport { InteractiveCredentialOptions } from \"./interactiveCredentialOptions\";\n\n/**\n * (Browser-only feature)\n * The \"login style\" to use in the authentication flow:\n * - \"redirect\" redirects the user to the authentication page and then\n * redirects them back to the page once authentication is completed.\n * - \"popup\" opens a new browser window through with the redirect flow\n * is initiated. The user's existing browser window does not leave\n * the current page\n */\nexport type BrowserLoginStyle = \"redirect\" | \"popup\";\n\n/**\n * Defines the common options for the InteractiveBrowserCredential class.\n */\nexport interface InteractiveBrowserCredentialNodeOptions\n extends InteractiveCredentialOptions,\n CredentialPersistenceOptions,\n BrowserCustomizationOptions,\n BrokerAuthOptions {\n /**\n * Gets the redirect URI of the application. This should be same as the value\n * in the application registration portal. Defaults to `window.location.href`.\n * This field is no longer required for Node.js.\n */\n redirectUri?: string | (() => string);\n\n /**\n * The Microsoft Entra tenant (directory) ID.\n */\n tenantId?: string;\n\n /**\n * The Client ID of the Microsoft Entra application that users will sign into.\n * It is recommended that developers register their applications and assign appropriate roles.\n * For more information, visit https://aka.ms/identity/AppRegistrationAndRoleAssignment.\n * If not specified, users will authenticate to an Azure development application,\n * which is not recommended for production scenarios.\n */\n clientId?: string;\n\n /**\n * loginHint allows a user name to be pre-selected for interactive logins.\n * Setting this option skips the account selection prompt and immediately attempts to login with the specified account.\n */\n loginHint?: string;\n}\n\n/**\n * Defines the common options for the InteractiveBrowserCredential class.\n */\nexport interface InteractiveBrowserCredentialInBrowserOptions extends InteractiveCredentialOptions {\n /**\n * Gets the redirect URI of the application. This should be same as the value\n * in the application registration portal. Defaults to `window.location.href`.\n * This field is no longer required for Node.js.\n */\n redirectUri?: string | (() => string);\n\n /**\n * The Microsoft Entra tenant (directory) ID.\n */\n tenantId?: string;\n\n /**\n * The Client ID of the Microsoft Entra application that users will sign into.\n * This parameter is required on the browser.\n * Developers need to register their applications and assign appropriate roles.\n * For more information, visit https://aka.ms/identity/AppRegistrationAndRoleAssignment.\n */\n clientId: string;\n\n /**\n * Specifies whether a redirect or a popup window should be used to\n * initiate the user authentication flow. Possible values are \"redirect\"\n * or \"popup\" (default) for browser and \"popup\" (default) for node.\n *\n */\n loginStyle?: BrowserLoginStyle;\n\n /**\n * loginHint allows a user name to be pre-selected for interactive logins.\n * Setting this option skips the account selection prompt and immediately attempts to login with the specified account.\n */\n loginHint?: string;\n}\n"]}
|
@@ -91,6 +91,7 @@ export class MsalMsiProvider {
|
|
91
91
|
// We will continue to implement these features in the Identity library.
|
92
92
|
const identitySource = this.managedIdentityApp.getManagedIdentitySource();
|
93
93
|
const isImdsMsi = identitySource === "DefaultToImds" || identitySource === "Imds"; // Neither actually checks that IMDS endpoint is available, just that it's the source the MSAL _would_ try to use.
|
94
|
+
logger.getToken.info(`MSAL Identity source: ${identitySource}`);
|
94
95
|
if (isTokenExchangeMsi) {
|
95
96
|
// In the AKS scenario we will use the existing tokenExchangeMsi indefinitely.
|
96
97
|
logger.getToken.info("Using the token exchange managed identity.");
|
@@ -102,7 +103,7 @@ export class MsalMsiProvider {
|
|
102
103
|
resourceId: this.resourceId,
|
103
104
|
});
|
104
105
|
if (result === null) {
|
105
|
-
throw new CredentialUnavailableError("
|
106
|
+
throw new CredentialUnavailableError("Attempted to use the token exchange managed identity, but received a null response.");
|
106
107
|
}
|
107
108
|
return result;
|
108
109
|
}
|
@@ -118,7 +119,7 @@ export class MsalMsiProvider {
|
|
118
119
|
resourceId: this.resourceId,
|
119
120
|
});
|
120
121
|
if (!isAvailable) {
|
121
|
-
throw new CredentialUnavailableError(`ManagedIdentityCredential:
|
122
|
+
throw new CredentialUnavailableError(`ManagedIdentityCredential: Attempted to use the IMDS endpoint, but it is not available.`);
|
122
123
|
}
|
123
124
|
}
|
124
125
|
// If we got this far, it means:
|
@@ -144,9 +145,9 @@ export class MsalMsiProvider {
|
|
144
145
|
throw err;
|
145
146
|
}
|
146
147
|
if (isNetworkError(err)) {
|
147
|
-
throw new CredentialUnavailableError(`ManagedIdentityCredential: Network unreachable. Message: ${err.message}
|
148
|
+
throw new CredentialUnavailableError(`ManagedIdentityCredential: Network unreachable. Message: ${err.message}`, { cause: err });
|
148
149
|
}
|
149
|
-
throw new CredentialUnavailableError(`ManagedIdentityCredential: Authentication failed. Message ${err.message}
|
150
|
+
throw new CredentialUnavailableError(`ManagedIdentityCredential: Authentication failed. Message ${err.message}`, { cause: err });
|
150
151
|
}
|
151
152
|
});
|
152
153
|
}
|
@@ -163,7 +164,7 @@ export class MsalMsiProvider {
|
|
163
164
|
});
|
164
165
|
};
|
165
166
|
if (!msalToken) {
|
166
|
-
throw createError("No response");
|
167
|
+
throw createError("No response.");
|
167
168
|
}
|
168
169
|
if (!msalToken.expiresOn) {
|
169
170
|
throw createError(`Response had no "expiresOn" property.`);
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"msalMsiProvider.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/msalMsiProvider.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { AuthenticationRequiredError, CredentialUnavailableError } from \"../../errors\";\nimport { MsalToken, ValidMsalToken } from \"../../msal/types\";\nimport { credentialLogger, formatError, formatSuccess } from \"../../util/logging\";\nimport { defaultLoggerCallback, getMSALLogLevel } from \"../../msal/utils\";\n\nimport { IdentityClient } from \"../../client/identityClient\";\nimport { MSIConfiguration } from \"./models\";\nimport { ManagedIdentityApplication } from \"@azure/msal-node\";\nimport { TokenCredentialOptions } from \"../../tokenCredentialOptions\";\nimport { getLogLevel } from \"@azure/logger\";\nimport { imdsMsi } from \"./imdsMsi\";\nimport { imdsRetryPolicy } from \"./imdsRetryPolicy\";\nimport { mapScopesToResource } from \"./utils\";\nimport { tokenExchangeMsi } from \"./tokenExchangeMsi\";\nimport { tracingClient } from \"../../util/tracing\";\n\nconst logger = credentialLogger(\"ManagedIdentityCredential(MSAL)\");\n\n/**\n * Options to send on the {@link ManagedIdentityCredential} constructor.\n * Since this is an internal implementation, uses a looser interface than the public one.\n */\ninterface ManagedIdentityCredentialOptions extends TokenCredentialOptions {\n /**\n * The client ID of the user - assigned identity, or app registration(when working with AKS pod - identity).\n */\n clientId?: string;\n\n /**\n * Allows specifying a custom resource Id.\n * In scenarios such as when user assigned identities are created using an ARM template,\n * where the resource Id of the identity is known but the client Id can't be known ahead of time,\n * this parameter allows programs to use these user assigned identities\n * without having to first determine the client Id of the created identity.\n */\n resourceId?: string;\n}\n\nexport class MsalMsiProvider {\n private managedIdentityApp: ManagedIdentityApplication;\n private identityClient: IdentityClient;\n private clientId?: string;\n private resourceId?: string;\n private msiRetryConfig: MSIConfiguration[\"retryConfig\"] = {\n maxRetries: 5,\n startDelayInMs: 800,\n intervalIncrement: 2,\n };\n private isAvailableIdentityClient: IdentityClient;\n\n constructor(\n clientIdOrOptions?: string | ManagedIdentityCredentialOptions,\n options: ManagedIdentityCredentialOptions = {},\n ) {\n let _options: ManagedIdentityCredentialOptions = {};\n if (typeof clientIdOrOptions === \"string\") {\n this.clientId = clientIdOrOptions;\n _options = options;\n } else {\n this.clientId = clientIdOrOptions?.clientId;\n _options = clientIdOrOptions ?? {};\n }\n this.resourceId = _options?.resourceId;\n\n // For JavaScript users.\n if (this.clientId && this.resourceId) {\n throw new Error(\n `ManagedIdentityCredential - Client Id and Resource Id can't be provided at the same time.`,\n );\n }\n\n // ManagedIdentity uses http for local requests\n _options.allowInsecureConnection = true;\n\n if (_options?.retryOptions?.maxRetries !== undefined) {\n this.msiRetryConfig.maxRetries = _options.retryOptions.maxRetries;\n }\n\n this.identityClient = new IdentityClient({\n ..._options,\n additionalPolicies: [{ policy: imdsRetryPolicy(this.msiRetryConfig), position: \"perCall\" }],\n });\n\n this.managedIdentityApp = new ManagedIdentityApplication({\n managedIdentityIdParams: {\n userAssignedClientId: this.clientId,\n userAssignedResourceId: this.resourceId,\n },\n system: {\n // todo: proxyUrl?\n disableInternalRetries: true,\n networkClient: this.identityClient,\n loggerOptions: {\n logLevel: getMSALLogLevel(getLogLevel()),\n piiLoggingEnabled: options.loggingOptions?.enableUnsafeSupportLogging,\n loggerCallback: defaultLoggerCallback(logger),\n },\n },\n });\n\n this.isAvailableIdentityClient = new IdentityClient({\n ..._options,\n retryOptions: {\n maxRetries: 0,\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 * If an unexpected error occurs, an {@link AuthenticationError} will be thrown with the details of the failure.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n public async getToken(\n scopes: string | string[],\n options: GetTokenOptions = {},\n ): Promise<AccessToken> {\n logger.getToken.info(\"Using the MSAL provider for Managed Identity.\");\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n throw new CredentialUnavailableError(\n `ManagedIdentityCredential: Multiple scopes are not supported. Scopes: ${JSON.stringify(scopes)}`,\n );\n }\n\n return tracingClient.withSpan(\"ManagedIdentityCredential.getToken\", options, async () => {\n try {\n const isTokenExchangeMsi = await tokenExchangeMsi.isAvailable({\n scopes,\n clientId: this.clientId,\n getTokenOptions: options,\n identityClient: this.identityClient,\n resourceId: this.resourceId,\n });\n\n // Most scenarios are handled by MSAL except for two:\n // AKS pod identity - MSAL does not implement the token exchange flow.\n // IMDS Endpoint probing - MSAL does not do any probing before trying to get a token.\n // As a DefaultAzureCredential optimization we probe the IMDS endpoint with a short timeout and no retries before actually trying to get a token\n // We will continue to implement these features in the Identity library.\n\n const identitySource = this.managedIdentityApp.getManagedIdentitySource();\n const isImdsMsi = identitySource === \"DefaultToImds\" || identitySource === \"Imds\"; // Neither actually checks that IMDS endpoint is available, just that it's the source the MSAL _would_ try to use.\n\n if (isTokenExchangeMsi) {\n // In the AKS scenario we will use the existing tokenExchangeMsi indefinitely.\n logger.getToken.info(\"Using the token exchange managed identity.\");\n const result = await tokenExchangeMsi.getToken({\n scopes,\n clientId: this.clientId,\n identityClient: this.identityClient,\n retryConfig: this.msiRetryConfig,\n resourceId: this.resourceId,\n });\n\n if (result === null) {\n throw new CredentialUnavailableError(\n \"The managed identity endpoint was reached, yet no tokens were received.\",\n );\n }\n\n return result;\n } else if (isImdsMsi) {\n // In the IMDS scenario we will probe the IMDS endpoint to ensure it's available before trying to get a token.\n // If the IMDS endpoint is not available and this is the source that MSAL will use, we will fail-fast with an error that tells DAC to move to the next credential.\n logger.getToken.info(\"Using the IMDS endpoint to probe for availability.\");\n const isAvailable = await imdsMsi.isAvailable({\n scopes,\n clientId: this.clientId,\n getTokenOptions: options,\n identityClient: this.isAvailableIdentityClient,\n resourceId: this.resourceId,\n });\n\n if (!isAvailable) {\n throw new CredentialUnavailableError(\n `ManagedIdentityCredential: The managed identity endpoint is not available.`,\n );\n }\n }\n\n // If we got this far, it means:\n // - This is not a tokenExchangeMsi,\n // - We already probed for IMDS endpoint availability and failed-fast if it's unreachable.\n // We can proceed normally by calling MSAL for a token.\n logger.getToken.info(\"Calling into MSAL for managed identity token.\");\n const token = await this.managedIdentityApp.acquireToken({\n resource,\n });\n\n this.ensureValidMsalToken(scopes, token, options);\n logger.getToken.info(formatSuccess(scopes));\n\n return {\n expiresOnTimestamp: token.expiresOn.getTime(),\n token: token.accessToken,\n };\n } catch (err: any) {\n logger.getToken.error(formatError(scopes, err));\n\n // AuthenticationRequiredError described as Error to enforce authentication after trying to retrieve a token silently.\n // TODO: why would this _ever_ happen considering we're not trying the silent request in this flow?\n if (err.name === \"AuthenticationRequiredError\") {\n throw err;\n }\n\n if (isNetworkError(err)) {\n throw new CredentialUnavailableError(\n `ManagedIdentityCredential: Network unreachable. Message: ${err.message}`,\n );\n }\n\n throw new CredentialUnavailableError(\n `ManagedIdentityCredential: Authentication failed. Message ${err.message}`,\n );\n }\n });\n }\n\n /**\n * Ensures the validity of the MSAL token\n */\n private ensureValidMsalToken(\n scopes: string | string[],\n msalToken?: MsalToken,\n getTokenOptions?: GetTokenOptions,\n ): asserts msalToken is ValidMsalToken {\n const createError = (message: string): Error => {\n logger.getToken.info(message);\n return new AuthenticationRequiredError({\n scopes: Array.isArray(scopes) ? scopes : [scopes],\n getTokenOptions,\n message,\n });\n };\n if (!msalToken) {\n throw createError(\"No response\");\n }\n if (!msalToken.expiresOn) {\n throw createError(`Response had no \"expiresOn\" property.`);\n }\n if (!msalToken.accessToken) {\n throw createError(`Response had no \"accessToken\" property.`);\n }\n }\n}\n\nfunction isNetworkError(err: any): boolean {\n // MSAL error\n if (err.errorCode === \"network_error\") {\n return true;\n }\n\n // Probe errors\n if (err.code === \"ENETUNREACH\" || err.code === \"EHOSTUNREACH\") {\n return true;\n }\n\n // This is a special case for Docker Desktop which responds with a 403 with a message that contains \"A socket operation was attempted to an unreachable network\" or \"A socket operation was attempted to an unreachable host\"\n // rather than just timing out, as expected.\n if (err.statusCode === 403 || err.code === 403) {\n if (err.message.includes(\"unreachable\")) {\n return true;\n }\n }\n\n return false;\n}\n"]}
|
1
|
+
{"version":3,"file":"msalMsiProvider.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/msalMsiProvider.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { AuthenticationRequiredError, CredentialUnavailableError } from \"../../errors\";\nimport { MsalToken, ValidMsalToken } from \"../../msal/types\";\nimport { credentialLogger, formatError, formatSuccess } from \"../../util/logging\";\nimport { defaultLoggerCallback, getMSALLogLevel } from \"../../msal/utils\";\n\nimport { IdentityClient } from \"../../client/identityClient\";\nimport { MSIConfiguration } from \"./models\";\nimport { ManagedIdentityApplication } from \"@azure/msal-node\";\nimport { TokenCredentialOptions } from \"../../tokenCredentialOptions\";\nimport { getLogLevel } from \"@azure/logger\";\nimport { imdsMsi } from \"./imdsMsi\";\nimport { imdsRetryPolicy } from \"./imdsRetryPolicy\";\nimport { mapScopesToResource } from \"./utils\";\nimport { tokenExchangeMsi } from \"./tokenExchangeMsi\";\nimport { tracingClient } from \"../../util/tracing\";\n\nconst logger = credentialLogger(\"ManagedIdentityCredential(MSAL)\");\n\n/**\n * Options to send on the {@link ManagedIdentityCredential} constructor.\n * Since this is an internal implementation, uses a looser interface than the public one.\n */\ninterface ManagedIdentityCredentialOptions extends TokenCredentialOptions {\n /**\n * The client ID of the user - assigned identity, or app registration(when working with AKS pod - identity).\n */\n clientId?: string;\n\n /**\n * Allows specifying a custom resource Id.\n * In scenarios such as when user assigned identities are created using an ARM template,\n * where the resource Id of the identity is known but the client Id can't be known ahead of time,\n * this parameter allows programs to use these user assigned identities\n * without having to first determine the client Id of the created identity.\n */\n resourceId?: string;\n}\n\nexport class MsalMsiProvider {\n private managedIdentityApp: ManagedIdentityApplication;\n private identityClient: IdentityClient;\n private clientId?: string;\n private resourceId?: string;\n private msiRetryConfig: MSIConfiguration[\"retryConfig\"] = {\n maxRetries: 5,\n startDelayInMs: 800,\n intervalIncrement: 2,\n };\n private isAvailableIdentityClient: IdentityClient;\n\n constructor(\n clientIdOrOptions?: string | ManagedIdentityCredentialOptions,\n options: ManagedIdentityCredentialOptions = {},\n ) {\n let _options: ManagedIdentityCredentialOptions = {};\n if (typeof clientIdOrOptions === \"string\") {\n this.clientId = clientIdOrOptions;\n _options = options;\n } else {\n this.clientId = clientIdOrOptions?.clientId;\n _options = clientIdOrOptions ?? {};\n }\n this.resourceId = _options?.resourceId;\n\n // For JavaScript users.\n if (this.clientId && this.resourceId) {\n throw new Error(\n `ManagedIdentityCredential - Client Id and Resource Id can't be provided at the same time.`,\n );\n }\n\n // ManagedIdentity uses http for local requests\n _options.allowInsecureConnection = true;\n\n if (_options?.retryOptions?.maxRetries !== undefined) {\n this.msiRetryConfig.maxRetries = _options.retryOptions.maxRetries;\n }\n\n this.identityClient = new IdentityClient({\n ..._options,\n additionalPolicies: [{ policy: imdsRetryPolicy(this.msiRetryConfig), position: \"perCall\" }],\n });\n\n this.managedIdentityApp = new ManagedIdentityApplication({\n managedIdentityIdParams: {\n userAssignedClientId: this.clientId,\n userAssignedResourceId: this.resourceId,\n },\n system: {\n // todo: proxyUrl?\n disableInternalRetries: true,\n networkClient: this.identityClient,\n loggerOptions: {\n logLevel: getMSALLogLevel(getLogLevel()),\n piiLoggingEnabled: options.loggingOptions?.enableUnsafeSupportLogging,\n loggerCallback: defaultLoggerCallback(logger),\n },\n },\n });\n\n this.isAvailableIdentityClient = new IdentityClient({\n ..._options,\n retryOptions: {\n maxRetries: 0,\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 * If an unexpected error occurs, an {@link AuthenticationError} will be thrown with the details of the failure.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n public async getToken(\n scopes: string | string[],\n options: GetTokenOptions = {},\n ): Promise<AccessToken> {\n logger.getToken.info(\"Using the MSAL provider for Managed Identity.\");\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n throw new CredentialUnavailableError(\n `ManagedIdentityCredential: Multiple scopes are not supported. Scopes: ${JSON.stringify(scopes)}`,\n );\n }\n\n return tracingClient.withSpan(\"ManagedIdentityCredential.getToken\", options, async () => {\n try {\n const isTokenExchangeMsi = await tokenExchangeMsi.isAvailable({\n scopes,\n clientId: this.clientId,\n getTokenOptions: options,\n identityClient: this.identityClient,\n resourceId: this.resourceId,\n });\n\n // Most scenarios are handled by MSAL except for two:\n // AKS pod identity - MSAL does not implement the token exchange flow.\n // IMDS Endpoint probing - MSAL does not do any probing before trying to get a token.\n // As a DefaultAzureCredential optimization we probe the IMDS endpoint with a short timeout and no retries before actually trying to get a token\n // We will continue to implement these features in the Identity library.\n\n const identitySource = this.managedIdentityApp.getManagedIdentitySource();\n const isImdsMsi = identitySource === \"DefaultToImds\" || identitySource === \"Imds\"; // Neither actually checks that IMDS endpoint is available, just that it's the source the MSAL _would_ try to use.\n\n logger.getToken.info(`MSAL Identity source: ${identitySource}`);\n\n if (isTokenExchangeMsi) {\n // In the AKS scenario we will use the existing tokenExchangeMsi indefinitely.\n logger.getToken.info(\"Using the token exchange managed identity.\");\n const result = await tokenExchangeMsi.getToken({\n scopes,\n clientId: this.clientId,\n identityClient: this.identityClient,\n retryConfig: this.msiRetryConfig,\n resourceId: this.resourceId,\n });\n\n if (result === null) {\n throw new CredentialUnavailableError(\n \"Attempted to use the token exchange managed identity, but received a null response.\",\n );\n }\n\n return result;\n } else if (isImdsMsi) {\n // In the IMDS scenario we will probe the IMDS endpoint to ensure it's available before trying to get a token.\n // If the IMDS endpoint is not available and this is the source that MSAL will use, we will fail-fast with an error that tells DAC to move to the next credential.\n logger.getToken.info(\"Using the IMDS endpoint to probe for availability.\");\n const isAvailable = await imdsMsi.isAvailable({\n scopes,\n clientId: this.clientId,\n getTokenOptions: options,\n identityClient: this.isAvailableIdentityClient,\n resourceId: this.resourceId,\n });\n\n if (!isAvailable) {\n throw new CredentialUnavailableError(\n `ManagedIdentityCredential: Attempted to use the IMDS endpoint, but it is not available.`,\n );\n }\n }\n\n // If we got this far, it means:\n // - This is not a tokenExchangeMsi,\n // - We already probed for IMDS endpoint availability and failed-fast if it's unreachable.\n // We can proceed normally by calling MSAL for a token.\n logger.getToken.info(\"Calling into MSAL for managed identity token.\");\n const token = await this.managedIdentityApp.acquireToken({\n resource,\n });\n\n this.ensureValidMsalToken(scopes, token, options);\n logger.getToken.info(formatSuccess(scopes));\n\n return {\n expiresOnTimestamp: token.expiresOn.getTime(),\n token: token.accessToken,\n };\n } catch (err: any) {\n logger.getToken.error(formatError(scopes, err));\n\n // AuthenticationRequiredError described as Error to enforce authentication after trying to retrieve a token silently.\n // TODO: why would this _ever_ happen considering we're not trying the silent request in this flow?\n if (err.name === \"AuthenticationRequiredError\") {\n throw err;\n }\n\n if (isNetworkError(err)) {\n throw new CredentialUnavailableError(\n `ManagedIdentityCredential: Network unreachable. Message: ${err.message}`,\n { cause: err },\n );\n }\n\n throw new CredentialUnavailableError(\n `ManagedIdentityCredential: Authentication failed. Message ${err.message}`,\n { cause: err },\n );\n }\n });\n }\n\n /**\n * Ensures the validity of the MSAL token\n */\n private ensureValidMsalToken(\n scopes: string | string[],\n msalToken?: MsalToken,\n getTokenOptions?: GetTokenOptions,\n ): asserts msalToken is ValidMsalToken {\n const createError = (message: string): Error => {\n logger.getToken.info(message);\n return new AuthenticationRequiredError({\n scopes: Array.isArray(scopes) ? scopes : [scopes],\n getTokenOptions,\n message,\n });\n };\n if (!msalToken) {\n throw createError(\"No response.\");\n }\n if (!msalToken.expiresOn) {\n throw createError(`Response had no \"expiresOn\" property.`);\n }\n if (!msalToken.accessToken) {\n throw createError(`Response had no \"accessToken\" property.`);\n }\n }\n}\n\nfunction isNetworkError(err: any): boolean {\n // MSAL error\n if (err.errorCode === \"network_error\") {\n return true;\n }\n\n // Probe errors\n if (err.code === \"ENETUNREACH\" || err.code === \"EHOSTUNREACH\") {\n return true;\n }\n\n // This is a special case for Docker Desktop which responds with a 403 with a message that contains \"A socket operation was attempted to an unreachable network\" or \"A socket operation was attempted to an unreachable host\"\n // rather than just timing out, as expected.\n if (err.statusCode === 403 || err.code === 403) {\n if (err.message.includes(\"unreachable\")) {\n return true;\n }\n }\n\n return false;\n}\n"]}
|