@azure/identity 4.3.1-alpha.20240618.4 → 4.3.1-alpha.20240620.2
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/index.js +356 -702
- package/dist/index.js.map +1 -1
- package/dist-esm/src/credentials/interactiveBrowserCredential.js +18 -21
- package/dist-esm/src/credentials/interactiveBrowserCredential.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/index.js +3 -284
- package/dist-esm/src/credentials/managedIdentityCredential/index.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/legacyMsiProvider.js +302 -0
- package/dist-esm/src/credentials/managedIdentityCredential/legacyMsiProvider.js.map +1 -0
- package/dist-esm/src/credentials/onBehalfOfCredential.js +62 -6
- package/dist-esm/src/credentials/onBehalfOfCredential.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalClient.js +102 -0
- package/dist-esm/src/msal/nodeFlows/msalClient.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalPlugins.js.map +1 -1
- package/package.json +1 -1
- package/types/identity.d.ts +11 -25
@@ -1,10 +1,11 @@
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
2
2
|
// Licensed under the MIT license.
|
3
|
-
import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, } from "../util/tenantIdUtils";
|
4
|
-
import { MsalOpenBrowser } from "../msal/nodeFlows/msalOpenBrowser";
|
3
|
+
import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, resolveTenantId, } from "../util/tenantIdUtils";
|
5
4
|
import { credentialLogger } from "../util/logging";
|
6
5
|
import { ensureScopes } from "../util/scopeUtils";
|
7
6
|
import { tracingClient } from "../util/tracing";
|
7
|
+
import { createMsalClient } from "../msal/nodeFlows/msalClient";
|
8
|
+
import { DeveloperSignOnClientId } from "../constants";
|
8
9
|
const logger = credentialLogger("InteractiveBrowserCredential");
|
9
10
|
/**
|
10
11
|
* Enables authentication to Microsoft Entra ID inside of the web browser
|
@@ -24,31 +25,27 @@ export class InteractiveBrowserCredential {
|
|
24
25
|
* @param options - Options for configuring the client which makes the authentication requests.
|
25
26
|
*/
|
26
27
|
constructor(options) {
|
27
|
-
var _a, _b, _c, _d;
|
28
|
-
|
29
|
-
? options.redirectUri()
|
30
|
-
: options.redirectUri || "http://localhost";
|
31
|
-
this.tenantId = options === null || options === void 0 ? void 0 : options.tenantId;
|
28
|
+
var _a, _b, _c, _d, _e;
|
29
|
+
this.tenantId = resolveTenantId(logger, options.tenantId, options.clientId);
|
32
30
|
this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants);
|
31
|
+
const msalClientOptions = Object.assign(Object.assign({}, options), { tokenCredentialOptions: options, logger });
|
33
32
|
const ibcNodeOptions = options;
|
33
|
+
this.browserCustomizationOptions = ibcNodeOptions.browserCustomizationOptions;
|
34
|
+
this.loginHint = ibcNodeOptions.loginHint;
|
34
35
|
if ((_a = ibcNodeOptions === null || ibcNodeOptions === void 0 ? void 0 : ibcNodeOptions.brokerOptions) === null || _a === void 0 ? void 0 : _a.enabled) {
|
35
36
|
if (!((_b = ibcNodeOptions === null || ibcNodeOptions === void 0 ? void 0 : ibcNodeOptions.brokerOptions) === null || _b === void 0 ? void 0 : _b.parentWindowHandle)) {
|
36
37
|
throw new Error("In order to do WAM authentication, `parentWindowHandle` under `brokerOptions` is a required parameter");
|
37
38
|
}
|
38
39
|
else {
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
} }));
|
40
|
+
msalClientOptions.brokerOptions = {
|
41
|
+
enabled: true,
|
42
|
+
parentWindowHandle: ibcNodeOptions.brokerOptions.parentWindowHandle,
|
43
|
+
legacyEnableMsaPassthrough: (_c = ibcNodeOptions.brokerOptions) === null || _c === void 0 ? void 0 : _c.legacyEnableMsaPassthrough,
|
44
|
+
useDefaultBrokerAccount: (_d = ibcNodeOptions.brokerOptions) === null || _d === void 0 ? void 0 : _d.useDefaultBrokerAccount,
|
45
|
+
};
|
46
46
|
}
|
47
47
|
}
|
48
|
-
|
49
|
-
this.msalFlow = new MsalOpenBrowser(Object.assign(Object.assign({}, options), { tokenCredentialOptions: options, logger,
|
50
|
-
redirectUri, browserCustomizationOptions: ibcNodeOptions === null || ibcNodeOptions === void 0 ? void 0 : ibcNodeOptions.browserCustomizationOptions }));
|
51
|
-
}
|
48
|
+
this.msalClient = createMsalClient((_e = options.clientId) !== null && _e !== void 0 ? _e : DeveloperSignOnClientId, this.tenantId, msalClientOptions);
|
52
49
|
this.disableAutomaticAuthentication = options === null || options === void 0 ? void 0 : options.disableAutomaticAuthentication;
|
53
50
|
}
|
54
51
|
/**
|
@@ -67,7 +64,7 @@ export class InteractiveBrowserCredential {
|
|
67
64
|
return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async (newOptions) => {
|
68
65
|
newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger);
|
69
66
|
const arrayScopes = ensureScopes(scopes);
|
70
|
-
return this.
|
67
|
+
return this.msalClient.getTokenByInteractiveRequest(arrayScopes, Object.assign(Object.assign({}, newOptions), { disableAutomaticAuthentication: this.disableAutomaticAuthentication, browserCustomizationOptions: this.browserCustomizationOptions, loginHint: this.loginHint }));
|
71
68
|
});
|
72
69
|
}
|
73
70
|
/**
|
@@ -86,8 +83,8 @@ export class InteractiveBrowserCredential {
|
|
86
83
|
async authenticate(scopes, options = {}) {
|
87
84
|
return tracingClient.withSpan(`${this.constructor.name}.authenticate`, options, async (newOptions) => {
|
88
85
|
const arrayScopes = ensureScopes(scopes);
|
89
|
-
await this.
|
90
|
-
return this.
|
86
|
+
await this.msalClient.getTokenByInteractiveRequest(arrayScopes, Object.assign(Object.assign({}, newOptions), { disableAutomaticAuthentication: false, browserCustomizationOptions: this.browserCustomizationOptions, loginHint: this.loginHint }));
|
87
|
+
return this.msalClient.getActiveAccount();
|
91
88
|
});
|
92
89
|
}
|
93
90
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"interactiveBrowserCredential.js","sourceRoot":"","sources":["../../../src/credentials/interactiveBrowserCredential.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AASlC,OAAO,EACL,yBAAyB,EACzB,mCAAmC,
|
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 require user interaction to retrieve the token.\n *\n * On Node.js, this credential has [Proof Key for Code Exchange (PKCE)](https://datatracker.ietf.org/doc/html/rfc7636) enabled by default.\n * PKCE is a security feature that mitigates authentication code interception attacks.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n async authenticate(\n scopes: string | string[],\n options: GetTokenOptions = {},\n ): Promise<AuthenticationRecord | undefined> {\n return 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,21 +1,6 @@
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
2
2
|
// Licensed under the MIT license.
|
3
|
-
import {
|
4
|
-
import { AuthenticationError, AuthenticationRequiredError, CredentialUnavailableError, } from "../../errors";
|
5
|
-
import { credentialLogger, formatError, formatSuccess } from "../../util/logging";
|
6
|
-
import { DeveloperSignOnClientId } from "../../constants";
|
7
|
-
import { IdentityClient } from "../../client/identityClient";
|
8
|
-
import { appServiceMsi2017 } from "./appServiceMsi2017";
|
9
|
-
import { appServiceMsi2019 } from "./appServiceMsi2019";
|
10
|
-
import { arcMsi } from "./arcMsi";
|
11
|
-
import { cloudShellMsi } from "./cloudShellMsi";
|
12
|
-
import { fabricMsi } from "./fabricMsi";
|
13
|
-
import { getLogLevel } from "@azure/logger";
|
14
|
-
import { getMSALLogLevel } from "../../msal/utils";
|
15
|
-
import { imdsMsi } from "./imdsMsi";
|
16
|
-
import { tokenExchangeMsi } from "./tokenExchangeMsi";
|
17
|
-
import { tracingClient } from "../../util/tracing";
|
18
|
-
const logger = credentialLogger("ManagedIdentityCredential");
|
3
|
+
import { LegacyMsiProvider } from "./legacyMsiProvider";
|
19
4
|
/**
|
20
5
|
* Attempts authentication using a managed identity available at the deployment environment.
|
21
6
|
* This authentication type works in Azure VMs, App Service instances, Azure Functions applications,
|
@@ -30,104 +15,7 @@ export class ManagedIdentityCredential {
|
|
30
15
|
* @hidden
|
31
16
|
*/
|
32
17
|
constructor(clientIdOrOptions, options) {
|
33
|
-
|
34
|
-
this.isEndpointUnavailable = null;
|
35
|
-
this.isAppTokenProviderInitialized = false;
|
36
|
-
this.msiRetryConfig = {
|
37
|
-
maxRetries: 5,
|
38
|
-
startDelayInMs: 800,
|
39
|
-
intervalIncrement: 2,
|
40
|
-
};
|
41
|
-
let _options;
|
42
|
-
if (typeof clientIdOrOptions === "string") {
|
43
|
-
this.clientId = clientIdOrOptions;
|
44
|
-
_options = options;
|
45
|
-
}
|
46
|
-
else {
|
47
|
-
this.clientId = clientIdOrOptions === null || clientIdOrOptions === void 0 ? void 0 : clientIdOrOptions.clientId;
|
48
|
-
_options = clientIdOrOptions;
|
49
|
-
}
|
50
|
-
this.resourceId = _options === null || _options === void 0 ? void 0 : _options.resourceId;
|
51
|
-
// For JavaScript users.
|
52
|
-
if (this.clientId && this.resourceId) {
|
53
|
-
throw new Error(`${ManagedIdentityCredential.name} - Client Id and Resource Id can't be provided at the same time.`);
|
54
|
-
}
|
55
|
-
if (((_a = _options === null || _options === void 0 ? void 0 : _options.retryOptions) === null || _a === void 0 ? void 0 : _a.maxRetries) !== undefined) {
|
56
|
-
this.msiRetryConfig.maxRetries = _options.retryOptions.maxRetries;
|
57
|
-
}
|
58
|
-
this.identityClient = new IdentityClient(_options);
|
59
|
-
this.isAvailableIdentityClient = new IdentityClient(Object.assign(Object.assign({}, _options), { retryOptions: {
|
60
|
-
maxRetries: 0,
|
61
|
-
} }));
|
62
|
-
/** authority host validation and metadata discovery to be skipped in managed identity
|
63
|
-
* since this wasn't done previously before adding token cache support
|
64
|
-
*/
|
65
|
-
this.confidentialApp = new ConfidentialClientApplication({
|
66
|
-
auth: {
|
67
|
-
authority: "https://login.microsoftonline.com/managed_identity",
|
68
|
-
clientId: (_b = this.clientId) !== null && _b !== void 0 ? _b : DeveloperSignOnClientId,
|
69
|
-
clientSecret: "dummy-secret",
|
70
|
-
cloudDiscoveryMetadata: '{"tenant_discovery_endpoint":"https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration","api-version":"1.1","metadata":[{"preferred_network":"login.microsoftonline.com","preferred_cache":"login.windows.net","aliases":["login.microsoftonline.com","login.windows.net","login.microsoft.com","sts.windows.net"]},{"preferred_network":"login.partner.microsoftonline.cn","preferred_cache":"login.partner.microsoftonline.cn","aliases":["login.partner.microsoftonline.cn","login.chinacloudapi.cn"]},{"preferred_network":"login.microsoftonline.de","preferred_cache":"login.microsoftonline.de","aliases":["login.microsoftonline.de"]},{"preferred_network":"login.microsoftonline.us","preferred_cache":"login.microsoftonline.us","aliases":["login.microsoftonline.us","login.usgovcloudapi.net"]},{"preferred_network":"login-us.microsoftonline.com","preferred_cache":"login-us.microsoftonline.com","aliases":["login-us.microsoftonline.com"]}]}',
|
71
|
-
authorityMetadata: '{"token_endpoint":"https://login.microsoftonline.com/common/oauth2/v2.0/token","token_endpoint_auth_methods_supported":["client_secret_post","private_key_jwt","client_secret_basic"],"jwks_uri":"https://login.microsoftonline.com/common/discovery/v2.0/keys","response_modes_supported":["query","fragment","form_post"],"subject_types_supported":["pairwise"],"id_token_signing_alg_values_supported":["RS256"],"response_types_supported":["code","id_token","code id_token","id_token token"],"scopes_supported":["openid","profile","email","offline_access"],"issuer":"https://login.microsoftonline.com/{tenantid}/v2.0","request_uri_parameter_supported":false,"userinfo_endpoint":"https://graph.microsoft.com/oidc/userinfo","authorization_endpoint":"https://login.microsoftonline.com/common/oauth2/v2.0/authorize","device_authorization_endpoint":"https://login.microsoftonline.com/common/oauth2/v2.0/devicecode","http_logout_supported":true,"frontchannel_logout_supported":true,"end_session_endpoint":"https://login.microsoftonline.com/common/oauth2/v2.0/logout","claims_supported":["sub","iss","cloud_instance_name","cloud_instance_host_name","cloud_graph_host_name","msgraph_host","aud","exp","iat","auth_time","acr","nonce","preferred_username","name","tid","ver","at_hash","c_hash","email"],"kerberos_endpoint":"https://login.microsoftonline.com/common/kerberos","tenant_region_scope":null,"cloud_instance_name":"microsoftonline.com","cloud_graph_host_name":"graph.windows.net","msgraph_host":"graph.microsoft.com","rbac_url":"https://pas.windows.net"}',
|
72
|
-
clientCapabilities: [],
|
73
|
-
},
|
74
|
-
system: {
|
75
|
-
loggerOptions: {
|
76
|
-
logLevel: getMSALLogLevel(getLogLevel()),
|
77
|
-
},
|
78
|
-
},
|
79
|
-
});
|
80
|
-
}
|
81
|
-
async cachedAvailableMSI(scopes, getTokenOptions) {
|
82
|
-
if (this.cachedMSI) {
|
83
|
-
return this.cachedMSI;
|
84
|
-
}
|
85
|
-
const MSIs = [
|
86
|
-
arcMsi,
|
87
|
-
fabricMsi,
|
88
|
-
appServiceMsi2019,
|
89
|
-
appServiceMsi2017,
|
90
|
-
cloudShellMsi,
|
91
|
-
tokenExchangeMsi(),
|
92
|
-
imdsMsi,
|
93
|
-
];
|
94
|
-
for (const msi of MSIs) {
|
95
|
-
if (await msi.isAvailable({
|
96
|
-
scopes,
|
97
|
-
identityClient: this.isAvailableIdentityClient,
|
98
|
-
clientId: this.clientId,
|
99
|
-
resourceId: this.resourceId,
|
100
|
-
getTokenOptions,
|
101
|
-
})) {
|
102
|
-
this.cachedMSI = msi;
|
103
|
-
return msi;
|
104
|
-
}
|
105
|
-
}
|
106
|
-
throw new CredentialUnavailableError(`${ManagedIdentityCredential.name} - No MSI credential available`);
|
107
|
-
}
|
108
|
-
async authenticateManagedIdentity(scopes, getTokenOptions) {
|
109
|
-
const { span, updatedOptions } = tracingClient.startSpan(`${ManagedIdentityCredential.name}.authenticateManagedIdentity`, getTokenOptions);
|
110
|
-
try {
|
111
|
-
// Determining the available MSI, and avoiding checking for other MSIs while the program is running.
|
112
|
-
const availableMSI = await this.cachedAvailableMSI(scopes, updatedOptions);
|
113
|
-
return availableMSI.getToken({
|
114
|
-
identityClient: this.identityClient,
|
115
|
-
scopes,
|
116
|
-
clientId: this.clientId,
|
117
|
-
resourceId: this.resourceId,
|
118
|
-
retryConfig: this.msiRetryConfig,
|
119
|
-
}, updatedOptions);
|
120
|
-
}
|
121
|
-
catch (err) {
|
122
|
-
span.setStatus({
|
123
|
-
status: "error",
|
124
|
-
error: err,
|
125
|
-
});
|
126
|
-
throw err;
|
127
|
-
}
|
128
|
-
finally {
|
129
|
-
span.end();
|
130
|
-
}
|
18
|
+
this.implProvider = new LegacyMsiProvider(clientIdOrOptions, options);
|
131
19
|
}
|
132
20
|
/**
|
133
21
|
* Authenticates with Microsoft Entra ID and returns an access token if successful.
|
@@ -139,176 +27,7 @@ export class ManagedIdentityCredential {
|
|
139
27
|
* TokenCredential implementation might make.
|
140
28
|
*/
|
141
29
|
async getToken(scopes, options) {
|
142
|
-
|
143
|
-
const { span, updatedOptions } = tracingClient.startSpan(`${ManagedIdentityCredential.name}.getToken`, options);
|
144
|
-
try {
|
145
|
-
// isEndpointAvailable can be true, false, or null,
|
146
|
-
// If it's null, it means we don't yet know whether
|
147
|
-
// the endpoint is available and need to check for it.
|
148
|
-
if (this.isEndpointUnavailable !== true) {
|
149
|
-
const availableMSI = await this.cachedAvailableMSI(scopes, updatedOptions);
|
150
|
-
if (availableMSI.name === "tokenExchangeMsi") {
|
151
|
-
result = await this.authenticateManagedIdentity(scopes, updatedOptions);
|
152
|
-
}
|
153
|
-
else {
|
154
|
-
const appTokenParameters = {
|
155
|
-
correlationId: this.identityClient.getCorrelationId(),
|
156
|
-
tenantId: (options === null || options === void 0 ? void 0 : options.tenantId) || "managed_identity",
|
157
|
-
scopes: Array.isArray(scopes) ? scopes : [scopes],
|
158
|
-
claims: options === null || options === void 0 ? void 0 : options.claims,
|
159
|
-
};
|
160
|
-
// Added a check to see if SetAppTokenProvider was already defined.
|
161
|
-
this.initializeSetAppTokenProvider();
|
162
|
-
const authenticationResult = await this.confidentialApp.acquireTokenByClientCredential(Object.assign({}, appTokenParameters));
|
163
|
-
result = this.handleResult(scopes, authenticationResult || undefined);
|
164
|
-
}
|
165
|
-
if (result === null) {
|
166
|
-
// If authenticateManagedIdentity returns null,
|
167
|
-
// it means no MSI endpoints are available.
|
168
|
-
// If so, we avoid trying to reach to them in future requests.
|
169
|
-
this.isEndpointUnavailable = true;
|
170
|
-
// It also means that the endpoint answered with either 200 or 201 (see the sendTokenRequest method),
|
171
|
-
// yet we had no access token. For this reason, we'll throw once with a specific message:
|
172
|
-
const error = new CredentialUnavailableError("The managed identity endpoint was reached, yet no tokens were received.");
|
173
|
-
logger.getToken.info(formatError(scopes, error));
|
174
|
-
throw error;
|
175
|
-
}
|
176
|
-
// Since `authenticateManagedIdentity` didn't throw, and the result was not null,
|
177
|
-
// We will assume that this endpoint is reachable from this point forward,
|
178
|
-
// and avoid pinging again to it.
|
179
|
-
this.isEndpointUnavailable = false;
|
180
|
-
}
|
181
|
-
else {
|
182
|
-
// We've previously determined that the endpoint was unavailable,
|
183
|
-
// either because it was unreachable or permanently unable to authenticate.
|
184
|
-
const error = new CredentialUnavailableError("The managed identity endpoint is not currently available");
|
185
|
-
logger.getToken.info(formatError(scopes, error));
|
186
|
-
throw error;
|
187
|
-
}
|
188
|
-
logger.getToken.info(formatSuccess(scopes));
|
189
|
-
return result;
|
190
|
-
}
|
191
|
-
catch (err) {
|
192
|
-
// CredentialUnavailable errors are expected to reach here.
|
193
|
-
// We intend them to bubble up, so that DefaultAzureCredential can catch them.
|
194
|
-
if (err.name === "AuthenticationRequiredError") {
|
195
|
-
throw err;
|
196
|
-
}
|
197
|
-
// Expected errors to reach this point:
|
198
|
-
// - Errors coming from a method unexpectedly breaking.
|
199
|
-
// - When identityClient.sendTokenRequest throws, in which case
|
200
|
-
// if the status code was 400, it means that the endpoint is working,
|
201
|
-
// but no identity is available.
|
202
|
-
span.setStatus({
|
203
|
-
status: "error",
|
204
|
-
error: err,
|
205
|
-
});
|
206
|
-
// If either the network is unreachable,
|
207
|
-
// we can safely assume the credential is unavailable.
|
208
|
-
if (err.code === "ENETUNREACH") {
|
209
|
-
const error = new CredentialUnavailableError(`${ManagedIdentityCredential.name}: Unavailable. Network unreachable. Message: ${err.message}`);
|
210
|
-
logger.getToken.info(formatError(scopes, error));
|
211
|
-
throw error;
|
212
|
-
}
|
213
|
-
// If either the host was unreachable,
|
214
|
-
// we can safely assume the credential is unavailable.
|
215
|
-
if (err.code === "EHOSTUNREACH") {
|
216
|
-
const error = new CredentialUnavailableError(`${ManagedIdentityCredential.name}: Unavailable. No managed identity endpoint found. Message: ${err.message}`);
|
217
|
-
logger.getToken.info(formatError(scopes, error));
|
218
|
-
throw error;
|
219
|
-
}
|
220
|
-
// If err.statusCode has a value of 400, it comes from sendTokenRequest,
|
221
|
-
// and it means that the endpoint is working, but that no identity is available.
|
222
|
-
if (err.statusCode === 400) {
|
223
|
-
throw new CredentialUnavailableError(`${ManagedIdentityCredential.name}: The managed identity endpoint is indicating there's no available identity. Message: ${err.message}`);
|
224
|
-
}
|
225
|
-
// 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"
|
226
|
-
// rather than just timing out, as expected.
|
227
|
-
if (err.statusCode === 403 || err.code === 403) {
|
228
|
-
if (err.message.includes("unreachable")) {
|
229
|
-
const error = new CredentialUnavailableError(`${ManagedIdentityCredential.name}: Unavailable. Network unreachable. Message: ${err.message}`);
|
230
|
-
logger.getToken.info(formatError(scopes, error));
|
231
|
-
throw error;
|
232
|
-
}
|
233
|
-
}
|
234
|
-
// If the error has no status code, we can assume there was no available identity.
|
235
|
-
// This will throw silently during any ChainedTokenCredential.
|
236
|
-
if (err.statusCode === undefined) {
|
237
|
-
throw new CredentialUnavailableError(`${ManagedIdentityCredential.name}: Authentication failed. Message ${err.message}`);
|
238
|
-
}
|
239
|
-
// Any other error should break the chain.
|
240
|
-
throw new AuthenticationError(err.statusCode, {
|
241
|
-
error: `${ManagedIdentityCredential.name} authentication failed.`,
|
242
|
-
error_description: err.message,
|
243
|
-
});
|
244
|
-
}
|
245
|
-
finally {
|
246
|
-
// Finally is always called, both if we return and if we throw in the above try/catch.
|
247
|
-
span.end();
|
248
|
-
}
|
249
|
-
}
|
250
|
-
/**
|
251
|
-
* Handles the MSAL authentication result.
|
252
|
-
* If the result has an account, we update the local account reference.
|
253
|
-
* If the token received is invalid, an error will be thrown depending on what's missing.
|
254
|
-
*/
|
255
|
-
handleResult(scopes, result, getTokenOptions) {
|
256
|
-
this.ensureValidMsalToken(scopes, result, getTokenOptions);
|
257
|
-
logger.getToken.info(formatSuccess(scopes));
|
258
|
-
return {
|
259
|
-
token: result.accessToken,
|
260
|
-
expiresOnTimestamp: result.expiresOn.getTime(),
|
261
|
-
};
|
262
|
-
}
|
263
|
-
/**
|
264
|
-
* Ensures the validity of the MSAL token
|
265
|
-
*/
|
266
|
-
ensureValidMsalToken(scopes, msalToken, getTokenOptions) {
|
267
|
-
const error = (message) => {
|
268
|
-
logger.getToken.info(message);
|
269
|
-
return new AuthenticationRequiredError({
|
270
|
-
scopes: Array.isArray(scopes) ? scopes : [scopes],
|
271
|
-
getTokenOptions,
|
272
|
-
message,
|
273
|
-
});
|
274
|
-
};
|
275
|
-
if (!msalToken) {
|
276
|
-
throw error("No response");
|
277
|
-
}
|
278
|
-
if (!msalToken.expiresOn) {
|
279
|
-
throw error(`Response had no "expiresOn" property.`);
|
280
|
-
}
|
281
|
-
if (!msalToken.accessToken) {
|
282
|
-
throw error(`Response had no "accessToken" property.`);
|
283
|
-
}
|
284
|
-
}
|
285
|
-
initializeSetAppTokenProvider() {
|
286
|
-
if (!this.isAppTokenProviderInitialized) {
|
287
|
-
this.confidentialApp.SetAppTokenProvider(async (appTokenProviderParameters) => {
|
288
|
-
logger.info(`SetAppTokenProvider invoked with parameters- ${JSON.stringify(appTokenProviderParameters)}`);
|
289
|
-
const getTokenOptions = Object.assign({}, appTokenProviderParameters);
|
290
|
-
logger.info(`authenticateManagedIdentity invoked with scopes- ${JSON.stringify(appTokenProviderParameters.scopes)} and getTokenOptions - ${JSON.stringify(getTokenOptions)}`);
|
291
|
-
const resultToken = await this.authenticateManagedIdentity(appTokenProviderParameters.scopes, getTokenOptions);
|
292
|
-
if (resultToken) {
|
293
|
-
logger.info(`SetAppTokenProvider will save the token in cache`);
|
294
|
-
const expiresInSeconds = (resultToken === null || resultToken === void 0 ? void 0 : resultToken.expiresOnTimestamp)
|
295
|
-
? Math.floor((resultToken.expiresOnTimestamp - Date.now()) / 1000)
|
296
|
-
: 0;
|
297
|
-
return {
|
298
|
-
accessToken: resultToken === null || resultToken === void 0 ? void 0 : resultToken.token,
|
299
|
-
expiresInSeconds,
|
300
|
-
};
|
301
|
-
}
|
302
|
-
else {
|
303
|
-
logger.info(`SetAppTokenProvider token has "no_access_token_returned" as the saved token`);
|
304
|
-
return {
|
305
|
-
accessToken: "no_access_token_returned",
|
306
|
-
expiresInSeconds: 0,
|
307
|
-
};
|
308
|
-
}
|
309
|
-
});
|
310
|
-
this.isAppTokenProviderInitialized = true;
|
311
|
-
}
|
30
|
+
return this.implProvider.getToken(scopes, options);
|
312
31
|
}
|
313
32
|
}
|
314
33
|
//# sourceMappingURL=index.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/index.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport { AppTokenProviderParameters, ConfidentialClientApplication } from \"@azure/msal-node\";\nimport {\n AuthenticationError,\n AuthenticationRequiredError,\n CredentialUnavailableError,\n} from \"../../errors\";\nimport { MSI, MSIConfiguration, MSIToken } from \"./models\";\nimport { MsalResult, MsalToken, ValidMsalToken } from \"../../msal/types\";\nimport { credentialLogger, formatError, formatSuccess } from \"../../util/logging\";\n\nimport { DeveloperSignOnClientId } from \"../../constants\";\nimport { IdentityClient } from \"../../client/identityClient\";\nimport { TokenCredentialOptions } from \"../../tokenCredentialOptions\";\nimport { appServiceMsi2017 } from \"./appServiceMsi2017\";\nimport { appServiceMsi2019 } from \"./appServiceMsi2019\";\nimport { arcMsi } from \"./arcMsi\";\nimport { cloudShellMsi } from \"./cloudShellMsi\";\nimport { fabricMsi } from \"./fabricMsi\";\nimport { getLogLevel } from \"@azure/logger\";\nimport { getMSALLogLevel } from \"../../msal/utils\";\nimport { imdsMsi } from \"./imdsMsi\";\nimport { tokenExchangeMsi } from \"./tokenExchangeMsi\";\nimport { tracingClient } from \"../../util/tracing\";\n\nconst logger = credentialLogger(\"ManagedIdentityCredential\");\n\n/**\n * Options to send on the {@link ManagedIdentityCredential} constructor.\n * This variation supports `clientId` and not `resourceId`, since only one of both is supported.\n */\nexport interface ManagedIdentityCredentialClientIdOptions 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/**\n * Options to send on the {@link ManagedIdentityCredential} constructor.\n * This variation supports `resourceId` and not `clientId`, since only one of both is supported.\n */\nexport interface ManagedIdentityCredentialResourceIdOptions extends TokenCredentialOptions {\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\n/**\n * Attempts authentication using a managed identity available at the deployment environment.\n * This authentication type works in Azure VMs, App Service instances, Azure Functions applications,\n * Azure Kubernetes Services, Azure Service Fabric instances and inside of the Azure Cloud Shell.\n *\n * More information about configuring managed identities can be found here:\n * https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview\n */\nexport class ManagedIdentityCredential implements TokenCredential {\n private identityClient: IdentityClient;\n private clientId: string | undefined;\n private resourceId: string | undefined;\n private isEndpointUnavailable: boolean | null = null;\n private isAvailableIdentityClient: IdentityClient;\n private confidentialApp: ConfidentialClientApplication;\n private isAppTokenProviderInitialized: boolean = false;\n private msiRetryConfig: MSIConfiguration[\"retryConfig\"] = {\n maxRetries: 5,\n startDelayInMs: 800,\n intervalIncrement: 2,\n };\n\n /**\n * Creates an instance of ManagedIdentityCredential with the client ID of a\n * user-assigned identity, or app registration (when working with AKS pod-identity).\n *\n * @param clientId - The client ID of the user-assigned identity, or app registration (when working with AKS pod-identity).\n * @param options - Options for configuring the client which makes the access token request.\n */\n constructor(clientId: string, options?: TokenCredentialOptions);\n /**\n * Creates an instance of ManagedIdentityCredential with clientId\n *\n * @param options - Options for configuring the client which makes the access token request.\n */\n constructor(options?: ManagedIdentityCredentialClientIdOptions);\n /**\n * Creates an instance of ManagedIdentityCredential with Resource Id\n *\n * @param options - Options for configuring the resource which makes the access token request.\n */\n constructor(options?: ManagedIdentityCredentialResourceIdOptions);\n /**\n * @internal\n * @hidden\n */\n constructor(\n clientIdOrOptions?:\n | string\n | ManagedIdentityCredentialClientIdOptions\n | ManagedIdentityCredentialResourceIdOptions,\n options?: TokenCredentialOptions,\n ) {\n let _options: TokenCredentialOptions | undefined;\n if (typeof clientIdOrOptions === \"string\") {\n this.clientId = clientIdOrOptions;\n _options = options;\n } else {\n this.clientId = (clientIdOrOptions as ManagedIdentityCredentialClientIdOptions)?.clientId;\n _options = clientIdOrOptions;\n }\n this.resourceId = (_options as ManagedIdentityCredentialResourceIdOptions)?.resourceId;\n // For JavaScript users.\n if (this.clientId && this.resourceId) {\n throw new Error(\n `${ManagedIdentityCredential.name} - Client Id and Resource Id can't be provided at the same time.`,\n );\n }\n if (_options?.retryOptions?.maxRetries !== undefined) {\n this.msiRetryConfig.maxRetries = _options.retryOptions.maxRetries;\n }\n this.identityClient = new IdentityClient(_options);\n this.isAvailableIdentityClient = new IdentityClient({\n ..._options,\n retryOptions: {\n maxRetries: 0,\n },\n });\n\n /** authority host validation and metadata discovery to be skipped in managed identity\n * since this wasn't done previously before adding token cache support\n */\n this.confidentialApp = new ConfidentialClientApplication({\n auth: {\n authority: \"https://login.microsoftonline.com/managed_identity\",\n clientId: this.clientId ?? DeveloperSignOnClientId,\n clientSecret: \"dummy-secret\",\n cloudDiscoveryMetadata:\n '{\"tenant_discovery_endpoint\":\"https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration\",\"api-version\":\"1.1\",\"metadata\":[{\"preferred_network\":\"login.microsoftonline.com\",\"preferred_cache\":\"login.windows.net\",\"aliases\":[\"login.microsoftonline.com\",\"login.windows.net\",\"login.microsoft.com\",\"sts.windows.net\"]},{\"preferred_network\":\"login.partner.microsoftonline.cn\",\"preferred_cache\":\"login.partner.microsoftonline.cn\",\"aliases\":[\"login.partner.microsoftonline.cn\",\"login.chinacloudapi.cn\"]},{\"preferred_network\":\"login.microsoftonline.de\",\"preferred_cache\":\"login.microsoftonline.de\",\"aliases\":[\"login.microsoftonline.de\"]},{\"preferred_network\":\"login.microsoftonline.us\",\"preferred_cache\":\"login.microsoftonline.us\",\"aliases\":[\"login.microsoftonline.us\",\"login.usgovcloudapi.net\"]},{\"preferred_network\":\"login-us.microsoftonline.com\",\"preferred_cache\":\"login-us.microsoftonline.com\",\"aliases\":[\"login-us.microsoftonline.com\"]}]}',\n authorityMetadata:\n '{\"token_endpoint\":\"https://login.microsoftonline.com/common/oauth2/v2.0/token\",\"token_endpoint_auth_methods_supported\":[\"client_secret_post\",\"private_key_jwt\",\"client_secret_basic\"],\"jwks_uri\":\"https://login.microsoftonline.com/common/discovery/v2.0/keys\",\"response_modes_supported\":[\"query\",\"fragment\",\"form_post\"],\"subject_types_supported\":[\"pairwise\"],\"id_token_signing_alg_values_supported\":[\"RS256\"],\"response_types_supported\":[\"code\",\"id_token\",\"code id_token\",\"id_token token\"],\"scopes_supported\":[\"openid\",\"profile\",\"email\",\"offline_access\"],\"issuer\":\"https://login.microsoftonline.com/{tenantid}/v2.0\",\"request_uri_parameter_supported\":false,\"userinfo_endpoint\":\"https://graph.microsoft.com/oidc/userinfo\",\"authorization_endpoint\":\"https://login.microsoftonline.com/common/oauth2/v2.0/authorize\",\"device_authorization_endpoint\":\"https://login.microsoftonline.com/common/oauth2/v2.0/devicecode\",\"http_logout_supported\":true,\"frontchannel_logout_supported\":true,\"end_session_endpoint\":\"https://login.microsoftonline.com/common/oauth2/v2.0/logout\",\"claims_supported\":[\"sub\",\"iss\",\"cloud_instance_name\",\"cloud_instance_host_name\",\"cloud_graph_host_name\",\"msgraph_host\",\"aud\",\"exp\",\"iat\",\"auth_time\",\"acr\",\"nonce\",\"preferred_username\",\"name\",\"tid\",\"ver\",\"at_hash\",\"c_hash\",\"email\"],\"kerberos_endpoint\":\"https://login.microsoftonline.com/common/kerberos\",\"tenant_region_scope\":null,\"cloud_instance_name\":\"microsoftonline.com\",\"cloud_graph_host_name\":\"graph.windows.net\",\"msgraph_host\":\"graph.microsoft.com\",\"rbac_url\":\"https://pas.windows.net\"}',\n clientCapabilities: [],\n },\n system: {\n loggerOptions: {\n logLevel: getMSALLogLevel(getLogLevel()),\n },\n },\n });\n }\n\n private cachedMSI: MSI | undefined;\n\n private async cachedAvailableMSI(\n scopes: string | string[],\n getTokenOptions?: GetTokenOptions,\n ): Promise<MSI> {\n if (this.cachedMSI) {\n return this.cachedMSI;\n }\n\n const MSIs = [\n arcMsi,\n fabricMsi,\n appServiceMsi2019,\n appServiceMsi2017,\n cloudShellMsi,\n tokenExchangeMsi(),\n imdsMsi,\n ];\n\n for (const msi of MSIs) {\n if (\n await msi.isAvailable({\n scopes,\n identityClient: this.isAvailableIdentityClient,\n clientId: this.clientId,\n resourceId: this.resourceId,\n getTokenOptions,\n })\n ) {\n this.cachedMSI = msi;\n return msi;\n }\n }\n\n throw new CredentialUnavailableError(\n `${ManagedIdentityCredential.name} - No MSI credential available`,\n );\n }\n\n private async authenticateManagedIdentity(\n scopes: string | string[],\n getTokenOptions?: GetTokenOptions,\n ): Promise<MSIToken | null> {\n const { span, updatedOptions } = tracingClient.startSpan(\n `${ManagedIdentityCredential.name}.authenticateManagedIdentity`,\n getTokenOptions,\n );\n\n try {\n // Determining the available MSI, and avoiding checking for other MSIs while the program is running.\n const availableMSI = await this.cachedAvailableMSI(scopes, updatedOptions);\n return availableMSI.getToken(\n {\n identityClient: this.identityClient,\n scopes,\n clientId: this.clientId,\n resourceId: this.resourceId,\n retryConfig: this.msiRetryConfig,\n },\n updatedOptions,\n );\n } catch (err: any) {\n span.setStatus({\n status: \"error\",\n error: err,\n });\n throw err;\n } finally {\n span.end();\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 let result: AccessToken | null = null;\n const { span, updatedOptions } = tracingClient.startSpan(\n `${ManagedIdentityCredential.name}.getToken`,\n options,\n );\n try {\n // isEndpointAvailable can be true, false, or null,\n // If it's null, it means we don't yet know whether\n // the endpoint is available and need to check for it.\n if (this.isEndpointUnavailable !== true) {\n const availableMSI = await this.cachedAvailableMSI(scopes, updatedOptions);\n if (availableMSI.name === \"tokenExchangeMsi\") {\n result = await this.authenticateManagedIdentity(scopes, updatedOptions);\n } else {\n const appTokenParameters: AppTokenProviderParameters = {\n correlationId: this.identityClient.getCorrelationId(),\n tenantId: options?.tenantId || \"managed_identity\",\n scopes: Array.isArray(scopes) ? scopes : [scopes],\n claims: options?.claims,\n };\n\n // Added a check to see if SetAppTokenProvider was already defined.\n this.initializeSetAppTokenProvider();\n const authenticationResult = await this.confidentialApp.acquireTokenByClientCredential({\n ...appTokenParameters,\n });\n result = this.handleResult(scopes, authenticationResult || undefined);\n }\n if (result === null) {\n // If authenticateManagedIdentity returns null,\n // it means no MSI endpoints are available.\n // If so, we avoid trying to reach to them in future requests.\n this.isEndpointUnavailable = true;\n\n // It also means that the endpoint answered with either 200 or 201 (see the sendTokenRequest method),\n // yet we had no access token. For this reason, we'll throw once with a specific message:\n const error = new CredentialUnavailableError(\n \"The managed identity endpoint was reached, yet no tokens were received.\",\n );\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n\n // Since `authenticateManagedIdentity` didn't throw, and the result was not null,\n // We will assume that this endpoint is reachable from this point forward,\n // and avoid pinging again to it.\n this.isEndpointUnavailable = false;\n } else {\n // We've previously determined that the endpoint was unavailable,\n // either because it was unreachable or permanently unable to authenticate.\n const error = new CredentialUnavailableError(\n \"The managed identity endpoint is not currently available\",\n );\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n\n logger.getToken.info(formatSuccess(scopes));\n return result;\n } catch (err: any) {\n // CredentialUnavailable errors are expected to reach here.\n // We intend them to bubble up, so that DefaultAzureCredential can catch them.\n if (err.name === \"AuthenticationRequiredError\") {\n throw err;\n }\n\n // Expected errors to reach this point:\n // - Errors coming from a method unexpectedly breaking.\n // - When identityClient.sendTokenRequest throws, in which case\n // if the status code was 400, it means that the endpoint is working,\n // but no identity is available.\n\n span.setStatus({\n status: \"error\",\n error: err,\n });\n\n // If either the network is unreachable,\n // we can safely assume the credential is unavailable.\n if (err.code === \"ENETUNREACH\") {\n const error = new CredentialUnavailableError(\n `${ManagedIdentityCredential.name}: Unavailable. Network unreachable. Message: ${err.message}`,\n );\n\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n\n // If either the host was unreachable,\n // we can safely assume the credential is unavailable.\n if (err.code === \"EHOSTUNREACH\") {\n const error = new CredentialUnavailableError(\n `${ManagedIdentityCredential.name}: Unavailable. No managed identity endpoint found. Message: ${err.message}`,\n );\n\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n // If err.statusCode has a value of 400, it comes from sendTokenRequest,\n // and it means that the endpoint is working, but that no identity is available.\n if (err.statusCode === 400) {\n throw new CredentialUnavailableError(\n `${ManagedIdentityCredential.name}: The managed identity endpoint is indicating there's no available identity. Message: ${err.message}`,\n );\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 const error = new CredentialUnavailableError(\n `${ManagedIdentityCredential.name}: Unavailable. Network unreachable. Message: ${err.message}`,\n );\n\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n }\n\n // If the error has no status code, we can assume there was no available identity.\n // This will throw silently during any ChainedTokenCredential.\n if (err.statusCode === undefined) {\n throw new CredentialUnavailableError(\n `${ManagedIdentityCredential.name}: Authentication failed. Message ${err.message}`,\n );\n }\n\n // Any other error should break the chain.\n throw new AuthenticationError(err.statusCode, {\n error: `${ManagedIdentityCredential.name} authentication failed.`,\n error_description: err.message,\n });\n } finally {\n // Finally is always called, both if we return and if we throw in the above try/catch.\n span.end();\n }\n }\n\n /**\n * Handles the MSAL authentication result.\n * If the result has an account, we update the local account reference.\n * If the token received is invalid, an error will be thrown depending on what's missing.\n */\n private handleResult(\n scopes: string | string[],\n result?: MsalResult,\n getTokenOptions?: GetTokenOptions,\n ): AccessToken {\n this.ensureValidMsalToken(scopes, result, getTokenOptions);\n logger.getToken.info(formatSuccess(scopes));\n return {\n token: result.accessToken,\n expiresOnTimestamp: result.expiresOn.getTime(),\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 error = (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 error(\"No response\");\n }\n if (!msalToken.expiresOn) {\n throw error(`Response had no \"expiresOn\" property.`);\n }\n if (!msalToken.accessToken) {\n throw error(`Response had no \"accessToken\" property.`);\n }\n }\n\n private initializeSetAppTokenProvider(): void {\n if (!this.isAppTokenProviderInitialized) {\n this.confidentialApp.SetAppTokenProvider(async (appTokenProviderParameters) => {\n logger.info(\n `SetAppTokenProvider invoked with parameters- ${JSON.stringify(\n appTokenProviderParameters,\n )}`,\n );\n const getTokenOptions: GetTokenOptions = {\n ...appTokenProviderParameters,\n };\n logger.info(\n `authenticateManagedIdentity invoked with scopes- ${JSON.stringify(\n appTokenProviderParameters.scopes,\n )} and getTokenOptions - ${JSON.stringify(getTokenOptions)}`,\n );\n const resultToken = await this.authenticateManagedIdentity(\n appTokenProviderParameters.scopes,\n getTokenOptions,\n );\n\n if (resultToken) {\n logger.info(`SetAppTokenProvider will save the token in cache`);\n\n const expiresInSeconds = resultToken?.expiresOnTimestamp\n ? Math.floor((resultToken.expiresOnTimestamp - Date.now()) / 1000)\n : 0;\n return {\n accessToken: resultToken?.token,\n expiresInSeconds,\n };\n } else {\n logger.info(\n `SetAppTokenProvider token has \"no_access_token_returned\" as the saved token`,\n );\n return {\n accessToken: \"no_access_token_returned\",\n expiresInSeconds: 0,\n };\n }\n });\n this.isAppTokenProviderInitialized = true;\n }\n }\n}\n"]}
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/index.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAIlC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AA6BxD;;;;;;;GAOG;AACH,MAAM,OAAO,yBAAyB;IAuBpC;;;OAGG;IACH,YACE,iBAG8C,EAC9C,OAAgC;QAEhC,IAAI,CAAC,YAAY,GAAG,IAAI,iBAAiB,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;IACxE,CAAC;IAED;;;;;;;;OAQG;IACI,KAAK,CAAC,QAAQ,CACnB,MAAyB,EACzB,OAAyB;QAEzB,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrD,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\n\nimport { LegacyMsiProvider } from \"./legacyMsiProvider\";\nimport { TokenCredentialOptions } from \"../../tokenCredentialOptions\";\n\n/**\n * Options to send on the {@link ManagedIdentityCredential} constructor.\n * This variation supports `clientId` and not `resourceId`, since only one of both is supported.\n */\nexport interface ManagedIdentityCredentialClientIdOptions 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/**\n * Options to send on the {@link ManagedIdentityCredential} constructor.\n * This variation supports `resourceId` and not `clientId`, since only one of both is supported.\n */\nexport interface ManagedIdentityCredentialResourceIdOptions extends TokenCredentialOptions {\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\n/**\n * Attempts authentication using a managed identity available at the deployment environment.\n * This authentication type works in Azure VMs, App Service instances, Azure Functions applications,\n * Azure Kubernetes Services, Azure Service Fabric instances and inside of the Azure Cloud Shell.\n *\n * More information about configuring managed identities can be found here:\n * https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview\n */\nexport class ManagedIdentityCredential implements TokenCredential {\n private implProvider: LegacyMsiProvider;\n\n /**\n * Creates an instance of ManagedIdentityCredential with the client ID of a\n * user-assigned identity, or app registration (when working with AKS pod-identity).\n *\n * @param clientId - The client ID of the user-assigned identity, or app registration (when working with AKS pod-identity).\n * @param options - Options for configuring the client which makes the access token request.\n */\n constructor(clientId: string, options?: TokenCredentialOptions);\n /**\n * Creates an instance of ManagedIdentityCredential with clientId\n *\n * @param options - Options for configuring the client which makes the access token request.\n */\n constructor(options?: ManagedIdentityCredentialClientIdOptions);\n /**\n * Creates an instance of ManagedIdentityCredential with Resource Id\n *\n * @param options - Options for configuring the resource which makes the access token request.\n */\n constructor(options?: ManagedIdentityCredentialResourceIdOptions);\n /**\n * @internal\n * @hidden\n */\n constructor(\n clientIdOrOptions?:\n | string\n | ManagedIdentityCredentialClientIdOptions\n | ManagedIdentityCredentialResourceIdOptions,\n options?: TokenCredentialOptions,\n ) {\n this.implProvider = new LegacyMsiProvider(clientIdOrOptions, options);\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 return this.implProvider.getToken(scopes, options);\n }\n}\n"]}
|