@azure/identity 2.0.0-beta.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of @azure/identity might be problematic. Click here for more details.
- package/CHANGELOG.md +232 -6
- package/README.md +124 -39
- package/dist/index.js +2317 -1596
- package/dist/index.js.map +1 -1
- package/dist-esm/src/client/identityClient.js +147 -133
- 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/authorizationCodeCredential.browser.js +1 -1
- package/dist-esm/src/credentials/authorizationCodeCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/authorizationCodeCredential.js +13 -76
- package/dist-esm/src/credentials/authorizationCodeCredential.js.map +1 -1
- package/dist-esm/src/credentials/azureApplicationCredential.browser.js +34 -0
- package/dist-esm/src/credentials/azureApplicationCredential.browser.js.map +1 -0
- package/dist-esm/src/credentials/azureApplicationCredential.js +36 -0
- package/dist-esm/src/credentials/azureApplicationCredential.js.map +1 -0
- package/dist-esm/src/credentials/azureCliCredential.browser.js +7 -0
- package/dist-esm/src/credentials/azureCliCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/azureCliCredential.js +110 -83
- package/dist-esm/src/credentials/azureCliCredential.js.map +1 -1
- package/dist-esm/src/credentials/azureCliCredentialOptions.js +4 -0
- package/dist-esm/src/credentials/azureCliCredentialOptions.js.map +1 -0
- package/dist-esm/src/credentials/azurePowerShellCredential.browser.js +3 -1
- package/dist-esm/src/credentials/azurePowerShellCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/azurePowerShellCredential.js +93 -83
- package/dist-esm/src/credentials/azurePowerShellCredential.js.map +1 -1
- package/dist-esm/src/credentials/azurePowerShellCredentialOptions.js +4 -0
- package/dist-esm/src/credentials/azurePowerShellCredentialOptions.js.map +1 -0
- package/dist-esm/src/credentials/chainedTokenCredential.js +34 -37
- package/dist-esm/src/credentials/chainedTokenCredential.js.map +1 -1
- package/dist-esm/src/credentials/clientCertificateCredential.browser.js +7 -0
- package/dist-esm/src/credentials/clientCertificateCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/clientCertificateCredential.js +24 -23
- package/dist-esm/src/credentials/clientCertificateCredential.js.map +1 -1
- package/dist-esm/src/credentials/clientCertificateCredentialOptions.js.map +1 -1
- package/dist-esm/src/credentials/clientSecretCredential.browser.js +39 -44
- package/dist-esm/src/credentials/clientSecretCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/clientSecretCredential.js +9 -11
- package/dist-esm/src/credentials/clientSecretCredential.js.map +1 -1
- package/dist-esm/src/credentials/clientSecretCredentialOptions.js.map +1 -1
- package/dist-esm/src/credentials/credentialPersistenceOptions.js +4 -0
- package/dist-esm/src/credentials/credentialPersistenceOptions.js.map +1 -0
- package/dist-esm/src/credentials/defaultAzureCredential.browser.js +1 -1
- package/dist-esm/src/credentials/defaultAzureCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/defaultAzureCredential.js +50 -27
- package/dist-esm/src/credentials/defaultAzureCredential.js.map +1 -1
- package/dist-esm/src/credentials/deviceCodeCredential.browser.js +7 -0
- package/dist-esm/src/credentials/deviceCodeCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/deviceCodeCredential.js +27 -22
- 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.browser.js +7 -0
- package/dist-esm/src/credentials/environmentCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/environmentCredential.js +39 -38
- package/dist-esm/src/credentials/environmentCredential.js.map +1 -1
- package/dist-esm/src/credentials/interactiveBrowserCredential.browser.js +20 -29
- package/dist-esm/src/credentials/interactiveBrowserCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/interactiveBrowserCredential.js +23 -29
- 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/appServiceMsi2017.js +36 -22
- package/dist-esm/src/credentials/managedIdentityCredential/appServiceMsi2017.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/arcMsi.js +62 -47
- package/dist-esm/src/credentials/managedIdentityCredential/arcMsi.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/cloudShellMsi.js +33 -22
- package/dist-esm/src/credentials/managedIdentityCredential/cloudShellMsi.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/constants.js +2 -1
- package/dist-esm/src/credentials/managedIdentityCredential/constants.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/fabricMsi.js +42 -27
- package/dist-esm/src/credentials/managedIdentityCredential/fabricMsi.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/imdsMsi.js +115 -91
- package/dist-esm/src/credentials/managedIdentityCredential/imdsMsi.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/index.browser.js +3 -6
- package/dist-esm/src/credentials/managedIdentityCredential/index.browser.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/index.js +120 -125
- package/dist-esm/src/credentials/managedIdentityCredential/index.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/models.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/tokenExchangeMsi.js +82 -0
- package/dist-esm/src/credentials/managedIdentityCredential/tokenExchangeMsi.js.map +1 -0
- package/dist-esm/src/credentials/managedIdentityCredential/utils.js +14 -8
- package/dist-esm/src/credentials/managedIdentityCredential/utils.js.map +1 -1
- package/dist-esm/src/credentials/onBehalfOfCredential.browser.js +23 -0
- package/dist-esm/src/credentials/onBehalfOfCredential.browser.js.map +1 -0
- package/dist-esm/src/credentials/onBehalfOfCredential.js +57 -0
- package/dist-esm/src/credentials/onBehalfOfCredential.js.map +1 -0
- package/dist-esm/src/credentials/onBehalfOfCredentialOptions.js +4 -0
- package/dist-esm/src/credentials/onBehalfOfCredentialOptions.js.map +1 -0
- package/dist-esm/src/credentials/usernamePasswordCredential.browser.js +41 -46
- package/dist-esm/src/credentials/usernamePasswordCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/usernamePasswordCredential.js +9 -13
- package/dist-esm/src/credentials/usernamePasswordCredential.js.map +1 -1
- package/dist-esm/src/credentials/usernamePasswordCredentialOptions.js.map +1 -1
- package/dist-esm/src/credentials/visualStudioCodeCredential.browser.js +27 -0
- package/dist-esm/src/credentials/visualStudioCodeCredential.browser.js.map +1 -0
- package/dist-esm/src/credentials/visualStudioCodeCredential.js +183 -0
- package/dist-esm/src/credentials/visualStudioCodeCredential.js.map +1 -0
- package/dist-esm/src/credentials/visualStudioCodeCredentialPlugin.js +4 -0
- package/dist-esm/src/credentials/visualStudioCodeCredentialPlugin.js.map +1 -0
- package/dist-esm/src/{client/errors.js → errors.js} +16 -1
- package/dist-esm/src/errors.js.map +1 -0
- package/dist-esm/src/index.js +4 -2
- package/dist-esm/src/index.js.map +1 -1
- package/dist-esm/src/msal/browserFlows/browserCommon.js +33 -31
- package/dist-esm/src/msal/browserFlows/browserCommon.js.map +1 -1
- package/dist-esm/src/msal/browserFlows/msalAuthCode.js +113 -115
- package/dist-esm/src/msal/browserFlows/msalAuthCode.js.map +1 -1
- package/dist-esm/src/msal/credentials.js.map +1 -1
- package/dist-esm/src/msal/flows.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalAuthorizationCode.js +41 -0
- package/dist-esm/src/msal/nodeFlows/msalAuthorizationCode.js.map +1 -0
- package/dist-esm/src/msal/nodeFlows/msalClientCertificate.js +65 -46
- package/dist-esm/src/msal/nodeFlows/msalClientCertificate.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalClientSecret.js +15 -16
- package/dist-esm/src/msal/nodeFlows/msalClientSecret.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalDeviceCode.js +20 -22
- package/dist-esm/src/msal/nodeFlows/msalDeviceCode.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalOnBehalfOf.js +56 -0
- package/dist-esm/src/msal/nodeFlows/msalOnBehalfOf.js.map +1 -0
- package/dist-esm/src/msal/nodeFlows/msalOpenBrowser.js +44 -33
- package/dist-esm/src/msal/nodeFlows/msalOpenBrowser.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalUsernamePassword.js +15 -17
- package/dist-esm/src/msal/nodeFlows/msalUsernamePassword.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/nodeCommon.js +141 -98
- package/dist-esm/src/msal/nodeFlows/nodeCommon.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/tokenCachePersistenceOptions.js +4 -0
- package/dist-esm/src/msal/nodeFlows/tokenCachePersistenceOptions.js.map +1 -0
- package/dist-esm/src/msal/utils.js +23 -15
- package/dist-esm/src/msal/utils.js.map +1 -1
- package/dist-esm/src/plugins/consumer.browser.js +7 -0
- package/dist-esm/src/plugins/consumer.browser.js.map +1 -0
- package/dist-esm/src/plugins/consumer.js +44 -0
- package/dist-esm/src/plugins/consumer.js.map +1 -0
- package/dist-esm/src/plugins/provider.js +4 -0
- package/dist-esm/src/plugins/provider.js.map +1 -0
- package/dist-esm/src/regionalAuthority.js +115 -0
- package/dist-esm/src/regionalAuthority.js.map +1 -0
- package/dist-esm/src/util/tracing.js +24 -27
- package/dist-esm/src/util/tracing.js.map +1 -1
- package/dist-esm/src/util/validateMultiTenant.browser.js +22 -0
- package/dist-esm/src/util/validateMultiTenant.browser.js.map +1 -0
- package/dist-esm/src/util/validateMultiTenant.js +29 -0
- package/dist-esm/src/util/validateMultiTenant.js.map +1 -0
- package/package.json +44 -28
- package/types/identity.d.ts +482 -126
- package/dist-esm/src/client/errors.js.map +0 -1
- package/dist-esm/src/msal/errors.js +0 -22
- package/dist-esm/src/msal/errors.js.map +0 -1
- package/dist-esm/src/util/authHostEnv.js +0 -13
- package/dist-esm/src/util/authHostEnv.js.map +0 -1
|
@@ -1,150 +1,158 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT license.
|
|
3
|
-
import {
|
|
4
|
-
import qs from "qs";
|
|
5
|
-
import { ServiceClient, WebResource, createPipelineFromOptions, isNode } from "@azure/core-http";
|
|
3
|
+
import { ServiceClient } from "@azure/core-client";
|
|
6
4
|
import { SpanStatusCode } from "@azure/core-tracing";
|
|
5
|
+
import { isNode } from "@azure/core-util";
|
|
6
|
+
import { createHttpHeaders, createPipelineRequest } from "@azure/core-rest-pipeline";
|
|
7
7
|
import { AbortController } from "@azure/abort-controller";
|
|
8
|
-
import { AuthenticationError, AuthenticationErrorName } from "
|
|
9
|
-
import { getAuthorityHostEnvironment } from "../util/authHostEnv";
|
|
8
|
+
import { AuthenticationError, AuthenticationErrorName } from "../errors";
|
|
10
9
|
import { getIdentityTokenEndpointSuffix } from "../util/identityTokenEndpoint";
|
|
11
10
|
import { DefaultAuthorityHost } from "../constants";
|
|
12
11
|
import { createSpan } from "../util/tracing";
|
|
13
12
|
import { logger } from "../util/logging";
|
|
14
13
|
const noCorrelationId = "noCorrelationId";
|
|
14
|
+
/**
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
export function getIdentityClientAuthorityHost(options) {
|
|
18
|
+
// The authorityHost can come from options or from the AZURE_AUTHORITY_HOST environment variable.
|
|
19
|
+
let authorityHost = options === null || options === void 0 ? void 0 : options.authorityHost;
|
|
20
|
+
// The AZURE_AUTHORITY_HOST environment variable can only be provided in Node.js.
|
|
21
|
+
if (isNode) {
|
|
22
|
+
authorityHost = authorityHost !== null && authorityHost !== void 0 ? authorityHost : process.env.AZURE_AUTHORITY_HOST;
|
|
23
|
+
}
|
|
24
|
+
// If the authorityHost is not provided, we use the default one from the public cloud: https://login.microsoftonline.com
|
|
25
|
+
return authorityHost !== null && authorityHost !== void 0 ? authorityHost : DefaultAuthorityHost;
|
|
26
|
+
}
|
|
15
27
|
/**
|
|
16
28
|
* The network module used by the Identity credentials.
|
|
17
29
|
*
|
|
18
30
|
* It allows for credentials to abort any pending request independently of the MSAL flow,
|
|
19
31
|
* by calling to the `abortRequests()` method.
|
|
20
32
|
*
|
|
21
|
-
* @internal
|
|
22
33
|
*/
|
|
23
34
|
export class IdentityClient extends ServiceClient {
|
|
24
35
|
constructor(options) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
json: ["application/json", "text/json", "text/plain"]
|
|
33
|
-
}
|
|
34
|
-
} })));
|
|
35
|
-
this.baseUri = this.authorityHost = options.authorityHost || DefaultAuthorityHost;
|
|
36
|
-
if (!this.baseUri.startsWith("https:")) {
|
|
36
|
+
var _a;
|
|
37
|
+
const packageDetails = `azsdk-js-identity/2.0.0`;
|
|
38
|
+
const userAgentPrefix = ((_a = options === null || options === void 0 ? void 0 : options.userAgentOptions) === null || _a === void 0 ? void 0 : _a.userAgentPrefix)
|
|
39
|
+
? `${options.userAgentOptions.userAgentPrefix} ${packageDetails}`
|
|
40
|
+
: `${packageDetails}`;
|
|
41
|
+
const baseUri = getIdentityClientAuthorityHost(options);
|
|
42
|
+
if (!baseUri.startsWith("https:")) {
|
|
37
43
|
throw new Error("The authorityHost address must use the 'https' protocol.");
|
|
38
44
|
}
|
|
45
|
+
super(Object.assign(Object.assign({ requestContentType: "application/json; charset=utf-8" }, options), { userAgentOptions: {
|
|
46
|
+
userAgentPrefix
|
|
47
|
+
}, baseUri }));
|
|
48
|
+
this.authorityHost = baseUri;
|
|
39
49
|
this.abortControllers = new Map();
|
|
40
50
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
((responseBody) => {
|
|
53
|
-
return Date.now() + responseBody.expires_in * 1000;
|
|
54
|
-
});
|
|
55
|
-
if (response.status === 200 || response.status === 201) {
|
|
56
|
-
const token = {
|
|
57
|
-
accessToken: {
|
|
58
|
-
token: response.parsedBody.access_token,
|
|
59
|
-
expiresOnTimestamp: expiresOnParser(response.parsedBody)
|
|
60
|
-
},
|
|
61
|
-
refreshToken: response.parsedBody.refresh_token
|
|
62
|
-
};
|
|
63
|
-
logger.info(`IdentityClient: [${webResource.url}] token acquired, expires on ${token.accessToken.expiresOnTimestamp}`);
|
|
64
|
-
return token;
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
const error = new AuthenticationError(response.status, response.parsedBody || response.bodyAsText);
|
|
68
|
-
logger.warning(`IdentityClient: authentication error. HTTP status: ${response.status}, ${error.errorResponse.errorDescription}`);
|
|
69
|
-
throw error;
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
refreshAccessToken(tenantId, clientId, scopes, refreshToken, clientSecret, expiresOnParser, options) {
|
|
74
|
-
var _a, _b;
|
|
75
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
76
|
-
if (refreshToken === undefined) {
|
|
51
|
+
async sendTokenRequest(request, expiresOnParser) {
|
|
52
|
+
logger.info(`IdentityClient: sending token request to [${request.url}]`);
|
|
53
|
+
const response = await this.sendRequest(request);
|
|
54
|
+
expiresOnParser =
|
|
55
|
+
expiresOnParser ||
|
|
56
|
+
((responseBody) => {
|
|
57
|
+
return Date.now() + responseBody.expires_in * 1000;
|
|
58
|
+
});
|
|
59
|
+
if (response.bodyAsText && (response.status === 200 || response.status === 201)) {
|
|
60
|
+
const parsedBody = JSON.parse(response.bodyAsText);
|
|
61
|
+
if (!parsedBody.access_token) {
|
|
77
62
|
return null;
|
|
78
63
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
scope: scopes
|
|
64
|
+
const token = {
|
|
65
|
+
accessToken: {
|
|
66
|
+
token: parsedBody.access_token,
|
|
67
|
+
expiresOnTimestamp: expiresOnParser(parsedBody)
|
|
68
|
+
},
|
|
69
|
+
refreshToken: parsedBody.refresh_token
|
|
86
70
|
};
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
71
|
+
logger.info(`IdentityClient: [${request.url}] token acquired, expires on ${token.accessToken.expiresOnTimestamp}`);
|
|
72
|
+
return token;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
const error = new AuthenticationError(response.status, response.bodyAsText);
|
|
76
|
+
logger.warning(`IdentityClient: authentication error. HTTP status: ${response.status}, ${error.errorResponse.errorDescription}`);
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async refreshAccessToken(tenantId, clientId, scopes, refreshToken, clientSecret, expiresOnParser, options) {
|
|
81
|
+
if (refreshToken === undefined) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
logger.info(`IdentityClient: refreshing access token with client ID: ${clientId}, scopes: ${scopes} started`);
|
|
85
|
+
const { span, updatedOptions } = createSpan("IdentityClient-refreshAccessToken", options);
|
|
86
|
+
const refreshParams = {
|
|
87
|
+
grant_type: "refresh_token",
|
|
88
|
+
client_id: clientId,
|
|
89
|
+
refresh_token: refreshToken,
|
|
90
|
+
scope: scopes
|
|
91
|
+
};
|
|
92
|
+
if (clientSecret !== undefined) {
|
|
93
|
+
refreshParams.client_secret = clientSecret;
|
|
94
|
+
}
|
|
95
|
+
const query = new URLSearchParams(refreshParams);
|
|
96
|
+
try {
|
|
97
|
+
const urlSuffix = getIdentityTokenEndpointSuffix(tenantId);
|
|
98
|
+
const request = createPipelineRequest({
|
|
99
|
+
url: `${this.authorityHost}/${tenantId}/${urlSuffix}`,
|
|
100
|
+
method: "POST",
|
|
101
|
+
body: query.toString(),
|
|
102
|
+
abortSignal: options && options.abortSignal,
|
|
103
|
+
headers: createHttpHeaders({
|
|
104
|
+
Accept: "application/json",
|
|
105
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
106
|
+
}),
|
|
107
|
+
tracingOptions: updatedOptions === null || updatedOptions === void 0 ? void 0 : updatedOptions.tracingOptions
|
|
108
|
+
});
|
|
109
|
+
const response = await this.sendTokenRequest(request, expiresOnParser);
|
|
110
|
+
logger.info(`IdentityClient: refreshed token for client ID: ${clientId}`);
|
|
111
|
+
return response;
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
if (err.name === AuthenticationErrorName &&
|
|
115
|
+
err.errorResponse.error === "interaction_required") {
|
|
116
|
+
// It's likely that the refresh token has expired, so
|
|
117
|
+
// return null so that the credential implementation will
|
|
118
|
+
// initiate the authentication flow again.
|
|
119
|
+
logger.info(`IdentityClient: interaction required for client ID: ${clientId}`);
|
|
120
|
+
span.setStatus({
|
|
121
|
+
code: SpanStatusCode.ERROR,
|
|
122
|
+
message: err.message
|
|
105
123
|
});
|
|
106
|
-
|
|
107
|
-
logger.info(`IdentityClient: refreshed token for client ID: ${clientId}`);
|
|
108
|
-
return response;
|
|
109
|
-
}
|
|
110
|
-
catch (err) {
|
|
111
|
-
if (err.name === AuthenticationErrorName &&
|
|
112
|
-
err.errorResponse.error === "interaction_required") {
|
|
113
|
-
// It's likely that the refresh token has expired, so
|
|
114
|
-
// return null so that the credential implementation will
|
|
115
|
-
// initiate the authentication flow again.
|
|
116
|
-
logger.info(`IdentityClient: interaction required for client ID: ${clientId}`);
|
|
117
|
-
span.setStatus({
|
|
118
|
-
code: SpanStatusCode.ERROR,
|
|
119
|
-
message: err.message
|
|
120
|
-
});
|
|
121
|
-
return null;
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
logger.warning(`IdentityClient: failed refreshing token for client ID: ${clientId}: ${err}`);
|
|
125
|
-
span.setStatus({
|
|
126
|
-
code: SpanStatusCode.ERROR,
|
|
127
|
-
message: err.message
|
|
128
|
-
});
|
|
129
|
-
throw err;
|
|
130
|
-
}
|
|
124
|
+
return null;
|
|
131
125
|
}
|
|
132
|
-
|
|
133
|
-
|
|
126
|
+
else {
|
|
127
|
+
logger.warning(`IdentityClient: failed refreshing token for client ID: ${clientId}: ${err}`);
|
|
128
|
+
span.setStatus({
|
|
129
|
+
code: SpanStatusCode.ERROR,
|
|
130
|
+
message: err.message
|
|
131
|
+
});
|
|
132
|
+
throw err;
|
|
134
133
|
}
|
|
135
|
-
}
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
span.end();
|
|
137
|
+
}
|
|
136
138
|
}
|
|
137
139
|
// Here is a custom layer that allows us to abort requests that go through MSAL,
|
|
138
140
|
// since MSAL doesn't allow us to pass options all the way through.
|
|
139
141
|
generateAbortSignal(correlationId) {
|
|
140
142
|
const controller = new AbortController();
|
|
141
|
-
const
|
|
142
|
-
const controllers = this.abortControllers.get(key) || [];
|
|
143
|
+
const controllers = this.abortControllers.get(correlationId) || [];
|
|
143
144
|
controllers.push(controller);
|
|
144
|
-
this.abortControllers.set(
|
|
145
|
+
this.abortControllers.set(correlationId, controllers);
|
|
146
|
+
const existingOnAbort = controller.signal.onabort;
|
|
147
|
+
controller.signal.onabort = (...params) => {
|
|
148
|
+
this.abortControllers.set(correlationId, undefined);
|
|
149
|
+
if (existingOnAbort) {
|
|
150
|
+
existingOnAbort(...params);
|
|
151
|
+
}
|
|
152
|
+
};
|
|
145
153
|
return controller.signal;
|
|
146
154
|
}
|
|
147
|
-
abortRequests(correlationId
|
|
155
|
+
abortRequests(correlationId) {
|
|
148
156
|
const key = correlationId || noCorrelationId;
|
|
149
157
|
const controllers = [
|
|
150
158
|
...(this.abortControllers.get(key) || []),
|
|
@@ -158,37 +166,43 @@ export class IdentityClient extends ServiceClient {
|
|
|
158
166
|
controller.abort();
|
|
159
167
|
}
|
|
160
168
|
this.abortControllers.set(key, undefined);
|
|
161
|
-
this.abortControllers.set(noCorrelationId, undefined);
|
|
162
169
|
}
|
|
163
170
|
getCorrelationId(options) {
|
|
164
171
|
var _a;
|
|
165
172
|
const parameter = (_a = options === null || options === void 0 ? void 0 : options.body) === null || _a === void 0 ? void 0 : _a.split("&").map((part) => part.split("=")).find(([key]) => key === "client-request-id");
|
|
166
|
-
return parameter && parameter.length ? parameter[1] : noCorrelationId;
|
|
173
|
+
return parameter && parameter.length ? parameter[1] || noCorrelationId : noCorrelationId;
|
|
167
174
|
}
|
|
168
175
|
// The MSAL network module methods follow
|
|
169
|
-
sendGetRequestAsync(url, options) {
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
headers: response.headers.rawHeaders(),
|
|
177
|
-
status: response.status
|
|
178
|
-
};
|
|
176
|
+
async sendGetRequestAsync(url, options) {
|
|
177
|
+
const request = createPipelineRequest({
|
|
178
|
+
url,
|
|
179
|
+
method: "GET",
|
|
180
|
+
body: options === null || options === void 0 ? void 0 : options.body,
|
|
181
|
+
headers: createHttpHeaders(options === null || options === void 0 ? void 0 : options.headers),
|
|
182
|
+
abortSignal: this.generateAbortSignal(noCorrelationId)
|
|
179
183
|
});
|
|
184
|
+
const response = await this.sendRequest(request);
|
|
185
|
+
return {
|
|
186
|
+
body: response.bodyAsText ? JSON.parse(response.bodyAsText) : undefined,
|
|
187
|
+
headers: response.headers.toJSON(),
|
|
188
|
+
status: response.status
|
|
189
|
+
};
|
|
180
190
|
}
|
|
181
|
-
sendPostRequestAsync(url, options) {
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
status: response.status
|
|
190
|
-
};
|
|
191
|
+
async sendPostRequestAsync(url, options) {
|
|
192
|
+
const request = createPipelineRequest({
|
|
193
|
+
url,
|
|
194
|
+
method: "POST",
|
|
195
|
+
body: options === null || options === void 0 ? void 0 : options.body,
|
|
196
|
+
headers: createHttpHeaders(options === null || options === void 0 ? void 0 : options.headers),
|
|
197
|
+
// MSAL doesn't send the correlation ID on the get requests.
|
|
198
|
+
abortSignal: this.generateAbortSignal(this.getCorrelationId(options))
|
|
191
199
|
});
|
|
200
|
+
const response = await this.sendRequest(request);
|
|
201
|
+
return {
|
|
202
|
+
body: response.bodyAsText ? JSON.parse(response.bodyAsText) : undefined,
|
|
203
|
+
headers: response.headers.toJSON(),
|
|
204
|
+
status: response.status
|
|
205
|
+
};
|
|
192
206
|
}
|
|
193
207
|
}
|
|
194
208
|
//# sourceMappingURL=identityClient.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identityClient.js","sourceRoot":"","sources":["../../../src/client/identityClient.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport qs from \"qs\";\nimport {\n AccessToken,\n ServiceClient,\n PipelineOptions,\n WebResource,\n RequestPrepareOptions,\n GetTokenOptions,\n createPipelineFromOptions,\n isNode\n} from \"@azure/core-http\";\nimport { INetworkModule, NetworkRequestOptions, NetworkResponse } from \"@azure/msal-common\";\nimport { SpanStatusCode } from \"@azure/core-tracing\";\nimport { AbortController, AbortSignalLike } from \"@azure/abort-controller\";\nimport { AuthenticationError, AuthenticationErrorName } from \"./errors\";\nimport { getAuthorityHostEnvironment } from \"../util/authHostEnv\";\nimport { getIdentityTokenEndpointSuffix } from \"../util/identityTokenEndpoint\";\nimport { DefaultAuthorityHost } from \"../constants\";\nimport { createSpan } from \"../util/tracing\";\nimport { logger } from \"../util/logging\";\n\nconst noCorrelationId = \"noCorrelationId\";\n\n/**\n * An internal type used to communicate details of a token request's\n * response that should not be sent back as part of the access token.\n * @internal\n */\nexport interface TokenResponse {\n /**\n * The AccessToken to be returned from getToken.\n */\n accessToken: AccessToken;\n\n /**\n * The refresh token if the 'offline_access' scope was used.\n */\n refreshToken?: string;\n}\n\n/**\n * The network module used by the Identity credentials.\n *\n * It allows for credentials to abort any pending request independently of the MSAL flow,\n * by calling to the `abortRequests()` method.\n *\n * @internal\n */\nexport class IdentityClient extends ServiceClient implements INetworkModule {\n public authorityHost: string;\n private abortControllers: Map<string, AbortController[] | undefined>;\n\n constructor(options?: TokenCredentialOptions) {\n if (isNode) {\n options = options || getAuthorityHostEnvironment();\n }\n // Only if the authorityHost is not provided, we use the default one.\n options = {\n authorityHost: DefaultAuthorityHost,\n ...options\n };\n super(\n undefined,\n createPipelineFromOptions({\n ...options,\n deserializationOptions: {\n expectedContentTypes: {\n json: [\"application/json\", \"text/json\", \"text/plain\"]\n }\n }\n })\n );\n\n this.baseUri = this.authorityHost = options.authorityHost || DefaultAuthorityHost;\n\n if (!this.baseUri.startsWith(\"https:\")) {\n throw new Error(\"The authorityHost address must use the 'https' protocol.\");\n }\n\n this.abortControllers = new Map();\n }\n\n createWebResource(requestOptions: RequestPrepareOptions): WebResource {\n const webResource = new WebResource();\n webResource.prepare(requestOptions);\n return webResource;\n }\n\n async sendTokenRequest(\n webResource: WebResource,\n expiresOnParser?: (responseBody: any) => number\n ): Promise<TokenResponse | null> {\n logger.info(`IdentityClient: sending token request to [${webResource.url}]`);\n const response = await this.sendRequest(webResource);\n\n expiresOnParser =\n expiresOnParser ||\n ((responseBody: any) => {\n return Date.now() + responseBody.expires_in * 1000;\n });\n\n if (response.status === 200 || response.status === 201) {\n const token = {\n accessToken: {\n token: response.parsedBody.access_token,\n expiresOnTimestamp: expiresOnParser(response.parsedBody)\n },\n refreshToken: response.parsedBody.refresh_token\n };\n\n logger.info(\n `IdentityClient: [${webResource.url}] token acquired, expires on ${token.accessToken.expiresOnTimestamp}`\n );\n return token;\n } else {\n const error = new AuthenticationError(\n response.status,\n response.parsedBody || response.bodyAsText\n );\n logger.warning(\n `IdentityClient: authentication error. HTTP status: ${response.status}, ${error.errorResponse.errorDescription}`\n );\n throw error;\n }\n }\n\n async refreshAccessToken(\n tenantId: string,\n clientId: string,\n scopes: string,\n refreshToken: string | undefined,\n clientSecret: string | undefined,\n expiresOnParser?: (responseBody: any) => number,\n options?: GetTokenOptions\n ): Promise<TokenResponse | null> {\n if (refreshToken === undefined) {\n return null;\n }\n logger.info(\n `IdentityClient: refreshing access token with client ID: ${clientId}, scopes: ${scopes} started`\n );\n\n const { span, updatedOptions } = createSpan(\"IdentityClient-refreshAccessToken\", options);\n\n const refreshParams = {\n grant_type: \"refresh_token\",\n client_id: clientId,\n refresh_token: refreshToken,\n scope: scopes\n };\n\n if (clientSecret !== undefined) {\n (refreshParams as any).client_secret = clientSecret;\n }\n\n try {\n const urlSuffix = getIdentityTokenEndpointSuffix(tenantId);\n const webResource = this.createWebResource({\n url: `${this.authorityHost}/${tenantId}/${urlSuffix}`,\n method: \"POST\",\n disableJsonStringifyOnBody: true,\n deserializationMapper: undefined,\n body: qs.stringify(refreshParams),\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/x-www-form-urlencoded\"\n },\n spanOptions: updatedOptions?.tracingOptions?.spanOptions,\n tracingContext: updatedOptions?.tracingOptions?.tracingContext,\n abortSignal: options && options.abortSignal\n });\n\n const response = await this.sendTokenRequest(webResource, expiresOnParser);\n logger.info(`IdentityClient: refreshed token for client ID: ${clientId}`);\n return response;\n } catch (err) {\n if (\n err.name === AuthenticationErrorName &&\n err.errorResponse.error === \"interaction_required\"\n ) {\n // It's likely that the refresh token has expired, so\n // return null so that the credential implementation will\n // initiate the authentication flow again.\n logger.info(`IdentityClient: interaction required for client ID: ${clientId}`);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n\n return null;\n } else {\n logger.warning(\n `IdentityClient: failed refreshing token for client ID: ${clientId}: ${err}`\n );\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n throw err;\n }\n } finally {\n span.end();\n }\n }\n\n // Here is a custom layer that allows us to abort requests that go through MSAL,\n // since MSAL doesn't allow us to pass options all the way through.\n\n generateAbortSignal(correlationId?: string): AbortSignalLike {\n const controller = new AbortController();\n const key = correlationId || noCorrelationId;\n\n const controllers = this.abortControllers.get(key) || [];\n controllers.push(controller);\n this.abortControllers.set(key, controllers);\n\n return controller.signal;\n }\n\n abortRequests(correlationId: string = noCorrelationId): void {\n const key = correlationId || noCorrelationId;\n const controllers = [\n ...(this.abortControllers.get(key) || []),\n // MSAL passes no correlation ID to the get requests...\n ...(this.abortControllers.get(noCorrelationId) || [])\n ];\n if (!controllers.length) {\n return;\n }\n for (const controller of controllers) {\n controller.abort();\n }\n this.abortControllers.set(key, undefined);\n this.abortControllers.set(noCorrelationId, undefined);\n }\n\n getCorrelationId(options?: NetworkRequestOptions): string | undefined {\n const parameter = options?.body\n ?.split(\"&\")\n .map((part) => part.split(\"=\"))\n .find(([key]) => key === \"client-request-id\");\n return parameter && parameter.length ? parameter[1] : noCorrelationId;\n }\n\n // The MSAL network module methods follow\n\n sendGetRequestAsync<T>(\n url: string,\n options?: NetworkRequestOptions\n ): Promise<NetworkResponse<T>> {\n const webResource = new WebResource(\n url,\n \"GET\",\n options?.body,\n {},\n options?.headers,\n false,\n false,\n // MSAL doesn't send the correlation ID on the get requests.\n this.generateAbortSignal()\n );\n\n return this.sendRequest(webResource).then((response) => {\n return {\n body: response.parsedBody as T,\n headers: response.headers.rawHeaders(),\n status: response.status\n };\n });\n }\n\n sendPostRequestAsync<T>(\n url: string,\n options?: NetworkRequestOptions\n ): Promise<NetworkResponse<T>> {\n const webResource = new WebResource(\n url,\n \"POST\",\n options?.body,\n {},\n options?.headers,\n false,\n false,\n // MSAL doesn't send the correlation ID on the get requests.\n this.generateAbortSignal(this.getCorrelationId(options))\n );\n\n return this.sendRequest(webResource).then((response) => {\n return {\n body: response.parsedBody as T,\n headers: response.headers.rawHeaders(),\n status: response.status\n };\n });\n }\n}\n\n/**\n * Provides options to configure how the Identity library makes authentication\n * requests to Azure Active Directory.\n */\nexport interface TokenCredentialOptions extends PipelineOptions {\n /**\n * The authority host to use for authentication requests.\n * The default is \"https://login.microsoftonline.com\".\n */\n authorityHost?: string;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"identityClient.js","sourceRoot":"","sources":["../../../src/client/identityClient.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { INetworkModule, NetworkRequestOptions, NetworkResponse } from \"@azure/msal-common\";\nimport { CommonClientOptions, ServiceClient } from \"@azure/core-client\";\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { SpanStatusCode } from \"@azure/core-tracing\";\nimport { isNode } from \"@azure/core-util\";\nimport {\n createHttpHeaders,\n createPipelineRequest,\n PipelineRequest\n} from \"@azure/core-rest-pipeline\";\nimport { AbortController, AbortSignalLike } from \"@azure/abort-controller\";\nimport { AuthenticationError, AuthenticationErrorName } from \"../errors\";\nimport { getIdentityTokenEndpointSuffix } from \"../util/identityTokenEndpoint\";\nimport { DefaultAuthorityHost } from \"../constants\";\nimport { createSpan } from \"../util/tracing\";\nimport { logger } from \"../util/logging\";\n\nconst noCorrelationId = \"noCorrelationId\";\n\n/**\n * An internal type used to communicate details of a token request's\n * response that should not be sent back as part of the access token.\n */\nexport interface TokenResponse {\n /**\n * The AccessToken to be returned from getToken.\n */\n accessToken: AccessToken;\n\n /**\n * The refresh token if the 'offline_access' scope was used.\n */\n refreshToken?: string;\n}\n\n/**\n * @internal\n */\nexport function getIdentityClientAuthorityHost(options?: TokenCredentialOptions): string {\n // The authorityHost can come from options or from the AZURE_AUTHORITY_HOST environment variable.\n let authorityHost = options?.authorityHost;\n\n // The AZURE_AUTHORITY_HOST environment variable can only be provided in Node.js.\n if (isNode) {\n authorityHost = authorityHost ?? process.env.AZURE_AUTHORITY_HOST;\n }\n\n // If the authorityHost is not provided, we use the default one from the public cloud: https://login.microsoftonline.com\n return authorityHost ?? DefaultAuthorityHost;\n}\n\n/**\n * The network module used by the Identity credentials.\n *\n * It allows for credentials to abort any pending request independently of the MSAL flow,\n * by calling to the `abortRequests()` method.\n *\n */\nexport class IdentityClient extends ServiceClient implements INetworkModule {\n public authorityHost: string;\n private abortControllers: Map<string, AbortController[] | undefined>;\n\n constructor(options?: TokenCredentialOptions) {\n const packageDetails = `azsdk-js-identity/2.0.0`;\n const userAgentPrefix = options?.userAgentOptions?.userAgentPrefix\n ? `${options.userAgentOptions.userAgentPrefix} ${packageDetails}`\n : `${packageDetails}`;\n\n const baseUri = getIdentityClientAuthorityHost(options);\n if (!baseUri.startsWith(\"https:\")) {\n throw new Error(\"The authorityHost address must use the 'https' protocol.\");\n }\n\n super({\n requestContentType: \"application/json; charset=utf-8\",\n ...options,\n userAgentOptions: {\n userAgentPrefix\n },\n baseUri\n });\n\n this.authorityHost = baseUri;\n this.abortControllers = new Map();\n }\n\n async sendTokenRequest(\n request: PipelineRequest,\n expiresOnParser?: (responseBody: any) => number\n ): Promise<TokenResponse | null> {\n logger.info(`IdentityClient: sending token request to [${request.url}]`);\n const response = await this.sendRequest(request);\n\n expiresOnParser =\n expiresOnParser ||\n ((responseBody: any) => {\n return Date.now() + responseBody.expires_in * 1000;\n });\n\n if (response.bodyAsText && (response.status === 200 || response.status === 201)) {\n const parsedBody: {\n token?: string;\n access_token?: string;\n refresh_token?: string;\n } = JSON.parse(response.bodyAsText);\n\n if (!parsedBody.access_token) {\n return null;\n }\n\n const token = {\n accessToken: {\n token: parsedBody.access_token,\n expiresOnTimestamp: expiresOnParser(parsedBody)\n },\n refreshToken: parsedBody.refresh_token\n };\n\n logger.info(\n `IdentityClient: [${request.url}] token acquired, expires on ${token.accessToken.expiresOnTimestamp}`\n );\n return token;\n } else {\n const error = new AuthenticationError(response.status, response.bodyAsText);\n logger.warning(\n `IdentityClient: authentication error. HTTP status: ${response.status}, ${error.errorResponse.errorDescription}`\n );\n throw error;\n }\n }\n\n async refreshAccessToken(\n tenantId: string,\n clientId: string,\n scopes: string,\n refreshToken: string | undefined,\n clientSecret: string | undefined,\n expiresOnParser?: (responseBody: any) => number,\n options?: GetTokenOptions\n ): Promise<TokenResponse | null> {\n if (refreshToken === undefined) {\n return null;\n }\n logger.info(\n `IdentityClient: refreshing access token with client ID: ${clientId}, scopes: ${scopes} started`\n );\n\n const { span, updatedOptions } = createSpan(\"IdentityClient-refreshAccessToken\", options);\n\n const refreshParams = {\n grant_type: \"refresh_token\",\n client_id: clientId,\n refresh_token: refreshToken,\n scope: scopes\n };\n\n if (clientSecret !== undefined) {\n (refreshParams as any).client_secret = clientSecret;\n }\n\n const query = new URLSearchParams(refreshParams);\n\n try {\n const urlSuffix = getIdentityTokenEndpointSuffix(tenantId);\n const request = createPipelineRequest({\n url: `${this.authorityHost}/${tenantId}/${urlSuffix}`,\n method: \"POST\",\n body: query.toString(),\n abortSignal: options && options.abortSignal,\n headers: createHttpHeaders({\n Accept: \"application/json\",\n \"Content-Type\": \"application/x-www-form-urlencoded\"\n }),\n tracingOptions: updatedOptions?.tracingOptions\n });\n\n const response = await this.sendTokenRequest(request, expiresOnParser);\n logger.info(`IdentityClient: refreshed token for client ID: ${clientId}`);\n return response;\n } catch (err) {\n if (\n err.name === AuthenticationErrorName &&\n err.errorResponse.error === \"interaction_required\"\n ) {\n // It's likely that the refresh token has expired, so\n // return null so that the credential implementation will\n // initiate the authentication flow again.\n logger.info(`IdentityClient: interaction required for client ID: ${clientId}`);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n\n return null;\n } else {\n logger.warning(\n `IdentityClient: failed refreshing token for client ID: ${clientId}: ${err}`\n );\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n throw err;\n }\n } finally {\n span.end();\n }\n }\n\n // Here is a custom layer that allows us to abort requests that go through MSAL,\n // since MSAL doesn't allow us to pass options all the way through.\n\n generateAbortSignal(correlationId: string): AbortSignalLike {\n const controller = new AbortController();\n const controllers = this.abortControllers.get(correlationId) || [];\n controllers.push(controller);\n this.abortControllers.set(correlationId, controllers);\n const existingOnAbort = controller.signal.onabort;\n controller.signal.onabort = (...params) => {\n this.abortControllers.set(correlationId, undefined);\n if (existingOnAbort) {\n existingOnAbort(...params);\n }\n };\n return controller.signal;\n }\n\n abortRequests(correlationId?: string): void {\n const key = correlationId || noCorrelationId;\n const controllers = [\n ...(this.abortControllers.get(key) || []),\n // MSAL passes no correlation ID to the get requests...\n ...(this.abortControllers.get(noCorrelationId) || [])\n ];\n if (!controllers.length) {\n return;\n }\n for (const controller of controllers) {\n controller.abort();\n }\n this.abortControllers.set(key, undefined);\n }\n\n getCorrelationId(options?: NetworkRequestOptions): string {\n const parameter = options?.body\n ?.split(\"&\")\n .map((part) => part.split(\"=\"))\n .find(([key]) => key === \"client-request-id\");\n return parameter && parameter.length ? parameter[1] || noCorrelationId : noCorrelationId;\n }\n\n // The MSAL network module methods follow\n\n async sendGetRequestAsync<T>(\n url: string,\n options?: NetworkRequestOptions\n ): Promise<NetworkResponse<T>> {\n const request = createPipelineRequest({\n url,\n method: \"GET\",\n body: options?.body,\n headers: createHttpHeaders(options?.headers),\n abortSignal: this.generateAbortSignal(noCorrelationId)\n });\n\n const response = await this.sendRequest(request);\n return {\n body: response.bodyAsText ? JSON.parse(response.bodyAsText) : undefined,\n headers: response.headers.toJSON(),\n status: response.status\n };\n }\n\n async sendPostRequestAsync<T>(\n url: string,\n options?: NetworkRequestOptions\n ): Promise<NetworkResponse<T>> {\n const request = createPipelineRequest({\n url,\n method: \"POST\",\n body: options?.body,\n headers: createHttpHeaders(options?.headers),\n // MSAL doesn't send the correlation ID on the get requests.\n abortSignal: this.generateAbortSignal(this.getCorrelationId(options))\n });\n\n const response = await this.sendRequest(request);\n return {\n body: response.bodyAsText ? JSON.parse(response.bodyAsText) : undefined,\n headers: response.headers.toJSON(),\n status: response.status\n };\n }\n}\n\n/**\n * Provides options to configure how the Identity library makes authentication\n * requests to Azure Active Directory.\n */\nexport interface TokenCredentialOptions extends CommonClientOptions {\n /**\n * The authority host to use for authentication requests.\n * Possible values are available through {@link AzureAuthorityHosts}.\n * The default is \"https://login.microsoftonline.com\".\n */\n authorityHost?: string;\n}\n"]}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
// TODO: temporary - this is the Azure CLI clientID - we'll replace it when
|
|
8
8
|
// Developer Sign On application is available
|
|
9
|
-
// https://github.com/Azure/azure-sdk-for-net/blob/
|
|
9
|
+
// https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/src/Constants.cs#L9
|
|
10
10
|
export const DeveloperSignOnClientId = "04b07795-8ddb-461a-bbee-02f9e1bf7b46";
|
|
11
11
|
/**
|
|
12
12
|
* The default tenant for authentication
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC;;;GAGG;AACH,2EAA2E;AAC3E,6CAA6C;AAC7C,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC;;;GAGG;AACH,2EAA2E;AAC3E,6CAA6C;AAC7C,uGAAuG;AACvG,MAAM,CAAC,MAAM,uBAAuB,GAAG,sCAAsC,CAAC;AAE9E;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAC;AAExC;;GAEG;AACH,MAAM,CAAN,IAAY,mBAiBX;AAjBD,WAAY,mBAAmB;IAC7B;;OAEG;IACH,oEAA6C,CAAA;IAC7C;;OAEG;IACH,wEAAiD,CAAA;IACjD;;OAEG;IACH,2EAAoD,CAAA;IACpD;;OAEG;IACH,6EAAsD,CAAA;AACxD,CAAC,EAjBW,mBAAmB,KAAnB,mBAAmB,QAiB9B;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,mBAAmB,CAAC,gBAAgB,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/**\n * The default client ID for authentication\n * @internal\n */\n// TODO: temporary - this is the Azure CLI clientID - we'll replace it when\n// Developer Sign On application is available\n// https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/src/Constants.cs#L9\nexport const DeveloperSignOnClientId = \"04b07795-8ddb-461a-bbee-02f9e1bf7b46\";\n\n/**\n * The default tenant for authentication\n * @internal\n */\nexport const DefaultTenantId = \"common\";\n\n/**\n * A list of known Azure authority hosts\n */\nexport enum AzureAuthorityHosts {\n /**\n * China-based Azure Authority Host\n */\n AzureChina = \"https://login.chinacloudapi.cn\",\n /**\n * Germany-based Azure Authority Host\n */\n AzureGermany = \"https://login.microsoftonline.de\",\n /**\n * US Government Azure Authority Host\n */\n AzureGovernment = \"https://login.microsoftonline.us\",\n /**\n * Public Cloud Azure Authority Host\n */\n AzurePublicCloud = \"https://login.microsoftonline.com\"\n}\n\n/**\n * The default authority host.\n */\nexport const DefaultAuthorityHost = AzureAuthorityHosts.AzurePublicCloud;\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT license.
|
|
3
3
|
import { credentialLogger, formatError } from "../util/logging";
|
|
4
|
-
const BrowserNotSupportedError = new Error("AuthorizationCodeCredential is not supported in the browser.
|
|
4
|
+
const BrowserNotSupportedError = new Error("AuthorizationCodeCredential is not supported in the browser. InteractiveBrowserCredential is more appropriate for this use case.");
|
|
5
5
|
const logger = credentialLogger("AuthorizationCodeCredential");
|
|
6
6
|
export class AuthorizationCodeCredential {
|
|
7
7
|
constructor() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorizationCodeCredential.browser.js","sourceRoot":"","sources":["../../../src/credentials/authorizationCodeCredential.browser.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;
|
|
1
|
+
{"version":3,"file":"authorizationCodeCredential.browser.js","sourceRoot":"","sources":["../../../src/credentials/authorizationCodeCredential.browser.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAKlC,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEhE,MAAM,wBAAwB,GAAG,IAAI,KAAK,CACxC,kIAAkI,CACnI,CAAC;AACF,MAAM,MAAM,GAAG,gBAAgB,CAAC,6BAA6B,CAAC,CAAC;AAE/D,MAAM,OAAO,2BAA2B;IAmBtC;QACE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC;QACvD,MAAM,wBAAwB,CAAC;IACjC,CAAC;IAEM,QAAQ;QACb,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC;QAChE,MAAM,wBAAwB,CAAC;IACjC,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { TokenCredential, AccessToken } from \"@azure/core-auth\";\n\nimport { TokenCredentialOptions } from \"../client/identityClient\";\nimport { credentialLogger, formatError } from \"../util/logging\";\n\nconst BrowserNotSupportedError = new Error(\n \"AuthorizationCodeCredential is not supported in the browser. InteractiveBrowserCredential is more appropriate for this use case.\"\n);\nconst logger = credentialLogger(\"AuthorizationCodeCredential\");\n\nexport class AuthorizationCodeCredential implements TokenCredential {\n /**\n * Only available in Node.js\n */\n constructor(\n tenantId: string | \"common\",\n clientId: string,\n clientSecret: string,\n authorizationCode: string,\n redirectUri: string,\n options?: TokenCredentialOptions\n );\n constructor(\n tenantId: string | \"common\",\n clientId: string,\n authorizationCode: string,\n redirectUri: string,\n options?: TokenCredentialOptions\n );\n constructor() {\n logger.info(formatError(\"\", BrowserNotSupportedError));\n throw BrowserNotSupportedError;\n }\n\n public getToken(): Promise<AccessToken | null> {\n logger.getToken.info(formatError(\"\", BrowserNotSupportedError));\n throw BrowserNotSupportedError;\n }\n}\n"]}
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT license.
|
|
3
|
-
import {
|
|
4
|
-
import qs from "qs";
|
|
5
|
-
import { createSpan } from "../util/tracing";
|
|
6
|
-
import { CredentialUnavailableError } from "../client/errors";
|
|
7
|
-
import { IdentityClient } from "../client/identityClient";
|
|
8
|
-
import { SpanStatusCode } from "@azure/core-tracing";
|
|
9
|
-
import { credentialLogger, formatSuccess, formatError } from "../util/logging";
|
|
10
|
-
import { getIdentityTokenEndpointSuffix } from "../util/identityTokenEndpoint";
|
|
3
|
+
import { credentialLogger } from "../util/logging";
|
|
11
4
|
import { checkTenantId } from "../util/checkTenantId";
|
|
5
|
+
import { MsalAuthorizationCode } from "../msal/nodeFlows/msalAuthorizationCode";
|
|
6
|
+
import { trace } from "../util/tracing";
|
|
12
7
|
const logger = credentialLogger("AuthorizationCodeCredential");
|
|
13
8
|
/**
|
|
14
9
|
* Enables authentication to Azure Active Directory using an authorization code
|
|
@@ -23,94 +18,36 @@ export class AuthorizationCodeCredential {
|
|
|
23
18
|
* @internal
|
|
24
19
|
*/
|
|
25
20
|
constructor(tenantId, clientId, clientSecretOrAuthorizationCode, authorizationCodeOrRedirectUri, redirectUriOrOptions, options) {
|
|
26
|
-
this.lastTokenResponse = null;
|
|
27
21
|
checkTenantId(logger, tenantId);
|
|
28
|
-
|
|
29
|
-
this.tenantId = tenantId;
|
|
22
|
+
let clientSecret = clientSecretOrAuthorizationCode;
|
|
30
23
|
if (typeof redirectUriOrOptions === "string") {
|
|
31
24
|
// the clientId+clientSecret constructor
|
|
32
|
-
this.clientSecret = clientSecretOrAuthorizationCode;
|
|
33
25
|
this.authorizationCode = authorizationCodeOrRedirectUri;
|
|
34
26
|
this.redirectUri = redirectUriOrOptions;
|
|
35
27
|
// options okay
|
|
36
28
|
}
|
|
37
29
|
else {
|
|
38
30
|
// clientId only
|
|
39
|
-
this.clientSecret = undefined;
|
|
40
31
|
this.authorizationCode = clientSecretOrAuthorizationCode;
|
|
41
32
|
this.redirectUri = authorizationCodeOrRedirectUri;
|
|
33
|
+
clientSecret = undefined;
|
|
42
34
|
options = redirectUriOrOptions;
|
|
43
35
|
}
|
|
44
|
-
this.
|
|
36
|
+
this.msalFlow = new MsalAuthorizationCode(Object.assign(Object.assign({}, options), { clientSecret,
|
|
37
|
+
clientId, tokenCredentialOptions: options || {}, logger, redirectUri: this.redirectUri, authorizationCode: this.authorizationCode }));
|
|
45
38
|
}
|
|
46
39
|
/**
|
|
47
|
-
* Authenticates with Azure Active Directory and returns an access token if
|
|
48
|
-
*
|
|
49
|
-
* return null. If an error occurs during authentication, an {@link AuthenticationError}
|
|
50
|
-
* containing failure details will be thrown.
|
|
40
|
+
* Authenticates with Azure Active Directory and returns an access token if successful.
|
|
41
|
+
* If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.
|
|
51
42
|
*
|
|
52
43
|
* @param scopes - The list of scopes for which the token will have access.
|
|
53
44
|
* @param options - The options used to configure any requests this
|
|
54
45
|
* TokenCredential implementation might make.
|
|
55
46
|
*/
|
|
56
|
-
getToken(scopes, options) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
try {
|
|
61
|
-
let tokenResponse = null;
|
|
62
|
-
let scopeString = typeof scopes === "string" ? scopes : scopes.join(" ");
|
|
63
|
-
if (scopeString.indexOf("offline_access") < 0) {
|
|
64
|
-
scopeString += " offline_access";
|
|
65
|
-
}
|
|
66
|
-
// Try to use the refresh token first
|
|
67
|
-
if (this.lastTokenResponse && this.lastTokenResponse.refreshToken) {
|
|
68
|
-
tokenResponse = yield this.identityClient.refreshAccessToken(this.tenantId, this.clientId, scopeString, this.lastTokenResponse.refreshToken, this.clientSecret, undefined, updatedOptions);
|
|
69
|
-
}
|
|
70
|
-
if (tokenResponse === null) {
|
|
71
|
-
const urlSuffix = getIdentityTokenEndpointSuffix(this.tenantId);
|
|
72
|
-
const webResource = this.identityClient.createWebResource({
|
|
73
|
-
url: `${this.identityClient.authorityHost}/${this.tenantId}/${urlSuffix}`,
|
|
74
|
-
method: "POST",
|
|
75
|
-
disableJsonStringifyOnBody: true,
|
|
76
|
-
deserializationMapper: undefined,
|
|
77
|
-
body: qs.stringify({
|
|
78
|
-
client_id: this.clientId,
|
|
79
|
-
grant_type: "authorization_code",
|
|
80
|
-
scope: scopeString,
|
|
81
|
-
code: this.authorizationCode,
|
|
82
|
-
redirect_uri: this.redirectUri,
|
|
83
|
-
client_secret: this.clientSecret
|
|
84
|
-
}),
|
|
85
|
-
headers: {
|
|
86
|
-
Accept: "application/json",
|
|
87
|
-
"Content-Type": "application/x-www-form-urlencoded"
|
|
88
|
-
},
|
|
89
|
-
abortSignal: options && options.abortSignal,
|
|
90
|
-
spanOptions: (_a = updatedOptions === null || updatedOptions === void 0 ? void 0 : updatedOptions.tracingOptions) === null || _a === void 0 ? void 0 : _a.spanOptions,
|
|
91
|
-
tracingContext: (_b = updatedOptions === null || updatedOptions === void 0 ? void 0 : updatedOptions.tracingOptions) === null || _b === void 0 ? void 0 : _b.tracingContext
|
|
92
|
-
});
|
|
93
|
-
tokenResponse = yield this.identityClient.sendTokenRequest(webResource);
|
|
94
|
-
}
|
|
95
|
-
this.lastTokenResponse = tokenResponse;
|
|
96
|
-
logger.getToken.info(formatSuccess(scopes));
|
|
97
|
-
const token = tokenResponse && tokenResponse.accessToken;
|
|
98
|
-
if (!token) {
|
|
99
|
-
throw new CredentialUnavailableError("Failed to retrieve a valid token");
|
|
100
|
-
}
|
|
101
|
-
return token;
|
|
102
|
-
}
|
|
103
|
-
catch (err) {
|
|
104
|
-
span.setStatus({
|
|
105
|
-
code: SpanStatusCode.ERROR,
|
|
106
|
-
message: err.message
|
|
107
|
-
});
|
|
108
|
-
logger.getToken.info(formatError(scopes, err));
|
|
109
|
-
throw err;
|
|
110
|
-
}
|
|
111
|
-
finally {
|
|
112
|
-
span.end();
|
|
113
|
-
}
|
|
47
|
+
async getToken(scopes, options = {}) {
|
|
48
|
+
return trace(`${this.constructor.name}.getToken`, options, async (newOptions) => {
|
|
49
|
+
const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];
|
|
50
|
+
return this.msalFlow.getToken(arrayScopes, Object.assign(Object.assign({}, newOptions), { disableAutomaticAuthentication: this.disableAutomaticAuthentication }));
|
|
114
51
|
});
|
|
115
52
|
}
|
|
116
53
|
}
|