@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,10 +1,9 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT license.
|
|
3
|
-
import { __awaiter } from "tslib";
|
|
4
3
|
import * as msalBrowser from "@azure/msal-browser";
|
|
5
|
-
import {
|
|
4
|
+
import { AuthenticationRequiredError } from "../../errors";
|
|
6
5
|
import { defaultLoggerCallback, msalToPublic, publicToMsal } from "../utils";
|
|
7
|
-
import {
|
|
6
|
+
import { MsalBrowser } from "./browserCommon";
|
|
8
7
|
// We keep a copy of the redirect hash.
|
|
9
8
|
const redirectHash = self.location.hash;
|
|
10
9
|
/**
|
|
@@ -21,13 +20,14 @@ export class MSALAuthCode extends MsalBrowser {
|
|
|
21
20
|
*/
|
|
22
21
|
constructor(options) {
|
|
23
22
|
super(options);
|
|
23
|
+
this.loginHint = options.loginHint;
|
|
24
24
|
this.msalConfig.cache = {
|
|
25
25
|
cacheLocation: "sessionStorage",
|
|
26
26
|
storeAuthStateInCookie: true // Set to true to improve the experience on IE11 and Edge.
|
|
27
27
|
};
|
|
28
28
|
this.msalConfig.system = {
|
|
29
29
|
loggerOptions: {
|
|
30
|
-
loggerCallback: defaultLoggerCallback(this.logger)
|
|
30
|
+
loggerCallback: defaultLoggerCallback(this.logger, "Browser")
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
33
|
// Preparing the MSAL application.
|
|
@@ -41,144 +41,142 @@ export class MSALAuthCode extends MsalBrowser {
|
|
|
41
41
|
* If no result was received, tries to load the account from the cache.
|
|
42
42
|
* @param result - Result object received from MSAL.
|
|
43
43
|
*/
|
|
44
|
-
handleBrowserResult(result) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
this.logger.info(`More than one account was found authenticated for this Client ID and Tenant ID.
|
|
44
|
+
async handleBrowserResult(result) {
|
|
45
|
+
try {
|
|
46
|
+
if (result && result.account) {
|
|
47
|
+
this.logger.info(`MSAL Browser V2 authentication successful.`);
|
|
48
|
+
this.app.setActiveAccount(result.account);
|
|
49
|
+
return msalToPublic(this.clientId, result.account);
|
|
50
|
+
}
|
|
51
|
+
// If by this point we happen to have an active account, we should stop trying to parse this.
|
|
52
|
+
const activeAccount = await this.app.getActiveAccount();
|
|
53
|
+
if (activeAccount) {
|
|
54
|
+
return msalToPublic(this.clientId, activeAccount);
|
|
55
|
+
}
|
|
56
|
+
// If we don't have an active account, we try to activate it from all the already loaded accounts.
|
|
57
|
+
const accounts = this.app.getAllAccounts();
|
|
58
|
+
if (accounts.length > 1) {
|
|
59
|
+
// If there's more than one account in memory, we force the user to authenticate again.
|
|
60
|
+
// At this point we can't identify which account should this credential work with,
|
|
61
|
+
// since at this point the user won't have provided enough information.
|
|
62
|
+
// We log a message in case that helps.
|
|
63
|
+
this.logger.info(`More than one account was found authenticated for this Client ID and Tenant ID.
|
|
65
64
|
However, no "authenticationRecord" has been provided for this credential,
|
|
66
65
|
therefore we're unable to pick between these accounts.
|
|
67
66
|
A new login attempt will be requested, to ensure the correct account is picked.
|
|
68
67
|
To work with multiple accounts for the same Client ID and Tenant ID, please provide an "authenticationRecord" when initializing "InteractiveBrowserCredential".`);
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
// If there's only one account for this MSAL object, we can safely activate it.
|
|
78
|
-
if (accounts.length === 1) {
|
|
79
|
-
const account = accounts[0];
|
|
80
|
-
this.app.setActiveAccount(account);
|
|
81
|
-
return msalToPublic(this.clientId, account);
|
|
82
|
-
}
|
|
83
|
-
this.logger.info(`No accounts were found through MSAL.`);
|
|
68
|
+
// To safely trigger a new login, we're also ensuring the local cache is cleared up for this MSAL object.
|
|
69
|
+
// However, we want to avoid kicking the user out of their authentication on the Azure side.
|
|
70
|
+
// We do this by calling to logout while specifying a `onRedirectNavigate` that returns false.
|
|
71
|
+
await this.app.logout({
|
|
72
|
+
onRedirectNavigate: () => false
|
|
73
|
+
});
|
|
74
|
+
return;
|
|
84
75
|
}
|
|
85
|
-
|
|
86
|
-
|
|
76
|
+
// If there's only one account for this MSAL object, we can safely activate it.
|
|
77
|
+
if (accounts.length === 1) {
|
|
78
|
+
const account = accounts[0];
|
|
79
|
+
this.app.setActiveAccount(account);
|
|
80
|
+
return msalToPublic(this.clientId, account);
|
|
87
81
|
}
|
|
88
|
-
|
|
89
|
-
}
|
|
82
|
+
this.logger.info(`No accounts were found through MSAL.`);
|
|
83
|
+
}
|
|
84
|
+
catch (e) {
|
|
85
|
+
this.logger.info(`Failed to acquire token through MSAL. ${e.message}`);
|
|
86
|
+
}
|
|
87
|
+
return;
|
|
90
88
|
}
|
|
91
89
|
/**
|
|
92
90
|
* Uses MSAL to handle the redirect.
|
|
93
91
|
*/
|
|
94
|
-
handleRedirect() {
|
|
95
|
-
return
|
|
96
|
-
return this.handleBrowserResult((yield this.app.handleRedirectPromise(redirectHash)) || undefined);
|
|
97
|
-
});
|
|
92
|
+
async handleRedirect() {
|
|
93
|
+
return this.handleBrowserResult((await this.app.handleRedirectPromise(redirectHash)) || undefined);
|
|
98
94
|
}
|
|
99
95
|
/**
|
|
100
96
|
* Uses MSAL to trigger a redirect or a popup login.
|
|
101
97
|
*/
|
|
102
|
-
login(scopes = []) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
case "popup":
|
|
114
|
-
return this.handleBrowserResult(yield this.app.loginPopup(loginRequest));
|
|
98
|
+
async login(scopes = []) {
|
|
99
|
+
const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];
|
|
100
|
+
const loginRequest = {
|
|
101
|
+
scopes: arrayScopes,
|
|
102
|
+
loginHint: this.loginHint
|
|
103
|
+
};
|
|
104
|
+
switch (this.loginStyle) {
|
|
105
|
+
case "redirect": {
|
|
106
|
+
await this.app.loginRedirect(loginRequest);
|
|
107
|
+
return;
|
|
115
108
|
}
|
|
116
|
-
|
|
109
|
+
case "popup":
|
|
110
|
+
return this.handleBrowserResult(await this.app.loginPopup(loginRequest));
|
|
111
|
+
}
|
|
117
112
|
}
|
|
118
113
|
/**
|
|
119
114
|
* Uses MSAL to retrieve the active account.
|
|
120
115
|
*/
|
|
121
|
-
getActiveAccount() {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
return msalToPublic(this.clientId, account);
|
|
128
|
-
});
|
|
116
|
+
async getActiveAccount() {
|
|
117
|
+
const account = this.app.getActiveAccount();
|
|
118
|
+
if (!account) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
return msalToPublic(this.clientId, account);
|
|
129
122
|
}
|
|
130
123
|
/**
|
|
131
124
|
* Attempts to retrieve a token from cache.
|
|
132
125
|
*/
|
|
133
|
-
getTokenSilent(scopes, options) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
126
|
+
async getTokenSilent(scopes, options) {
|
|
127
|
+
const account = await this.getActiveAccount();
|
|
128
|
+
if (!account) {
|
|
129
|
+
throw new AuthenticationRequiredError({
|
|
130
|
+
scopes,
|
|
131
|
+
getTokenOptions: options,
|
|
132
|
+
message: "Silent authentication failed. We couldn't retrieve an active account from the cache."
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
const parameters = {
|
|
136
|
+
authority: (options === null || options === void 0 ? void 0 : options.authority) || this.msalConfig.auth.authority,
|
|
137
|
+
correlationId: options === null || options === void 0 ? void 0 : options.correlationId,
|
|
138
|
+
account: publicToMsal(account),
|
|
139
|
+
forceRefresh: false,
|
|
140
|
+
scopes
|
|
141
|
+
};
|
|
142
|
+
try {
|
|
143
|
+
this.logger.info("Attempting to acquire token silently");
|
|
144
|
+
const response = await this.app.acquireTokenSilent(parameters);
|
|
145
|
+
return this.handleResult(scopes, this.clientId, response);
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
throw this.handleError(scopes, err, options);
|
|
149
|
+
}
|
|
155
150
|
}
|
|
156
151
|
/**
|
|
157
152
|
* Attempts to retrieve the token in the browser.
|
|
158
153
|
*/
|
|
159
|
-
doGetToken(scopes, options) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
154
|
+
async doGetToken(scopes, options) {
|
|
155
|
+
const account = await this.getActiveAccount();
|
|
156
|
+
if (!account) {
|
|
157
|
+
throw new AuthenticationRequiredError({
|
|
158
|
+
scopes,
|
|
159
|
+
getTokenOptions: options,
|
|
160
|
+
message: "Silent authentication failed. We couldn't retrieve an active account from the cache."
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
const parameters = {
|
|
164
|
+
authority: (options === null || options === void 0 ? void 0 : options.authority) || this.msalConfig.auth.authority,
|
|
165
|
+
correlationId: options === null || options === void 0 ? void 0 : options.correlationId,
|
|
166
|
+
account: publicToMsal(account),
|
|
167
|
+
loginHint: this.loginHint,
|
|
168
|
+
scopes
|
|
169
|
+
};
|
|
170
|
+
switch (this.loginStyle) {
|
|
171
|
+
case "redirect":
|
|
172
|
+
// This will go out of the page.
|
|
173
|
+
// Once the InteractiveBrowserCredential is initialized again,
|
|
174
|
+
// we'll load the MSAL account in the constructor.
|
|
175
|
+
await this.app.acquireTokenRedirect(parameters);
|
|
176
|
+
return { token: "", expiresOnTimestamp: 0 };
|
|
177
|
+
case "popup":
|
|
178
|
+
return this.handleResult(scopes, this.clientId, await this.app.acquireTokenPopup(parameters));
|
|
179
|
+
}
|
|
182
180
|
}
|
|
183
181
|
}
|
|
184
182
|
//# sourceMappingURL=msalAuthCode.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"msalAuthCode.js","sourceRoot":"","sources":["../../../../src/msal/browserFlows/msalAuthCode.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport * as msalBrowser from \"@azure/msal-browser\";\nimport { MsalBrowserFlowOptions, MsalBrowser } from \"./browserCommon\";\nimport { AccessToken } from \"@azure/core-http\";\nimport { defaultLoggerCallback, msalToPublic, publicToMsal } from \"../utils\";\nimport { AuthenticationRecord } from \"../types\";\nimport { AuthenticationRequiredError } from \"../errors\";\nimport { CredentialFlowGetTokenOptions } from \"../credentials\";\n\n// We keep a copy of the redirect hash.\nconst redirectHash = self.location.hash;\n\n/**\n * Uses MSAL Browser 2.X for browser authentication,\n * which uses the [Auth Code Flow](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow).\n * @internal\n */\nexport class MSALAuthCode extends MsalBrowser {\n protected app: msalBrowser.PublicClientApplication;\n\n /**\n * Sets up an MSAL object based on the given parameters.\n * MSAL with Auth Code allows sending a previously obtained `authenticationRecord` through the optional parameters,\n * which is set to be the active account.\n * @param options - Parameters necessary and otherwise used to create the MSAL object.\n */\n constructor(options: MsalBrowserFlowOptions) {\n super(options);\n\n this.msalConfig.cache = {\n cacheLocation: \"sessionStorage\",\n storeAuthStateInCookie: true // Set to true to improve the experience on IE11 and Edge.\n };\n this.msalConfig.system = {\n loggerOptions: {\n loggerCallback: defaultLoggerCallback(this.logger)\n }\n };\n\n // Preparing the MSAL application.\n this.app = new msalBrowser.PublicClientApplication(\n this.msalConfig as msalBrowser.Configuration\n );\n if (this.account) {\n this.app.setActiveAccount(publicToMsal(this.account));\n }\n }\n\n /**\n * Loads the account based on the result of the authentication.\n * If no result was received, tries to load the account from the cache.\n * @param result - Result object received from MSAL.\n */\n private async handleBrowserResult(\n result?: msalBrowser.AuthenticationResult\n ): Promise<AuthenticationRecord | undefined> {\n try {\n if (result && result.account) {\n this.logger.info(`MSAL Browser V2 authentication successful.`);\n this.app.setActiveAccount(result.account);\n return msalToPublic(this.clientId, result.account);\n }\n\n // If by this point we happen to have an active account, we should stop trying to parse this.\n const activeAccount = await this.app!.getActiveAccount();\n if (activeAccount) {\n return msalToPublic(this.clientId, activeAccount);\n }\n\n // If we don't have an active account, we try to activate it from all the already loaded accounts.\n const accounts = this.app.getAllAccounts();\n if (accounts.length > 1) {\n // If there's more than one account in memory, we force the user to authenticate again.\n // At this point we can't identify which account should this credential work with,\n // since at this point the user won't have provided enough information.\n // We log a message in case that helps.\n this.logger.info(\n `More than one account was found authenticated for this Client ID and Tenant ID.\nHowever, no \"authenticationRecord\" has been provided for this credential,\ntherefore we're unable to pick between these accounts.\nA new login attempt will be requested, to ensure the correct account is picked.\nTo work with multiple accounts for the same Client ID and Tenant ID, please provide an \"authenticationRecord\" when initializing \"InteractiveBrowserCredential\".`\n );\n // To safely trigger a new login, we're also ensuring the local cache is cleared up for this MSAL object.\n // However, we want to avoid kicking the user out of their authentication on the Azure side.\n // We do this by calling to logout while specifying a `onRedirectNavigate` that returns false.\n await this.app.logout({\n onRedirectNavigate: () => false\n });\n return;\n }\n\n // If there's only one account for this MSAL object, we can safely activate it.\n if (accounts.length === 1) {\n const account = accounts[0];\n this.app.setActiveAccount(account);\n return msalToPublic(this.clientId, account);\n }\n\n this.logger.info(`No accounts were found through MSAL.`);\n } catch (e) {\n this.logger.info(`Failed to acquire token through MSAL. ${e.message}`);\n }\n return;\n }\n\n /**\n * Uses MSAL to handle the redirect.\n */\n public async handleRedirect(): Promise<AuthenticationRecord | undefined> {\n return this.handleBrowserResult(\n (await this.app.handleRedirectPromise(redirectHash)) || undefined\n );\n }\n\n /**\n * Uses MSAL to trigger a redirect or a popup login.\n */\n public async login(scopes: string | string[] = []): Promise<AuthenticationRecord | undefined> {\n const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];\n const loginRequest = {\n scopes: arrayScopes\n };\n switch (this.loginStyle) {\n case \"redirect\": {\n await this.app.loginRedirect(loginRequest);\n return;\n }\n case \"popup\":\n return this.handleBrowserResult(await this.app.loginPopup(loginRequest));\n }\n }\n\n /**\n * Uses MSAL to retrieve the active account.\n */\n public async getActiveAccount(): Promise<AuthenticationRecord | undefined> {\n const account = this.app.getActiveAccount();\n if (!account) {\n return;\n }\n return msalToPublic(this.clientId, account);\n }\n\n /**\n * Attempts to retrieve a token from cache.\n */\n public async getTokenSilent(\n scopes: string[],\n options?: CredentialFlowGetTokenOptions\n ): Promise<AccessToken> {\n const account = await this.getActiveAccount();\n if (!account) {\n throw new AuthenticationRequiredError(scopes, options);\n }\n\n const parameters: msalBrowser.SilentRequest = {\n authority: this.msalConfig.auth.authority!,\n correlationId: options?.correlationId,\n account: publicToMsal(account),\n forceRefresh: false,\n scopes\n };\n\n try {\n this.logger.info(\"Attempting to acquire token silently\");\n const response = await this.app.acquireTokenSilent(parameters);\n return this.handleResult(scopes, this.clientId, response);\n } catch (err) {\n throw this.handleError(scopes, err, options);\n }\n }\n\n /**\n * Attempts to retrieve the token in the browser.\n */\n protected async doGetToken(\n scopes: string[],\n options?: CredentialFlowGetTokenOptions\n ): Promise<AccessToken> {\n const account = await this.getActiveAccount();\n if (!account) {\n throw new AuthenticationRequiredError(scopes, options);\n }\n\n const parameters: msalBrowser.RedirectRequest = {\n authority: this.msalConfig.auth.authority!,\n correlationId: options?.correlationId,\n account: publicToMsal(account),\n scopes\n };\n\n switch (this.loginStyle) {\n case \"redirect\":\n // This will go out of the page.\n // Once the InteractiveBrowserCredential is initialized again,\n // we'll load the MSAL account in the constructor.\n await this.app.acquireTokenRedirect(parameters);\n return { token: \"\", expiresOnTimestamp: 0 };\n case \"popup\":\n return this.handleResult(\n scopes,\n this.clientId,\n await this.app.acquireTokenPopup(parameters)\n );\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"msalAuthCode.js","sourceRoot":"","sources":["../../../../src/msal/browserFlows/msalAuthCode.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport * as msalBrowser from \"@azure/msal-browser\";\n\nimport { AccessToken } from \"@azure/core-auth\";\n\nimport { AuthenticationRequiredError } from \"../../errors\";\nimport { defaultLoggerCallback, msalToPublic, publicToMsal } from \"../utils\";\nimport { AuthenticationRecord } from \"../types\";\nimport { CredentialFlowGetTokenOptions } from \"../credentials\";\nimport { MsalBrowserFlowOptions, MsalBrowser } from \"./browserCommon\";\n\n// We keep a copy of the redirect hash.\nconst redirectHash = self.location.hash;\n\n/**\n * Uses MSAL Browser 2.X for browser authentication,\n * which uses the [Auth Code Flow](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow).\n * @internal\n */\nexport class MSALAuthCode extends MsalBrowser {\n protected app: msalBrowser.PublicClientApplication;\n private loginHint?: string;\n\n /**\n * Sets up an MSAL object based on the given parameters.\n * MSAL with Auth Code allows sending a previously obtained `authenticationRecord` through the optional parameters,\n * which is set to be the active account.\n * @param options - Parameters necessary and otherwise used to create the MSAL object.\n */\n constructor(options: MsalBrowserFlowOptions) {\n super(options);\n this.loginHint = options.loginHint;\n\n this.msalConfig.cache = {\n cacheLocation: \"sessionStorage\",\n storeAuthStateInCookie: true // Set to true to improve the experience on IE11 and Edge.\n };\n this.msalConfig.system = {\n loggerOptions: {\n loggerCallback: defaultLoggerCallback(this.logger, \"Browser\")\n }\n };\n\n // Preparing the MSAL application.\n this.app = new msalBrowser.PublicClientApplication(\n this.msalConfig as msalBrowser.Configuration\n );\n if (this.account) {\n this.app.setActiveAccount(publicToMsal(this.account));\n }\n }\n\n /**\n * Loads the account based on the result of the authentication.\n * If no result was received, tries to load the account from the cache.\n * @param result - Result object received from MSAL.\n */\n private async handleBrowserResult(\n result?: msalBrowser.AuthenticationResult\n ): Promise<AuthenticationRecord | undefined> {\n try {\n if (result && result.account) {\n this.logger.info(`MSAL Browser V2 authentication successful.`);\n this.app.setActiveAccount(result.account);\n return msalToPublic(this.clientId, result.account);\n }\n\n // If by this point we happen to have an active account, we should stop trying to parse this.\n const activeAccount = await this.app!.getActiveAccount();\n if (activeAccount) {\n return msalToPublic(this.clientId, activeAccount);\n }\n\n // If we don't have an active account, we try to activate it from all the already loaded accounts.\n const accounts = this.app.getAllAccounts();\n if (accounts.length > 1) {\n // If there's more than one account in memory, we force the user to authenticate again.\n // At this point we can't identify which account should this credential work with,\n // since at this point the user won't have provided enough information.\n // We log a message in case that helps.\n this.logger.info(\n `More than one account was found authenticated for this Client ID and Tenant ID.\nHowever, no \"authenticationRecord\" has been provided for this credential,\ntherefore we're unable to pick between these accounts.\nA new login attempt will be requested, to ensure the correct account is picked.\nTo work with multiple accounts for the same Client ID and Tenant ID, please provide an \"authenticationRecord\" when initializing \"InteractiveBrowserCredential\".`\n );\n // To safely trigger a new login, we're also ensuring the local cache is cleared up for this MSAL object.\n // However, we want to avoid kicking the user out of their authentication on the Azure side.\n // We do this by calling to logout while specifying a `onRedirectNavigate` that returns false.\n await this.app.logout({\n onRedirectNavigate: () => false\n });\n return;\n }\n\n // If there's only one account for this MSAL object, we can safely activate it.\n if (accounts.length === 1) {\n const account = accounts[0];\n this.app.setActiveAccount(account);\n return msalToPublic(this.clientId, account);\n }\n\n this.logger.info(`No accounts were found through MSAL.`);\n } catch (e) {\n this.logger.info(`Failed to acquire token through MSAL. ${e.message}`);\n }\n return;\n }\n\n /**\n * Uses MSAL to handle the redirect.\n */\n public async handleRedirect(): Promise<AuthenticationRecord | undefined> {\n return this.handleBrowserResult(\n (await this.app.handleRedirectPromise(redirectHash)) || undefined\n );\n }\n\n /**\n * Uses MSAL to trigger a redirect or a popup login.\n */\n public async login(scopes: string | string[] = []): Promise<AuthenticationRecord | undefined> {\n const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];\n const loginRequest: msalBrowser.RedirectRequest = {\n scopes: arrayScopes,\n loginHint: this.loginHint\n };\n switch (this.loginStyle) {\n case \"redirect\": {\n await this.app.loginRedirect(loginRequest);\n return;\n }\n case \"popup\":\n return this.handleBrowserResult(await this.app.loginPopup(loginRequest));\n }\n }\n\n /**\n * Uses MSAL to retrieve the active account.\n */\n public async getActiveAccount(): Promise<AuthenticationRecord | undefined> {\n const account = this.app.getActiveAccount();\n if (!account) {\n return;\n }\n return msalToPublic(this.clientId, account);\n }\n\n /**\n * Attempts to retrieve a token from cache.\n */\n public async getTokenSilent(\n scopes: string[],\n options?: CredentialFlowGetTokenOptions\n ): Promise<AccessToken> {\n const account = await this.getActiveAccount();\n if (!account) {\n throw new AuthenticationRequiredError({\n scopes,\n getTokenOptions: options,\n message:\n \"Silent authentication failed. We couldn't retrieve an active account from the cache.\"\n });\n }\n\n const parameters: msalBrowser.SilentRequest = {\n authority: options?.authority || this.msalConfig.auth.authority!,\n correlationId: options?.correlationId,\n account: publicToMsal(account),\n forceRefresh: false,\n scopes\n };\n\n try {\n this.logger.info(\"Attempting to acquire token silently\");\n const response = await this.app.acquireTokenSilent(parameters);\n return this.handleResult(scopes, this.clientId, response);\n } catch (err) {\n throw this.handleError(scopes, err, options);\n }\n }\n\n /**\n * Attempts to retrieve the token in the browser.\n */\n protected async doGetToken(\n scopes: string[],\n options?: CredentialFlowGetTokenOptions\n ): Promise<AccessToken> {\n const account = await this.getActiveAccount();\n if (!account) {\n throw new AuthenticationRequiredError({\n scopes,\n getTokenOptions: options,\n message:\n \"Silent authentication failed. We couldn't retrieve an active account from the cache.\"\n });\n }\n\n const parameters: msalBrowser.RedirectRequest = {\n authority: options?.authority || this.msalConfig.auth.authority!,\n correlationId: options?.correlationId,\n account: publicToMsal(account),\n loginHint: this.loginHint,\n scopes\n };\n\n switch (this.loginStyle) {\n case \"redirect\":\n // This will go out of the page.\n // Once the InteractiveBrowserCredential is initialized again,\n // we'll load the MSAL account in the constructor.\n await this.app.acquireTokenRedirect(parameters);\n return { token: \"\", expiresOnTimestamp: 0 };\n case \"popup\":\n return this.handleResult(\n scopes,\n this.clientId,\n await this.app.acquireTokenPopup(parameters)\n );\n }\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../../src/msal/credentials.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions } from \"@azure/core-
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../../src/msal/credentials.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\n\nimport { AuthenticationRecord } from \"./types\";\n\n/**\n * The MSAL clients `getToken` requests can receive a `correlationId` and `disableAutomaticAuthentication`.\n * (which is used to prevent `getToken` from triggering the manual authentication if `getTokenSilent` fails).\n * @internal\n */\nexport interface CredentialFlowGetTokenOptions extends GetTokenOptions {\n /**\n * Unique identifier useful to track outgoing requests.\n */\n correlationId?: string;\n /**\n * Makes getToken throw if a manual authentication is necessary.\n */\n disableAutomaticAuthentication?: boolean;\n /**\n * Authority, to overwrite the default one, if necessary.\n */\n authority?: string;\n}\n\n/**\n * Simplified representation of the internal authentication flow.\n * @internal\n */\nexport interface CredentialFlow {\n /**\n * Clears the MSAL cache.\n */\n logout(): Promise<void>;\n /**\n * Tries to load the active account, either from memory or from MSAL.\n */\n getActiveAccount(): Promise<AuthenticationRecord | undefined>;\n /**\n * Calls to the implementation's doGetToken method.\n */\n getToken(scopes?: string[], options?: CredentialFlowGetTokenOptions): Promise<AccessToken | null>;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flows.js","sourceRoot":"","sources":["../../../src/msal/flows.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken } from \"@azure/core-
|
|
1
|
+
{"version":3,"file":"flows.js","sourceRoot":"","sources":["../../../src/msal/flows.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken } from \"@azure/core-auth\";\n\nimport { CredentialLogger } from \"../util/logging\";\nimport { AuthenticationRecord } from \"./types\";\nimport { CredentialFlowGetTokenOptions } from \"./credentials\";\n\n/**\n * Union of the constructor parameters that all MSAL flow types take.\n * @internal\n */\nexport interface MsalFlowOptions {\n logger: CredentialLogger;\n clientId?: string;\n tenantId?: string;\n authorityHost?: string;\n authenticationRecord?: AuthenticationRecord;\n disableAutomaticAuthentication?: boolean;\n}\n\n/**\n * The common methods we use to work with the MSAL flows.\n * @internal\n */\nexport interface MsalFlow {\n /**\n * Allows for any setup before any request is processed.\n */\n init(options?: CredentialFlowGetTokenOptions): Promise<void>;\n /**\n * Tries to load the active account, either from memory or from MSAL.\n */\n getActiveAccount(): Promise<AuthenticationRecord | undefined>;\n /**\n * Tries to retrieve the token silently using MSAL.\n */\n getTokenSilent(scopes?: string[], options?: CredentialFlowGetTokenOptions): Promise<AccessToken>;\n /**\n * Calls to the implementation's doGetToken method.\n */\n getToken(scopes?: string[], options?: CredentialFlowGetTokenOptions): Promise<AccessToken>;\n}\n"]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT license.
|
|
3
|
+
import { credentialLogger } from "../../util/logging";
|
|
4
|
+
import { MsalNode } from "./nodeCommon";
|
|
5
|
+
/**
|
|
6
|
+
* This MSAL client sets up a web server to listen for redirect callbacks, then calls to the MSAL's public application's `acquireTokenByDeviceCode` during `doGetToken`
|
|
7
|
+
* to trigger the authentication flow, and then respond based on the values obtained from the redirect callback
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export class MsalAuthorizationCode extends MsalNode {
|
|
11
|
+
constructor(options) {
|
|
12
|
+
super(options);
|
|
13
|
+
this.logger = credentialLogger("Node.js MSAL Authorization Code");
|
|
14
|
+
this.redirectUri = options.redirectUri;
|
|
15
|
+
this.authorizationCode = options.authorizationCode;
|
|
16
|
+
if (options.clientSecret) {
|
|
17
|
+
this.msalConfig.auth.clientSecret = options.clientSecret;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async getAuthCodeUrl(options) {
|
|
21
|
+
await this.init();
|
|
22
|
+
return this.confidentialApp.getAuthCodeUrl(options);
|
|
23
|
+
}
|
|
24
|
+
async doGetToken(scopes, options) {
|
|
25
|
+
var _a;
|
|
26
|
+
try {
|
|
27
|
+
const result = await ((_a = this.confidentialApp) === null || _a === void 0 ? void 0 : _a.acquireTokenByCode({
|
|
28
|
+
scopes,
|
|
29
|
+
redirectUri: this.redirectUri,
|
|
30
|
+
code: this.authorizationCode
|
|
31
|
+
}));
|
|
32
|
+
// The Client Credential flow does not return an account,
|
|
33
|
+
// so each time getToken gets called, we will have to acquire a new token through the service.
|
|
34
|
+
return this.handleResult(scopes, this.clientId, result || undefined);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
throw this.handleError(scopes, err, options);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=msalAuthorizationCode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"msalAuthorizationCode.js","sourceRoot":"","sources":["../../../../src/msal/nodeFlows/msalAuthorizationCode.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAmB,QAAQ,EAAE,MAAM,cAAc,CAAC;AAYzD;;;;GAIG;AACH,MAAM,OAAO,qBAAsB,SAAQ,QAAQ;IAIjD,YAAY,OAAqC;QAC/C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,gBAAgB,CAAC,iCAAiC,CAAC,CAAC;QAClE,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;QACnD,IAAI,OAAO,CAAC,YAAY,EAAE;YACxB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;SAC1D;IACH,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,OAAkD;QACrE,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC,eAAgB,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IACvD,CAAC;IAES,KAAK,CAAC,UAAU,CACxB,MAAgB,EAChB,OAAuC;;QAEvC,IAAI;YACF,MAAM,MAAM,GAAG,MAAM,CAAA,MAAA,IAAI,CAAC,eAAe,0CAAE,kBAAkB,CAAC;gBAC5D,MAAM;gBACN,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,IAAI,EAAE,IAAI,CAAC,iBAAiB;aAC7B,CAAC,CAAA,CAAC;YACH,yDAAyD;YACzD,8FAA8F;YAC9F,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,IAAI,SAAS,CAAC,CAAC;SACtE;QAAC,OAAO,GAAG,EAAE;YACZ,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;SAC9C;IACH,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken } from \"@azure/core-auth\";\nimport { credentialLogger } from \"../../util/logging\";\nimport { CredentialFlowGetTokenOptions } from \"../credentials\";\nimport { MsalNodeOptions, MsalNode } from \"./nodeCommon\";\n\n/**\n * Options that can be passed to configure MSAL to handle authentication through opening a browser window.\n * @internal\n */\nexport interface MSALAuthorizationCodeOptions extends MsalNodeOptions {\n redirectUri: string;\n authorizationCode: string;\n clientSecret?: string;\n}\n\n/**\n * This MSAL client sets up a web server to listen for redirect callbacks, then calls to the MSAL's public application's `acquireTokenByDeviceCode` during `doGetToken`\n * to trigger the authentication flow, and then respond based on the values obtained from the redirect callback\n * @internal\n */\nexport class MsalAuthorizationCode extends MsalNode {\n private redirectUri: string;\n private authorizationCode: string;\n\n constructor(options: MSALAuthorizationCodeOptions) {\n super(options);\n this.logger = credentialLogger(\"Node.js MSAL Authorization Code\");\n this.redirectUri = options.redirectUri;\n this.authorizationCode = options.authorizationCode;\n if (options.clientSecret) {\n this.msalConfig.auth.clientSecret = options.clientSecret;\n }\n }\n\n async getAuthCodeUrl(options: { scopes: string[]; redirectUri: string }): Promise<string> {\n await this.init();\n return this.confidentialApp!.getAuthCodeUrl(options);\n }\n\n protected async doGetToken(\n scopes: string[],\n options?: CredentialFlowGetTokenOptions\n ): Promise<AccessToken> {\n try {\n const result = await this.confidentialApp?.acquireTokenByCode({\n scopes,\n redirectUri: this.redirectUri,\n code: this.authorizationCode\n });\n // The Client Credential flow does not return an account,\n // so each time getToken gets called, we will have to acquire a new token through the service.\n return this.handleResult(scopes, this.clientId, result || undefined);\n } catch (err) {\n throw this.handleError(scopes, err, options);\n }\n }\n}\n"]}
|
|
@@ -1,10 +1,45 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT license.
|
|
3
|
-
import {
|
|
4
|
-
import { readFileSync } from "fs";
|
|
3
|
+
import { readFile } from "fs";
|
|
5
4
|
import { createHash } from "crypto";
|
|
5
|
+
import { promisify } from "util";
|
|
6
6
|
import { MsalNode } from "./nodeCommon";
|
|
7
7
|
import { formatError } from "../../util/logging";
|
|
8
|
+
const readFileAsync = promisify(readFile);
|
|
9
|
+
/**
|
|
10
|
+
* Tries to asynchronously load a certificate from the given path.
|
|
11
|
+
*
|
|
12
|
+
* @param configuration - Either the PEM value or the path to the certificate.
|
|
13
|
+
* @param sendCertificateChain - Option to include x5c header for SubjectName and Issuer name authorization.
|
|
14
|
+
* @returns - The certificate parts, or `undefined` if the certificate could not be loaded.
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
export async function parseCertificate(configuration, sendCertificateChain) {
|
|
18
|
+
const certificateParts = {};
|
|
19
|
+
certificateParts.certificateContents =
|
|
20
|
+
configuration.certificate || (await readFileAsync(configuration.certificatePath, "utf8"));
|
|
21
|
+
if (sendCertificateChain) {
|
|
22
|
+
certificateParts.x5c = certificateParts.certificateContents;
|
|
23
|
+
}
|
|
24
|
+
const certificatePattern = /(-+BEGIN CERTIFICATE-+)(\n\r?|\r\n?)([A-Za-z0-9+/\n\r]+=*)(\n\r?|\r\n?)(-+END CERTIFICATE-+)/g;
|
|
25
|
+
const publicKeys = [];
|
|
26
|
+
// Match all possible certificates, in the order they are in the file. These will form the chain that is used for x5c
|
|
27
|
+
let match;
|
|
28
|
+
do {
|
|
29
|
+
match = certificatePattern.exec(certificateParts.certificateContents);
|
|
30
|
+
if (match) {
|
|
31
|
+
publicKeys.push(match[3]);
|
|
32
|
+
}
|
|
33
|
+
} while (match);
|
|
34
|
+
if (publicKeys.length === 0) {
|
|
35
|
+
throw new Error("The file at the specified path does not contain a PEM-encoded certificate.");
|
|
36
|
+
}
|
|
37
|
+
certificateParts.thumbprint = createHash("sha1")
|
|
38
|
+
.update(Buffer.from(publicKeys[0], "base64"))
|
|
39
|
+
.digest("hex")
|
|
40
|
+
.toUpperCase();
|
|
41
|
+
return certificateParts;
|
|
42
|
+
}
|
|
8
43
|
/**
|
|
9
44
|
* MSAL client certificate client. Calls to MSAL's confidential application's `acquireTokenByClientCredential` during `doGetToken`.
|
|
10
45
|
* @internal
|
|
@@ -13,57 +48,41 @@ export class MsalClientCertificate extends MsalNode {
|
|
|
13
48
|
constructor(options) {
|
|
14
49
|
super(options);
|
|
15
50
|
this.requiresConfidential = true;
|
|
51
|
+
this.configuration = options.configuration;
|
|
16
52
|
this.sendCertificateChain = options.sendCertificateChain;
|
|
17
|
-
const parts = this.parseCertificate(options.certificatePath);
|
|
18
|
-
this.msalConfig.auth.clientCertificate = {
|
|
19
|
-
thumbprint: parts.thumbprint,
|
|
20
|
-
privateKey: parts.certificateContents,
|
|
21
|
-
x5c: parts.x5c
|
|
22
|
-
};
|
|
23
53
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
54
|
+
// Changing the MSAL configuration asynchronously
|
|
55
|
+
async init(options) {
|
|
56
|
+
try {
|
|
57
|
+
const parts = await parseCertificate(this.configuration, this.sendCertificateChain);
|
|
58
|
+
this.msalConfig.auth.clientCertificate = {
|
|
59
|
+
thumbprint: parts.thumbprint,
|
|
60
|
+
privateKey: parts.certificateContents,
|
|
61
|
+
x5c: parts.x5c
|
|
62
|
+
};
|
|
29
63
|
}
|
|
30
|
-
|
|
31
|
-
const publicKeys = [];
|
|
32
|
-
// Match all possible certificates, in the order they are in the file. These will form the chain that is used for x5c
|
|
33
|
-
let match;
|
|
34
|
-
do {
|
|
35
|
-
match = certificatePattern.exec(certificateParts.certificateContents);
|
|
36
|
-
if (match) {
|
|
37
|
-
publicKeys.push(match[3]);
|
|
38
|
-
}
|
|
39
|
-
} while (match);
|
|
40
|
-
if (publicKeys.length === 0) {
|
|
41
|
-
const error = new Error("The file at the specified path does not contain a PEM-encoded certificate.");
|
|
64
|
+
catch (error) {
|
|
42
65
|
this.logger.info(formatError("", error));
|
|
43
66
|
throw error;
|
|
44
67
|
}
|
|
45
|
-
|
|
46
|
-
.update(Buffer.from(publicKeys[0], "base64"))
|
|
47
|
-
.digest("hex")
|
|
48
|
-
.toUpperCase();
|
|
49
|
-
return certificateParts;
|
|
68
|
+
return super.init(options);
|
|
50
69
|
}
|
|
51
|
-
doGetToken(scopes, options = {}) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
70
|
+
async doGetToken(scopes, options = {}) {
|
|
71
|
+
try {
|
|
72
|
+
const result = await this.confidentialApp.acquireTokenByClientCredential({
|
|
73
|
+
scopes,
|
|
74
|
+
correlationId: options.correlationId,
|
|
75
|
+
azureRegion: this.azureRegion,
|
|
76
|
+
authority: options.authority
|
|
77
|
+
});
|
|
78
|
+
// Even though we're providing the same default in memory persistence cache that we use for DeviceCodeCredential,
|
|
79
|
+
// The Client Credential flow does not return the account information from the authentication service,
|
|
80
|
+
// so each time getToken gets called, we will have to acquire a new token through the service.
|
|
81
|
+
return this.handleResult(scopes, this.clientId, result || undefined);
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
throw this.handleError(scopes, err, options);
|
|
85
|
+
}
|
|
67
86
|
}
|
|
68
87
|
}
|
|
69
88
|
//# sourceMappingURL=msalClientCertificate.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"msalClientCertificate.js","sourceRoot":"","sources":["../../../../src/msal/nodeFlows/msalClientCertificate.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC
|
|
1
|
+
{"version":3,"file":"msalClientCertificate.js","sourceRoot":"","sources":["../../../../src/msal/nodeFlows/msalClientCertificate.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { readFile } from \"fs\";\nimport { createHash } from \"crypto\";\nimport { promisify } from \"util\";\nimport { AccessToken } from \"@azure/core-auth\";\n\nimport { MsalNodeOptions, MsalNode } from \"./nodeCommon\";\nimport { formatError } from \"../../util/logging\";\nimport { CredentialFlowGetTokenOptions } from \"../credentials\";\nimport { ClientCertificateCredentialPEMConfiguration } from \"../../credentials/clientCertificateCredential\";\n\nconst readFileAsync = promisify(readFile);\n\n/**\n * Options that can be passed to configure MSAL to handle client certificates.\n * @internal\n */\nexport interface MSALClientCertificateOptions extends MsalNodeOptions {\n /**\n * Location of the PEM certificate.\n */\n configuration: ClientCertificateCredentialPEMConfiguration;\n /**\n * Option to include x5c header for SubjectName and Issuer name authorization.\n * Set this option to send base64 encoded public certificate in the client assertion header as an x5c claim\n */\n sendCertificateChain?: boolean;\n}\n\n/**\n * Parts of a certificate, as understood by MSAL.\n * @internal\n */\ninterface CertificateParts {\n /**\n * Hex encoded X.509 SHA-1 thumbprint of the certificate\n */\n thumbprint: string;\n /**\n * The PEM encoded private key (string should contain -----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY-----\n */\n certificateContents: string;\n /**\n * x5c header.\n */\n x5c: string;\n}\n\n/**\n * Tries to asynchronously load a certificate from the given path.\n *\n * @param configuration - Either the PEM value or the path to the certificate.\n * @param sendCertificateChain - Option to include x5c header for SubjectName and Issuer name authorization.\n * @returns - The certificate parts, or `undefined` if the certificate could not be loaded.\n * @internal\n */\nexport async function parseCertificate(\n configuration: ClientCertificateCredentialPEMConfiguration,\n sendCertificateChain?: boolean\n): Promise<CertificateParts> {\n const certificateParts: Partial<CertificateParts> = {};\n\n certificateParts.certificateContents =\n configuration.certificate || (await readFileAsync(configuration.certificatePath!, \"utf8\"));\n if (sendCertificateChain) {\n certificateParts.x5c = certificateParts.certificateContents;\n }\n\n const certificatePattern = /(-+BEGIN CERTIFICATE-+)(\\n\\r?|\\r\\n?)([A-Za-z0-9+/\\n\\r]+=*)(\\n\\r?|\\r\\n?)(-+END CERTIFICATE-+)/g;\n const publicKeys: string[] = [];\n\n // Match all possible certificates, in the order they are in the file. These will form the chain that is used for x5c\n let match;\n do {\n match = certificatePattern.exec(certificateParts.certificateContents);\n if (match) {\n publicKeys.push(match[3]);\n }\n } while (match);\n\n if (publicKeys.length === 0) {\n throw new Error(\"The file at the specified path does not contain a PEM-encoded certificate.\");\n }\n\n certificateParts.thumbprint = createHash(\"sha1\")\n .update(Buffer.from(publicKeys[0], \"base64\"))\n .digest(\"hex\")\n .toUpperCase();\n\n return certificateParts as CertificateParts;\n}\n\n/**\n * MSAL client certificate client. Calls to MSAL's confidential application's `acquireTokenByClientCredential` during `doGetToken`.\n * @internal\n */\nexport class MsalClientCertificate extends MsalNode {\n private configuration: ClientCertificateCredentialPEMConfiguration;\n private sendCertificateChain?: boolean;\n\n constructor(options: MSALClientCertificateOptions) {\n super(options);\n this.requiresConfidential = true;\n this.configuration = options.configuration;\n this.sendCertificateChain = options.sendCertificateChain;\n }\n\n // Changing the MSAL configuration asynchronously\n async init(options?: CredentialFlowGetTokenOptions): Promise<void> {\n try {\n const parts = await parseCertificate(this.configuration, this.sendCertificateChain);\n this.msalConfig.auth.clientCertificate = {\n thumbprint: parts.thumbprint,\n privateKey: parts.certificateContents,\n x5c: parts.x5c\n };\n } catch (error) {\n this.logger.info(formatError(\"\", error));\n throw error;\n }\n return super.init(options);\n }\n\n protected async doGetToken(\n scopes: string[],\n options: CredentialFlowGetTokenOptions = {}\n ): Promise<AccessToken> {\n try {\n const result = await this.confidentialApp!.acquireTokenByClientCredential({\n scopes,\n correlationId: options.correlationId,\n azureRegion: this.azureRegion,\n authority: options.authority\n });\n // Even though we're providing the same default in memory persistence cache that we use for DeviceCodeCredential,\n // The Client Credential flow does not return the account information from the authentication service,\n // so each time getToken gets called, we will have to acquire a new token through the service.\n return this.handleResult(scopes, this.clientId, result || undefined);\n } catch (err) {\n throw this.handleError(scopes, err, options);\n }\n }\n}\n"]}
|