@azure/msal-browser 4.8.0 → 4.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/IPublicClientApplication.mjs +1 -1
- package/dist/app/PublicClientApplication.mjs +1 -1
- package/dist/app/PublicClientNext.mjs +1 -1
- package/dist/broker/nativeBroker/NativeMessageHandler.mjs +1 -1
- package/dist/broker/nativeBroker/NativeStatusCodes.mjs +1 -1
- package/dist/cache/AccountManager.mjs +1 -1
- package/dist/cache/AsyncMemoryStorage.mjs +1 -1
- package/dist/cache/BrowserCacheManager.d.ts +4 -41
- package/dist/cache/BrowserCacheManager.d.ts.map +1 -1
- package/dist/cache/BrowserCacheManager.mjs +18 -143
- package/dist/cache/BrowserCacheManager.mjs.map +1 -1
- package/dist/cache/CacheHelpers.mjs +1 -1
- package/dist/cache/CookieStorage.mjs +1 -1
- package/dist/cache/DatabaseStorage.mjs +1 -1
- package/dist/cache/LocalStorage.mjs +2 -2
- package/dist/cache/MemoryStorage.mjs +1 -1
- package/dist/cache/SessionStorage.mjs +1 -1
- package/dist/cache/TokenCache.mjs +1 -1
- package/dist/config/Configuration.mjs +5 -5
- package/dist/config/Configuration.mjs.map +1 -1
- package/dist/controllers/ControllerFactory.mjs +1 -1
- package/dist/controllers/NestedAppAuthController.d.ts +2 -2
- package/dist/controllers/NestedAppAuthController.d.ts.map +1 -1
- package/dist/controllers/NestedAppAuthController.mjs +1 -1
- package/dist/controllers/NestedAppAuthController.mjs.map +1 -1
- package/dist/controllers/StandardController.d.ts.map +1 -1
- package/dist/controllers/StandardController.mjs +28 -16
- package/dist/controllers/StandardController.mjs.map +1 -1
- package/dist/controllers/UnknownOperatingContextController.d.ts +2 -2
- package/dist/controllers/UnknownOperatingContextController.d.ts.map +1 -1
- package/dist/controllers/UnknownOperatingContextController.mjs +1 -1
- package/dist/controllers/UnknownOperatingContextController.mjs.map +1 -1
- package/dist/crypto/BrowserCrypto.d.ts +11 -0
- package/dist/crypto/BrowserCrypto.d.ts.map +1 -1
- package/dist/crypto/BrowserCrypto.mjs +68 -5
- package/dist/crypto/BrowserCrypto.mjs.map +1 -1
- package/dist/crypto/CryptoOps.mjs +1 -1
- package/dist/crypto/PkceGenerator.mjs +1 -1
- package/dist/crypto/SignedHttpRequest.mjs +1 -1
- package/dist/encode/Base64Decode.mjs +1 -1
- package/dist/encode/Base64Encode.mjs +1 -1
- package/dist/error/BrowserAuthError.d.ts +3 -5
- package/dist/error/BrowserAuthError.d.ts.map +1 -1
- package/dist/error/BrowserAuthError.mjs +5 -7
- package/dist/error/BrowserAuthError.mjs.map +1 -1
- package/dist/error/BrowserAuthErrorCodes.d.ts +3 -1
- package/dist/error/BrowserAuthErrorCodes.d.ts.map +1 -1
- package/dist/error/BrowserAuthErrorCodes.mjs +6 -4
- package/dist/error/BrowserAuthErrorCodes.mjs.map +1 -1
- package/dist/error/BrowserConfigurationAuthError.mjs +2 -2
- package/dist/error/BrowserConfigurationAuthErrorCodes.mjs +1 -1
- package/dist/error/NativeAuthError.mjs +1 -1
- package/dist/error/NativeAuthErrorCodes.mjs +1 -1
- package/dist/error/NestedAppAuthError.mjs +1 -1
- package/dist/event/EventHandler.mjs +1 -1
- package/dist/event/EventMessage.mjs +1 -1
- package/dist/event/EventType.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/interaction_client/BaseInteractionClient.mjs +1 -1
- package/dist/interaction_client/HybridSpaAuthorizationCodeClient.mjs +1 -1
- package/dist/interaction_client/NativeInteractionClient.d.ts.map +1 -1
- package/dist/interaction_client/NativeInteractionClient.mjs +1 -3
- package/dist/interaction_client/NativeInteractionClient.mjs.map +1 -1
- package/dist/interaction_client/PopupClient.d.ts +14 -1
- package/dist/interaction_client/PopupClient.d.ts.map +1 -1
- package/dist/interaction_client/PopupClient.mjs +65 -64
- package/dist/interaction_client/PopupClient.mjs.map +1 -1
- package/dist/interaction_client/RedirectClient.d.ts +20 -3
- package/dist/interaction_client/RedirectClient.d.ts.map +1 -1
- package/dist/interaction_client/RedirectClient.mjs +132 -76
- package/dist/interaction_client/RedirectClient.mjs.map +1 -1
- package/dist/interaction_client/SilentAuthCodeClient.d.ts.map +1 -1
- package/dist/interaction_client/SilentAuthCodeClient.mjs +1 -1
- package/dist/interaction_client/SilentAuthCodeClient.mjs.map +1 -1
- package/dist/interaction_client/SilentCacheClient.mjs +1 -1
- package/dist/interaction_client/SilentIframeClient.d.ts +13 -3
- package/dist/interaction_client/SilentIframeClient.d.ts.map +1 -1
- package/dist/interaction_client/SilentIframeClient.mjs +57 -44
- package/dist/interaction_client/SilentIframeClient.mjs.map +1 -1
- package/dist/interaction_client/SilentRefreshClient.mjs +1 -1
- package/dist/interaction_client/StandardInteractionClient.d.ts +2 -3
- package/dist/interaction_client/StandardInteractionClient.d.ts.map +1 -1
- package/dist/interaction_client/StandardInteractionClient.mjs +1 -1
- package/dist/interaction_client/StandardInteractionClient.mjs.map +1 -1
- package/dist/interaction_handler/InteractionHandler.d.ts +4 -5
- package/dist/interaction_handler/InteractionHandler.d.ts.map +1 -1
- package/dist/interaction_handler/InteractionHandler.mjs +1 -1
- package/dist/interaction_handler/InteractionHandler.mjs.map +1 -1
- package/dist/interaction_handler/SilentHandler.d.ts +4 -2
- package/dist/interaction_handler/SilentHandler.d.ts.map +1 -1
- package/dist/interaction_handler/SilentHandler.mjs +15 -5
- package/dist/interaction_handler/SilentHandler.mjs.map +1 -1
- package/dist/naa/BridgeError.mjs +1 -1
- package/dist/naa/BridgeProxy.mjs +1 -1
- package/dist/naa/BridgeStatusCode.mjs +1 -1
- package/dist/naa/mapping/NestedAppAuthAdapter.mjs +2 -2
- package/dist/navigation/NavigationClient.mjs +1 -1
- package/dist/network/FetchClient.mjs +1 -1
- package/dist/operatingcontext/BaseOperatingContext.mjs +1 -1
- package/dist/operatingcontext/NestedAppOperatingContext.mjs +1 -1
- package/dist/operatingcontext/StandardOperatingContext.mjs +1 -1
- package/dist/operatingcontext/UnknownOperatingContext.mjs +1 -1
- package/dist/packageMetadata.d.ts +1 -1
- package/dist/packageMetadata.mjs +2 -2
- package/dist/protocol/Authorize.d.ts +53 -1
- package/dist/protocol/Authorize.d.ts.map +1 -1
- package/dist/protocol/Authorize.mjs +147 -4
- package/dist/protocol/Authorize.mjs.map +1 -1
- package/dist/request/AuthorizationUrlRequest.d.ts +2 -4
- package/dist/request/AuthorizationUrlRequest.d.ts.map +1 -1
- package/dist/request/PopupRequest.d.ts +1 -1
- package/dist/request/PopupRequest.d.ts.map +1 -1
- package/dist/request/RedirectRequest.d.ts +1 -1
- package/dist/request/RedirectRequest.d.ts.map +1 -1
- package/dist/request/RequestHelpers.mjs +1 -1
- package/dist/request/SsoSilentRequest.d.ts +1 -1
- package/dist/request/SsoSilentRequest.d.ts.map +1 -1
- package/dist/response/ResponseHandler.mjs +1 -1
- package/dist/telemetry/BrowserPerformanceClient.mjs +1 -1
- package/dist/telemetry/BrowserPerformanceMeasurement.mjs +1 -1
- package/dist/utils/BrowserConstants.d.ts +1 -10
- package/dist/utils/BrowserConstants.d.ts.map +1 -1
- package/dist/utils/BrowserConstants.mjs +2 -15
- package/dist/utils/BrowserConstants.mjs.map +1 -1
- package/dist/utils/BrowserProtocolUtils.mjs +1 -1
- package/dist/utils/BrowserUtils.mjs +1 -1
- package/lib/msal-browser.cjs +1588 -1555
- package/lib/msal-browser.cjs.map +1 -1
- package/lib/msal-browser.js +1588 -1555
- package/lib/msal-browser.js.map +1 -1
- package/lib/msal-browser.min.js +68 -67
- package/lib/types/cache/BrowserCacheManager.d.ts +4 -41
- package/lib/types/cache/BrowserCacheManager.d.ts.map +1 -1
- package/lib/types/controllers/NestedAppAuthController.d.ts +2 -2
- package/lib/types/controllers/NestedAppAuthController.d.ts.map +1 -1
- package/lib/types/controllers/StandardController.d.ts.map +1 -1
- package/lib/types/controllers/UnknownOperatingContextController.d.ts +2 -2
- package/lib/types/controllers/UnknownOperatingContextController.d.ts.map +1 -1
- package/lib/types/crypto/BrowserCrypto.d.ts +11 -0
- package/lib/types/crypto/BrowserCrypto.d.ts.map +1 -1
- package/lib/types/error/BrowserAuthError.d.ts +3 -5
- package/lib/types/error/BrowserAuthError.d.ts.map +1 -1
- package/lib/types/error/BrowserAuthErrorCodes.d.ts +3 -1
- package/lib/types/error/BrowserAuthErrorCodes.d.ts.map +1 -1
- package/lib/types/interaction_client/NativeInteractionClient.d.ts.map +1 -1
- package/lib/types/interaction_client/PopupClient.d.ts +14 -1
- package/lib/types/interaction_client/PopupClient.d.ts.map +1 -1
- package/lib/types/interaction_client/RedirectClient.d.ts +20 -3
- package/lib/types/interaction_client/RedirectClient.d.ts.map +1 -1
- package/lib/types/interaction_client/SilentAuthCodeClient.d.ts.map +1 -1
- package/lib/types/interaction_client/SilentIframeClient.d.ts +13 -3
- package/lib/types/interaction_client/SilentIframeClient.d.ts.map +1 -1
- package/lib/types/interaction_client/StandardInteractionClient.d.ts +2 -3
- package/lib/types/interaction_client/StandardInteractionClient.d.ts.map +1 -1
- package/lib/types/interaction_handler/InteractionHandler.d.ts +4 -5
- package/lib/types/interaction_handler/InteractionHandler.d.ts.map +1 -1
- package/lib/types/interaction_handler/SilentHandler.d.ts +4 -2
- package/lib/types/interaction_handler/SilentHandler.d.ts.map +1 -1
- package/lib/types/packageMetadata.d.ts +1 -1
- package/lib/types/protocol/Authorize.d.ts +53 -1
- package/lib/types/protocol/Authorize.d.ts.map +1 -1
- package/lib/types/request/AuthorizationUrlRequest.d.ts +2 -4
- package/lib/types/request/AuthorizationUrlRequest.d.ts.map +1 -1
- package/lib/types/request/PopupRequest.d.ts +1 -1
- package/lib/types/request/PopupRequest.d.ts.map +1 -1
- package/lib/types/request/RedirectRequest.d.ts +1 -1
- package/lib/types/request/RedirectRequest.d.ts.map +1 -1
- package/lib/types/request/SsoSilentRequest.d.ts +1 -1
- package/lib/types/request/SsoSilentRequest.d.ts.map +1 -1
- package/lib/types/utils/BrowserConstants.d.ts +1 -10
- package/lib/types/utils/BrowserConstants.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/cache/BrowserCacheManager.ts +30 -205
- package/src/config/Configuration.ts +2 -2
- package/src/controllers/NestedAppAuthController.ts +2 -0
- package/src/controllers/StandardController.ts +35 -24
- package/src/controllers/UnknownOperatingContextController.ts +2 -0
- package/src/crypto/BrowserCrypto.ts +91 -2
- package/src/error/BrowserAuthError.ts +6 -8
- package/src/error/BrowserAuthErrorCodes.ts +3 -1
- package/src/interaction_client/NativeInteractionClient.ts +0 -2
- package/src/interaction_client/PopupClient.ts +163 -119
- package/src/interaction_client/RedirectClient.ts +258 -140
- package/src/interaction_client/SilentAuthCodeClient.ts +2 -2
- package/src/interaction_client/SilentIframeClient.ts +154 -99
- package/src/interaction_client/StandardInteractionClient.ts +3 -3
- package/src/interaction_handler/InteractionHandler.ts +4 -4
- package/src/interaction_handler/SilentHandler.ts +31 -2
- package/src/packageMetadata.ts +1 -1
- package/src/protocol/Authorize.ts +356 -2
- package/src/request/AuthorizationUrlRequest.ts +3 -5
- package/src/request/PopupRequest.ts +1 -0
- package/src/request/RedirectRequest.ts +1 -0
- package/src/request/SsoSilentRequest.ts +1 -0
- package/src/utils/BrowserConstants.ts +1 -10
- package/dist/interaction_handler/RedirectHandler.d.ts +0 -33
- package/dist/interaction_handler/RedirectHandler.d.ts.map +0 -1
- package/dist/interaction_handler/RedirectHandler.mjs +0 -144
- package/dist/interaction_handler/RedirectHandler.mjs.map +0 -1
- package/lib/types/interaction_handler/RedirectHandler.d.ts +0 -33
- package/lib/types/interaction_handler/RedirectHandler.d.ts.map +0 -1
- package/src/interaction_handler/RedirectHandler.ts +0 -252
package/lib/msal-browser.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @azure/msal-browser v4.
|
|
1
|
+
/*! @azure/msal-browser v4.9.1 2025-03-26 */
|
|
2
2
|
'use strict';
|
|
3
3
|
(function (global, factory) {
|
|
4
4
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.msal = {}));
|
|
7
7
|
})(this, (function (exports) { 'use strict';
|
|
8
8
|
|
|
9
|
-
/*! @azure/msal-common v15.
|
|
9
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
10
10
|
/*
|
|
11
11
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
12
12
|
* Licensed under the MIT License.
|
|
@@ -41,11 +41,8 @@
|
|
|
41
41
|
PROFILE_SCOPE: "profile",
|
|
42
42
|
OFFLINE_ACCESS_SCOPE: "offline_access",
|
|
43
43
|
EMAIL_SCOPE: "email",
|
|
44
|
-
// Default response type for authorization code flow
|
|
45
|
-
CODE_RESPONSE_TYPE: "code",
|
|
46
44
|
CODE_GRANT_TYPE: "authorization_code",
|
|
47
45
|
RT_GRANT_TYPE: "refresh_token",
|
|
48
|
-
FRAGMENT_RESPONSE_MODE: "fragment",
|
|
49
46
|
S256_CODE_CHALLENGE_METHOD: "S256",
|
|
50
47
|
URL_FORM_CONTENT_TYPE: "application/x-www-form-urlencoded;charset=utf-8",
|
|
51
48
|
AUTHORIZATION_PENDING: "authorization_pending",
|
|
@@ -65,31 +62,14 @@
|
|
|
65
62
|
"login.microsoft.com",
|
|
66
63
|
"sts.windows.net",
|
|
67
64
|
],
|
|
68
|
-
TOKEN_RESPONSE_TYPE: "token",
|
|
69
|
-
ID_TOKEN_RESPONSE_TYPE: "id_token",
|
|
70
65
|
SHR_NONCE_VALIDITY: 240,
|
|
71
66
|
INVALID_INSTANCE: "invalid_instance",
|
|
72
67
|
};
|
|
73
68
|
const HttpStatus = {
|
|
74
|
-
SUCCESS: 200,
|
|
75
|
-
SUCCESS_RANGE_START: 200,
|
|
76
|
-
SUCCESS_RANGE_END: 299,
|
|
77
|
-
REDIRECT: 302,
|
|
78
|
-
CLIENT_ERROR: 400,
|
|
79
69
|
CLIENT_ERROR_RANGE_START: 400,
|
|
80
|
-
BAD_REQUEST: 400,
|
|
81
|
-
UNAUTHORIZED: 401,
|
|
82
|
-
NOT_FOUND: 404,
|
|
83
|
-
REQUEST_TIMEOUT: 408,
|
|
84
|
-
TOO_MANY_REQUESTS: 429,
|
|
85
70
|
CLIENT_ERROR_RANGE_END: 499,
|
|
86
|
-
SERVER_ERROR: 500,
|
|
87
71
|
SERVER_ERROR_RANGE_START: 500,
|
|
88
|
-
|
|
89
|
-
GATEWAY_TIMEOUT: 504,
|
|
90
|
-
SERVER_ERROR_RANGE_END: 599,
|
|
91
|
-
MULTI_SIDED_ERROR: 600,
|
|
92
|
-
};
|
|
72
|
+
SERVER_ERROR_RANGE_END: 599};
|
|
93
73
|
const OIDC_DEFAULT_SCOPES = [
|
|
94
74
|
Constants.OPENID_SCOPE,
|
|
95
75
|
Constants.PROFILE_SCOPE,
|
|
@@ -150,8 +130,16 @@
|
|
|
150
130
|
PLAIN: "plain",
|
|
151
131
|
S256: "S256",
|
|
152
132
|
};
|
|
133
|
+
/**
|
|
134
|
+
* Allowed values for response_type
|
|
135
|
+
*/
|
|
136
|
+
const OAuthResponseType = {
|
|
137
|
+
CODE: "code",
|
|
138
|
+
IDTOKEN_TOKEN_REFRESHTOKEN: "id_token token refresh_token",
|
|
139
|
+
};
|
|
153
140
|
/**
|
|
154
141
|
* allowed values for server response type
|
|
142
|
+
* @deprecated Use ResponseMode instead
|
|
155
143
|
*/
|
|
156
144
|
const ServerResponseType = {
|
|
157
145
|
QUERY: "query",
|
|
@@ -161,28 +149,19 @@
|
|
|
161
149
|
* allowed values for response_mode
|
|
162
150
|
*/
|
|
163
151
|
const ResponseMode = {
|
|
164
|
-
|
|
165
|
-
FORM_POST: "form_post",
|
|
166
|
-
};
|
|
152
|
+
QUERY: "query"};
|
|
167
153
|
/**
|
|
168
154
|
* allowed grant_type
|
|
169
155
|
*/
|
|
170
156
|
const GrantType = {
|
|
171
|
-
IMPLICIT_GRANT: "implicit",
|
|
172
157
|
AUTHORIZATION_CODE_GRANT: "authorization_code",
|
|
173
|
-
|
|
174
|
-
RESOURCE_OWNER_PASSWORD_GRANT: "password",
|
|
175
|
-
REFRESH_TOKEN_GRANT: "refresh_token",
|
|
176
|
-
DEVICE_CODE_GRANT: "device_code",
|
|
177
|
-
JWT_BEARER: "urn:ietf:params:oauth:grant-type:jwt-bearer",
|
|
178
|
-
};
|
|
158
|
+
REFRESH_TOKEN_GRANT: "refresh_token"};
|
|
179
159
|
/**
|
|
180
160
|
* Account types in Cache
|
|
181
161
|
*/
|
|
182
162
|
const CacheAccountType = {
|
|
183
163
|
MSSTS_ACCOUNT_TYPE: "MSSTS",
|
|
184
164
|
ADFS_ACCOUNT_TYPE: "ADFS",
|
|
185
|
-
MSAV1_ACCOUNT_TYPE: "MSA",
|
|
186
165
|
GENERIC_ACCOUNT_TYPE: "Generic", // NTLM, Kerberos, FBA, Basic etc
|
|
187
166
|
};
|
|
188
167
|
/**
|
|
@@ -219,7 +198,6 @@
|
|
|
219
198
|
};
|
|
220
199
|
const SERVER_TELEM_CONSTANTS = {
|
|
221
200
|
SCHEMA_VERSION: 5,
|
|
222
|
-
MAX_CUR_HEADER_BYTES: 80,
|
|
223
201
|
MAX_LAST_HEADER_BYTES: 330,
|
|
224
202
|
MAX_CACHED_ERRORS: 50,
|
|
225
203
|
CACHE_KEY: "server-telemetry",
|
|
@@ -274,9 +252,7 @@
|
|
|
274
252
|
* Region Discovery Outcomes
|
|
275
253
|
*/
|
|
276
254
|
const RegionDiscoveryOutcomes = {
|
|
277
|
-
CONFIGURED_MATCHES_DETECTED: "1",
|
|
278
255
|
CONFIGURED_NO_AUTO_DETECTION: "2",
|
|
279
|
-
CONFIGURED_NOT_DETECTED: "3",
|
|
280
256
|
AUTO_DETECTION_REQUESTED_SUCCESSFUL: "4",
|
|
281
257
|
AUTO_DETECTION_REQUESTED_FAILED: "5",
|
|
282
258
|
};
|
|
@@ -303,7 +279,7 @@
|
|
|
303
279
|
// Token renewal offset default in seconds
|
|
304
280
|
const DEFAULT_TOKEN_RENEWAL_OFFSET_SEC = 300;
|
|
305
281
|
|
|
306
|
-
/*! @azure/msal-common v15.
|
|
282
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
307
283
|
/*
|
|
308
284
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
309
285
|
* Licensed under the MIT License.
|
|
@@ -320,7 +296,7 @@
|
|
|
320
296
|
unexpectedError: unexpectedError
|
|
321
297
|
});
|
|
322
298
|
|
|
323
|
-
/*! @azure/msal-common v15.
|
|
299
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
324
300
|
|
|
325
301
|
/*
|
|
326
302
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -369,7 +345,7 @@
|
|
|
369
345
|
: AuthErrorMessages[code]);
|
|
370
346
|
}
|
|
371
347
|
|
|
372
|
-
/*! @azure/msal-common v15.
|
|
348
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
373
349
|
/*
|
|
374
350
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
375
351
|
* Licensed under the MIT License.
|
|
@@ -467,7 +443,7 @@
|
|
|
467
443
|
userTimeoutReached: userTimeoutReached
|
|
468
444
|
});
|
|
469
445
|
|
|
470
|
-
/*! @azure/msal-common v15.
|
|
446
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
471
447
|
|
|
472
448
|
/*
|
|
473
449
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -719,7 +695,7 @@
|
|
|
719
695
|
return new ClientAuthError(errorCode, additionalMessage);
|
|
720
696
|
}
|
|
721
697
|
|
|
722
|
-
/*! @azure/msal-common v15.
|
|
698
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
723
699
|
|
|
724
700
|
/*
|
|
725
701
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -758,7 +734,7 @@
|
|
|
758
734
|
},
|
|
759
735
|
};
|
|
760
736
|
|
|
761
|
-
/*! @azure/msal-common v15.
|
|
737
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
762
738
|
|
|
763
739
|
/*
|
|
764
740
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -949,12 +925,12 @@
|
|
|
949
925
|
}
|
|
950
926
|
}
|
|
951
927
|
|
|
952
|
-
/*! @azure/msal-common v15.
|
|
928
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
953
929
|
/* eslint-disable header/header */
|
|
954
930
|
const name$1 = "@azure/msal-common";
|
|
955
|
-
const version$1 = "15.
|
|
931
|
+
const version$1 = "15.4.0";
|
|
956
932
|
|
|
957
|
-
/*! @azure/msal-common v15.
|
|
933
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
958
934
|
/*
|
|
959
935
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
960
936
|
* Licensed under the MIT License.
|
|
@@ -974,7 +950,7 @@
|
|
|
974
950
|
AzureUsGovernment: "https://login.microsoftonline.us",
|
|
975
951
|
};
|
|
976
952
|
|
|
977
|
-
/*! @azure/msal-common v15.
|
|
953
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
978
954
|
|
|
979
955
|
/*
|
|
980
956
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -1035,7 +1011,7 @@
|
|
|
1035
1011
|
}
|
|
1036
1012
|
}
|
|
1037
1013
|
|
|
1038
|
-
/*! @azure/msal-common v15.
|
|
1014
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
1039
1015
|
/*
|
|
1040
1016
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
1041
1017
|
* Licensed under the MIT License.
|
|
@@ -1090,7 +1066,7 @@
|
|
|
1090
1066
|
return cachedAtSec > nowSeconds();
|
|
1091
1067
|
}
|
|
1092
1068
|
|
|
1093
|
-
/*! @azure/msal-common v15.
|
|
1069
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
1094
1070
|
|
|
1095
1071
|
/*
|
|
1096
1072
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -1417,7 +1393,7 @@
|
|
|
1417
1393
|
return metadata.expiresAt <= nowSeconds();
|
|
1418
1394
|
}
|
|
1419
1395
|
|
|
1420
|
-
/*! @azure/msal-common v15.
|
|
1396
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
1421
1397
|
/*
|
|
1422
1398
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
1423
1399
|
* Licensed under the MIT License.
|
|
@@ -1471,7 +1447,7 @@
|
|
|
1471
1447
|
urlParseError: urlParseError
|
|
1472
1448
|
});
|
|
1473
1449
|
|
|
1474
|
-
/*! @azure/msal-common v15.
|
|
1450
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
1475
1451
|
|
|
1476
1452
|
/*
|
|
1477
1453
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -1609,7 +1585,7 @@
|
|
|
1609
1585
|
return new ClientConfigurationError(errorCode);
|
|
1610
1586
|
}
|
|
1611
1587
|
|
|
1612
|
-
/*! @azure/msal-common v15.
|
|
1588
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
1613
1589
|
/*
|
|
1614
1590
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
1615
1591
|
* Licensed under the MIT License.
|
|
@@ -1706,7 +1682,7 @@
|
|
|
1706
1682
|
}
|
|
1707
1683
|
}
|
|
1708
1684
|
|
|
1709
|
-
/*! @azure/msal-common v15.
|
|
1685
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
1710
1686
|
|
|
1711
1687
|
/*
|
|
1712
1688
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -1897,7 +1873,7 @@
|
|
|
1897
1873
|
}
|
|
1898
1874
|
}
|
|
1899
1875
|
|
|
1900
|
-
/*! @azure/msal-common v15.
|
|
1876
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
1901
1877
|
|
|
1902
1878
|
/*
|
|
1903
1879
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -1937,7 +1913,7 @@
|
|
|
1937
1913
|
};
|
|
1938
1914
|
}
|
|
1939
1915
|
|
|
1940
|
-
/*! @azure/msal-common v15.
|
|
1916
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
1941
1917
|
/*
|
|
1942
1918
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
1943
1919
|
* Licensed under the MIT License.
|
|
@@ -2016,7 +1992,7 @@
|
|
|
2016
1992
|
return updatedAccountInfo;
|
|
2017
1993
|
}
|
|
2018
1994
|
|
|
2019
|
-
/*! @azure/msal-common v15.
|
|
1995
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
2020
1996
|
/*
|
|
2021
1997
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2022
1998
|
* Licensed under the MIT License.
|
|
@@ -2031,7 +2007,7 @@
|
|
|
2031
2007
|
Ciam: 3,
|
|
2032
2008
|
};
|
|
2033
2009
|
|
|
2034
|
-
/*! @azure/msal-common v15.
|
|
2010
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
2035
2011
|
/*
|
|
2036
2012
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2037
2013
|
* Licensed under the MIT License.
|
|
@@ -2053,7 +2029,7 @@
|
|
|
2053
2029
|
return null;
|
|
2054
2030
|
}
|
|
2055
2031
|
|
|
2056
|
-
/*! @azure/msal-common v15.
|
|
2032
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
2057
2033
|
/*
|
|
2058
2034
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2059
2035
|
* Licensed under the MIT License.
|
|
@@ -2062,11 +2038,22 @@
|
|
|
2062
2038
|
* Protocol modes supported by MSAL.
|
|
2063
2039
|
*/
|
|
2064
2040
|
const ProtocolMode = {
|
|
2041
|
+
/**
|
|
2042
|
+
* Auth Code + PKCE with Entra ID (formerly AAD) specific optimizations and features
|
|
2043
|
+
*/
|
|
2065
2044
|
AAD: "AAD",
|
|
2045
|
+
/**
|
|
2046
|
+
* Auth Code + PKCE without Entra ID specific optimizations and features. For use only with non-Microsoft owned authorities.
|
|
2047
|
+
* Support is limited for this mode.
|
|
2048
|
+
*/
|
|
2066
2049
|
OIDC: "OIDC",
|
|
2050
|
+
/**
|
|
2051
|
+
* Encrypted Authorize Response (EAR) with Entra ID specific optimizations and features
|
|
2052
|
+
*/
|
|
2053
|
+
EAR: "EAR",
|
|
2067
2054
|
};
|
|
2068
2055
|
|
|
2069
|
-
/*! @azure/msal-common v15.
|
|
2056
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
2070
2057
|
|
|
2071
2058
|
/*
|
|
2072
2059
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -2162,11 +2149,11 @@
|
|
|
2162
2149
|
if (authority.authorityType === AuthorityType.Adfs) {
|
|
2163
2150
|
account.authorityType = CacheAccountType.ADFS_ACCOUNT_TYPE;
|
|
2164
2151
|
}
|
|
2165
|
-
else if (authority.protocolMode === ProtocolMode.
|
|
2166
|
-
account.authorityType = CacheAccountType.
|
|
2152
|
+
else if (authority.protocolMode === ProtocolMode.OIDC) {
|
|
2153
|
+
account.authorityType = CacheAccountType.GENERIC_ACCOUNT_TYPE;
|
|
2167
2154
|
}
|
|
2168
2155
|
else {
|
|
2169
|
-
account.authorityType = CacheAccountType.
|
|
2156
|
+
account.authorityType = CacheAccountType.MSSTS_ACCOUNT_TYPE;
|
|
2170
2157
|
}
|
|
2171
2158
|
let clientInfo;
|
|
2172
2159
|
if (accountDetails.clientInfo && base64Decode) {
|
|
@@ -2309,7 +2296,7 @@
|
|
|
2309
2296
|
}
|
|
2310
2297
|
}
|
|
2311
2298
|
|
|
2312
|
-
/*! @azure/msal-common v15.
|
|
2299
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
2313
2300
|
|
|
2314
2301
|
/*
|
|
2315
2302
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -2344,6 +2331,7 @@
|
|
|
2344
2331
|
const deserializedHash = Object.fromEntries(new URLSearchParams(normalizedResponse));
|
|
2345
2332
|
// Check for known response properties
|
|
2346
2333
|
if (deserializedHash.code ||
|
|
2334
|
+
deserializedHash.ear_jwe ||
|
|
2347
2335
|
deserializedHash.error ||
|
|
2348
2336
|
deserializedHash.error_description ||
|
|
2349
2337
|
deserializedHash.state) {
|
|
@@ -2366,7 +2354,7 @@
|
|
|
2366
2354
|
return queryParameterArray.join("&");
|
|
2367
2355
|
}
|
|
2368
2356
|
|
|
2369
|
-
/*! @azure/msal-common v15.
|
|
2357
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
2370
2358
|
|
|
2371
2359
|
/*
|
|
2372
2360
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -2530,7 +2518,7 @@
|
|
|
2530
2518
|
}
|
|
2531
2519
|
}
|
|
2532
2520
|
|
|
2533
|
-
/*! @azure/msal-common v15.
|
|
2521
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
2534
2522
|
|
|
2535
2523
|
/*
|
|
2536
2524
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -2561,7 +2549,6 @@
|
|
|
2561
2549
|
},
|
|
2562
2550
|
},
|
|
2563
2551
|
instanceDiscoveryMetadata: {
|
|
2564
|
-
tenant_discovery_endpoint: "https://{canonicalAuthority}/v2.0/.well-known/openid-configuration",
|
|
2565
2552
|
metadata: [
|
|
2566
2553
|
{
|
|
2567
2554
|
preferred_network: "login.microsoftonline.com",
|
|
@@ -2670,7 +2657,7 @@
|
|
|
2670
2657
|
return null;
|
|
2671
2658
|
}
|
|
2672
2659
|
|
|
2673
|
-
/*! @azure/msal-common v15.
|
|
2660
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
2674
2661
|
/*
|
|
2675
2662
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2676
2663
|
* Licensed under the MIT License.
|
|
@@ -2678,7 +2665,7 @@
|
|
|
2678
2665
|
const cacheQuotaExceededErrorCode = "cache_quota_exceeded";
|
|
2679
2666
|
const cacheUnknownErrorCode = "cache_error_unknown";
|
|
2680
2667
|
|
|
2681
|
-
/*! @azure/msal-common v15.
|
|
2668
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
2682
2669
|
|
|
2683
2670
|
/*
|
|
2684
2671
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -2705,7 +2692,7 @@
|
|
|
2705
2692
|
}
|
|
2706
2693
|
}
|
|
2707
2694
|
|
|
2708
|
-
/*! @azure/msal-common v15.
|
|
2695
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
2709
2696
|
|
|
2710
2697
|
/*
|
|
2711
2698
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -3890,7 +3877,7 @@
|
|
|
3890
3877
|
}
|
|
3891
3878
|
}
|
|
3892
3879
|
|
|
3893
|
-
/*! @azure/msal-common v15.
|
|
3880
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
3894
3881
|
|
|
3895
3882
|
/*
|
|
3896
3883
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -3989,7 +3976,7 @@
|
|
|
3989
3976
|
return (config.authOptions.authority.options.protocolMode === ProtocolMode.OIDC);
|
|
3990
3977
|
}
|
|
3991
3978
|
|
|
3992
|
-
/*! @azure/msal-common v15.
|
|
3979
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
3993
3980
|
/*
|
|
3994
3981
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3995
3982
|
* Licensed under the MIT License.
|
|
@@ -3999,7 +3986,7 @@
|
|
|
3999
3986
|
UPN: "UPN",
|
|
4000
3987
|
};
|
|
4001
3988
|
|
|
4002
|
-
/*! @azure/msal-common v15.
|
|
3989
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
4003
3990
|
/*
|
|
4004
3991
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4005
3992
|
* Licensed under the MIT License.
|
|
@@ -4045,9 +4032,11 @@
|
|
|
4045
4032
|
const X_CLIENT_EXTRA_SKU = "x-client-xtra-sku";
|
|
4046
4033
|
const BROKER_CLIENT_ID = "brk_client_id";
|
|
4047
4034
|
const BROKER_REDIRECT_URI = "brk_redirect_uri";
|
|
4048
|
-
const INSTANCE_AWARE = "instance_aware";
|
|
4035
|
+
const INSTANCE_AWARE = "instance_aware";
|
|
4036
|
+
const EAR_JWK = "ear_jwk";
|
|
4037
|
+
const EAR_JWE_CRYPTO = "ear_jwe_crypto";
|
|
4049
4038
|
|
|
4050
|
-
/*! @azure/msal-common v15.
|
|
4039
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
4051
4040
|
|
|
4052
4041
|
/*
|
|
4053
4042
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -4066,10 +4055,12 @@
|
|
|
4066
4055
|
}
|
|
4067
4056
|
}
|
|
4068
4057
|
/**
|
|
4069
|
-
*
|
|
4058
|
+
* Add the given response_type
|
|
4059
|
+
* @param parameters
|
|
4060
|
+
* @param responseType
|
|
4070
4061
|
*/
|
|
4071
|
-
function
|
|
4072
|
-
parameters.set(RESPONSE_TYPE,
|
|
4062
|
+
function addResponseType(parameters, responseType) {
|
|
4063
|
+
parameters.set(RESPONSE_TYPE, responseType);
|
|
4073
4064
|
}
|
|
4074
4065
|
/**
|
|
4075
4066
|
* add response_mode. defaults to query.
|
|
@@ -4400,9 +4391,20 @@
|
|
|
4400
4391
|
if (!parameters.has(BROKER_REDIRECT_URI)) {
|
|
4401
4392
|
parameters.set(BROKER_REDIRECT_URI, brokerRedirectUri);
|
|
4402
4393
|
}
|
|
4394
|
+
}
|
|
4395
|
+
/**
|
|
4396
|
+
* Add EAR (Encrypted Authorize Response) request parameters
|
|
4397
|
+
* @param parameters
|
|
4398
|
+
* @param jwk
|
|
4399
|
+
*/
|
|
4400
|
+
function addEARParameters(parameters, jwk) {
|
|
4401
|
+
parameters.set(EAR_JWK, encodeURIComponent(jwk));
|
|
4402
|
+
// ear_jwe_crypto will always have value: {"alg":"dir","enc":"A256GCM"} so we can hardcode this
|
|
4403
|
+
const jweCryptoB64Encoded = "eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0";
|
|
4404
|
+
parameters.set(EAR_JWE_CRYPTO, jweCryptoB64Encoded);
|
|
4403
4405
|
}
|
|
4404
4406
|
|
|
4405
|
-
/*! @azure/msal-common v15.
|
|
4407
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
4406
4408
|
/*
|
|
4407
4409
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4408
4410
|
* Licensed under the MIT License.
|
|
@@ -4414,7 +4416,7 @@
|
|
|
4414
4416
|
response.hasOwnProperty("jwks_uri"));
|
|
4415
4417
|
}
|
|
4416
4418
|
|
|
4417
|
-
/*! @azure/msal-common v15.
|
|
4419
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
4418
4420
|
/*
|
|
4419
4421
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4420
4422
|
* Licensed under the MIT License.
|
|
@@ -4424,7 +4426,7 @@
|
|
|
4424
4426
|
response.hasOwnProperty("metadata"));
|
|
4425
4427
|
}
|
|
4426
4428
|
|
|
4427
|
-
/*! @azure/msal-common v15.
|
|
4429
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
4428
4430
|
/*
|
|
4429
4431
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4430
4432
|
* Licensed under the MIT License.
|
|
@@ -4434,7 +4436,7 @@
|
|
|
4434
4436
|
response.hasOwnProperty("error_description"));
|
|
4435
4437
|
}
|
|
4436
4438
|
|
|
4437
|
-
/*! @azure/msal-common v15.
|
|
4439
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
4438
4440
|
/*
|
|
4439
4441
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4440
4442
|
* Licensed under the MIT License.
|
|
@@ -4620,6 +4622,9 @@
|
|
|
4620
4622
|
*/
|
|
4621
4623
|
HandleCodeResponseFromServer: "handleCodeResponseFromServer",
|
|
4622
4624
|
HandleCodeResponse: "handleCodeResponse",
|
|
4625
|
+
HandleResponseEar: "handleResponseEar",
|
|
4626
|
+
HandleResponsePlatformBroker: "handleResponsePlatformBroker",
|
|
4627
|
+
HandleResponseCode: "handleResponseCode",
|
|
4623
4628
|
UpdateTokenEndpointAuthority: "updateTokenEndpointAuthority",
|
|
4624
4629
|
/**
|
|
4625
4630
|
* APIs in Authorization Code Client (msal-common)
|
|
@@ -4686,6 +4691,8 @@
|
|
|
4686
4691
|
UrlEncodeArr: "urlEncodeArr",
|
|
4687
4692
|
Encrypt: "encrypt",
|
|
4688
4693
|
Decrypt: "decrypt",
|
|
4694
|
+
GenerateEarKey: "generateEarKey",
|
|
4695
|
+
DecryptEarResponse: "decryptEarResponse",
|
|
4689
4696
|
};
|
|
4690
4697
|
const PerformanceEventAbbreviations = new Map([
|
|
4691
4698
|
[PerformanceEvents.AcquireTokenByCode, "ATByCode"],
|
|
@@ -4803,6 +4810,12 @@
|
|
|
4803
4810
|
"HandleCodeResFromServer",
|
|
4804
4811
|
],
|
|
4805
4812
|
[PerformanceEvents.HandleCodeResponse, "HandleCodeResp"],
|
|
4813
|
+
[PerformanceEvents.HandleResponseEar, "HandleRespEar"],
|
|
4814
|
+
[PerformanceEvents.HandleResponseCode, "HandleRespCode"],
|
|
4815
|
+
[
|
|
4816
|
+
PerformanceEvents.HandleResponsePlatformBroker,
|
|
4817
|
+
"HandleRespPlatBroker",
|
|
4818
|
+
],
|
|
4806
4819
|
[PerformanceEvents.UpdateTokenEndpointAuthority, "UpdTEndpointAuth"],
|
|
4807
4820
|
[PerformanceEvents.AuthClientAcquireToken, "AuthClientAT"],
|
|
4808
4821
|
[PerformanceEvents.AuthClientExecuteTokenRequest, "AuthClientExecTReq"],
|
|
@@ -4905,6 +4918,8 @@
|
|
|
4905
4918
|
[PerformanceEvents.UrlEncodeArr, "urlEncArr"],
|
|
4906
4919
|
[PerformanceEvents.Encrypt, "encrypt"],
|
|
4907
4920
|
[PerformanceEvents.Decrypt, "decrypt"],
|
|
4921
|
+
[PerformanceEvents.GenerateEarKey, "genEarKey"],
|
|
4922
|
+
[PerformanceEvents.DecryptEarResponse, "decryptEarResp"],
|
|
4908
4923
|
]);
|
|
4909
4924
|
/**
|
|
4910
4925
|
* State of the performance event.
|
|
@@ -4913,7 +4928,6 @@
|
|
|
4913
4928
|
* @enum {number}
|
|
4914
4929
|
*/
|
|
4915
4930
|
const PerformanceEventStatus = {
|
|
4916
|
-
NotStarted: 0,
|
|
4917
4931
|
InProgress: 1,
|
|
4918
4932
|
Completed: 2,
|
|
4919
4933
|
};
|
|
@@ -4934,7 +4948,7 @@
|
|
|
4934
4948
|
"encryptedCacheExpiredCount",
|
|
4935
4949
|
]);
|
|
4936
4950
|
|
|
4937
|
-
/*! @azure/msal-common v15.
|
|
4951
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
4938
4952
|
/*
|
|
4939
4953
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4940
4954
|
* Licensed under the MIT License.
|
|
@@ -5030,7 +5044,7 @@
|
|
|
5030
5044
|
};
|
|
5031
5045
|
};
|
|
5032
5046
|
|
|
5033
|
-
/*! @azure/msal-common v15.
|
|
5047
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
5034
5048
|
|
|
5035
5049
|
/*
|
|
5036
5050
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -5139,7 +5153,7 @@
|
|
|
5139
5153
|
},
|
|
5140
5154
|
};
|
|
5141
5155
|
|
|
5142
|
-
/*! @azure/msal-common v15.
|
|
5156
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
5143
5157
|
|
|
5144
5158
|
/*
|
|
5145
5159
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -5317,7 +5331,7 @@
|
|
|
5317
5331
|
return (authorityUri.PathSegments.length === 1 &&
|
|
5318
5332
|
!Authority.reservedTenantDomains.has(authorityUri.PathSegments[0]) &&
|
|
5319
5333
|
this.getAuthorityType(authorityUri) === AuthorityType.Default &&
|
|
5320
|
-
this.protocolMode
|
|
5334
|
+
this.protocolMode !== ProtocolMode.OIDC);
|
|
5321
5335
|
}
|
|
5322
5336
|
/**
|
|
5323
5337
|
* Replaces tenant in url path with current tenant. Defaults to common.
|
|
@@ -5364,7 +5378,7 @@
|
|
|
5364
5378
|
const canonicalAuthorityHost = this.hostnameAndPort;
|
|
5365
5379
|
if (this.canonicalAuthority.endsWith("v2.0/") ||
|
|
5366
5380
|
this.authorityType === AuthorityType.Adfs ||
|
|
5367
|
-
(this.protocolMode
|
|
5381
|
+
(this.protocolMode === ProtocolMode.OIDC &&
|
|
5368
5382
|
!this.isAliasOfKnownMicrosoftAuthority(canonicalAuthorityHost))) {
|
|
5369
5383
|
return `${this.canonicalAuthority}.well-known/openid-configuration`;
|
|
5370
5384
|
}
|
|
@@ -5978,7 +5992,7 @@
|
|
|
5978
5992
|
};
|
|
5979
5993
|
}
|
|
5980
5994
|
|
|
5981
|
-
/*! @azure/msal-common v15.
|
|
5995
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
5982
5996
|
|
|
5983
5997
|
/*
|
|
5984
5998
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -6009,7 +6023,7 @@
|
|
|
6009
6023
|
}
|
|
6010
6024
|
}
|
|
6011
6025
|
|
|
6012
|
-
/*! @azure/msal-common v15.
|
|
6026
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
6013
6027
|
|
|
6014
6028
|
/*
|
|
6015
6029
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -6028,7 +6042,7 @@
|
|
|
6028
6042
|
}
|
|
6029
6043
|
}
|
|
6030
6044
|
|
|
6031
|
-
/*! @azure/msal-common v15.
|
|
6045
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
6032
6046
|
/*
|
|
6033
6047
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
6034
6048
|
* Licensed under the MIT License.
|
|
@@ -6049,7 +6063,7 @@
|
|
|
6049
6063
|
};
|
|
6050
6064
|
}
|
|
6051
6065
|
|
|
6052
|
-
/*! @azure/msal-common v15.
|
|
6066
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
6053
6067
|
|
|
6054
6068
|
/*
|
|
6055
6069
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -6136,7 +6150,7 @@
|
|
|
6136
6150
|
}
|
|
6137
6151
|
}
|
|
6138
6152
|
|
|
6139
|
-
/*! @azure/msal-common v15.
|
|
6153
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
6140
6154
|
|
|
6141
6155
|
/*
|
|
6142
6156
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -6166,7 +6180,7 @@
|
|
|
6166
6180
|
return new NetworkError(error, httpStatus, responseHeaders);
|
|
6167
6181
|
}
|
|
6168
6182
|
|
|
6169
|
-
/*! @azure/msal-common v15.
|
|
6183
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
6170
6184
|
|
|
6171
6185
|
/*
|
|
6172
6186
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -6314,7 +6328,7 @@
|
|
|
6314
6328
|
}
|
|
6315
6329
|
}
|
|
6316
6330
|
|
|
6317
|
-
/*! @azure/msal-common v15.
|
|
6331
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
6318
6332
|
/*
|
|
6319
6333
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
6320
6334
|
* Licensed under the MIT License.
|
|
@@ -6340,7 +6354,7 @@
|
|
|
6340
6354
|
refreshTokenExpired: refreshTokenExpired
|
|
6341
6355
|
});
|
|
6342
6356
|
|
|
6343
|
-
/*! @azure/msal-common v15.
|
|
6357
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
6344
6358
|
|
|
6345
6359
|
/*
|
|
6346
6360
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -6428,7 +6442,7 @@
|
|
|
6428
6442
|
return new InteractionRequiredAuthError(errorCode, InteractionRequiredAuthErrorMessages[errorCode]);
|
|
6429
6443
|
}
|
|
6430
6444
|
|
|
6431
|
-
/*! @azure/msal-common v15.
|
|
6445
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
6432
6446
|
|
|
6433
6447
|
/*
|
|
6434
6448
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -6500,16 +6514,14 @@
|
|
|
6500
6514
|
}
|
|
6501
6515
|
}
|
|
6502
6516
|
|
|
6503
|
-
/*! @azure/msal-common v15.
|
|
6517
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
6504
6518
|
|
|
6505
6519
|
/*
|
|
6506
6520
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
6507
6521
|
* Licensed under the MIT License.
|
|
6508
6522
|
*/
|
|
6509
6523
|
const KeyLocation = {
|
|
6510
|
-
SW: "sw"
|
|
6511
|
-
UHW: "uhw",
|
|
6512
|
-
};
|
|
6524
|
+
SW: "sw"};
|
|
6513
6525
|
/** @internal */
|
|
6514
6526
|
class PopTokenGenerator {
|
|
6515
6527
|
constructor(cryptoUtils, performanceClient) {
|
|
@@ -6584,7 +6596,7 @@
|
|
|
6584
6596
|
}
|
|
6585
6597
|
}
|
|
6586
6598
|
|
|
6587
|
-
/*! @azure/msal-common v15.
|
|
6599
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
6588
6600
|
/*
|
|
6589
6601
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
6590
6602
|
* Licensed under the MIT License.
|
|
@@ -6611,7 +6623,7 @@
|
|
|
6611
6623
|
}
|
|
6612
6624
|
}
|
|
6613
6625
|
|
|
6614
|
-
/*! @azure/msal-common v15.
|
|
6626
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
6615
6627
|
|
|
6616
6628
|
/*
|
|
6617
6629
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -6942,7 +6954,7 @@
|
|
|
6942
6954
|
return baseAccount;
|
|
6943
6955
|
}
|
|
6944
6956
|
|
|
6945
|
-
/*! @azure/msal-common v15.
|
|
6957
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
6946
6958
|
|
|
6947
6959
|
/*
|
|
6948
6960
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -7009,7 +7021,7 @@
|
|
|
7009
7021
|
}
|
|
7010
7022
|
}
|
|
7011
7023
|
|
|
7012
|
-
/*! @azure/msal-common v15.
|
|
7024
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
7013
7025
|
/*
|
|
7014
7026
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
7015
7027
|
* Licensed under the MIT License.
|
|
@@ -7027,7 +7039,7 @@
|
|
|
7027
7039
|
}
|
|
7028
7040
|
}
|
|
7029
7041
|
|
|
7030
|
-
/*! @azure/msal-common v15.
|
|
7042
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
7031
7043
|
|
|
7032
7044
|
/*
|
|
7033
7045
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -7260,7 +7272,7 @@
|
|
|
7260
7272
|
}
|
|
7261
7273
|
}
|
|
7262
7274
|
|
|
7263
|
-
/*! @azure/msal-common v15.
|
|
7275
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
7264
7276
|
|
|
7265
7277
|
/*
|
|
7266
7278
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -7469,7 +7481,7 @@
|
|
|
7469
7481
|
}
|
|
7470
7482
|
}
|
|
7471
7483
|
|
|
7472
|
-
/*! @azure/msal-common v15.
|
|
7484
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
7473
7485
|
|
|
7474
7486
|
/*
|
|
7475
7487
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -7567,7 +7579,7 @@
|
|
|
7567
7579
|
}
|
|
7568
7580
|
}
|
|
7569
7581
|
|
|
7570
|
-
/*! @azure/msal-common v15.
|
|
7582
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
7571
7583
|
|
|
7572
7584
|
/*
|
|
7573
7585
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -7582,7 +7594,7 @@
|
|
|
7582
7594
|
},
|
|
7583
7595
|
};
|
|
7584
7596
|
|
|
7585
|
-
/*! @azure/msal-common v15.
|
|
7597
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
7586
7598
|
|
|
7587
7599
|
/*
|
|
7588
7600
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -7711,10 +7723,10 @@
|
|
|
7711
7723
|
if (request.embeddedClientId) {
|
|
7712
7724
|
addBrokerParameters(parameters, authOptions.clientId, authOptions.redirectUri);
|
|
7713
7725
|
}
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
|
|
7726
|
+
// If extraQueryParameters includes instance_aware its value will be added when extraQueryParameters are added
|
|
7727
|
+
if (authOptions.instanceAware &&
|
|
7728
|
+
(!request.extraQueryParameters ||
|
|
7729
|
+
!Object.keys(request.extraQueryParameters).includes(INSTANCE_AWARE))) {
|
|
7718
7730
|
addInstanceAware(parameters);
|
|
7719
7731
|
}
|
|
7720
7732
|
return parameters;
|
|
@@ -7806,7 +7818,7 @@
|
|
|
7806
7818
|
return account.idTokenClaims?.login_hint || null;
|
|
7807
7819
|
}
|
|
7808
7820
|
|
|
7809
|
-
/*! @azure/msal-common v15.
|
|
7821
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
7810
7822
|
|
|
7811
7823
|
/*
|
|
7812
7824
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -7864,7 +7876,7 @@
|
|
|
7864
7876
|
}
|
|
7865
7877
|
}
|
|
7866
7878
|
|
|
7867
|
-
/*! @azure/msal-common v15.
|
|
7879
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
7868
7880
|
|
|
7869
7881
|
/*
|
|
7870
7882
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -8127,7 +8139,7 @@
|
|
|
8127
8139
|
}
|
|
8128
8140
|
}
|
|
8129
8141
|
|
|
8130
|
-
/*! @azure/msal-common v15.
|
|
8142
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
8131
8143
|
/*
|
|
8132
8144
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
8133
8145
|
* Licensed under the MIT License.
|
|
@@ -8135,7 +8147,7 @@
|
|
|
8135
8147
|
const missingKidError = "missing_kid_error";
|
|
8136
8148
|
const missingAlgError = "missing_alg_error";
|
|
8137
8149
|
|
|
8138
|
-
/*! @azure/msal-common v15.
|
|
8150
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
8139
8151
|
|
|
8140
8152
|
/*
|
|
8141
8153
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -8160,7 +8172,7 @@
|
|
|
8160
8172
|
return new JoseHeaderError(code, JoseHeaderErrorMessages[code]);
|
|
8161
8173
|
}
|
|
8162
8174
|
|
|
8163
|
-
/*! @azure/msal-common v15.
|
|
8175
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
8164
8176
|
|
|
8165
8177
|
/*
|
|
8166
8178
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -8200,7 +8212,7 @@
|
|
|
8200
8212
|
}
|
|
8201
8213
|
}
|
|
8202
8214
|
|
|
8203
|
-
/*! @azure/msal-common v15.
|
|
8215
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
8204
8216
|
|
|
8205
8217
|
/*
|
|
8206
8218
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -8279,7 +8291,7 @@
|
|
|
8279
8291
|
}
|
|
8280
8292
|
}
|
|
8281
8293
|
|
|
8282
|
-
/*! @azure/msal-common v15.
|
|
8294
|
+
/*! @azure/msal-common v15.4.0 2025-03-26 */
|
|
8283
8295
|
|
|
8284
8296
|
/*
|
|
8285
8297
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -8893,6 +8905,8 @@
|
|
|
8893
8905
|
* Licensed under the MIT License.
|
|
8894
8906
|
*/
|
|
8895
8907
|
const pkceNotCreated = "pkce_not_created";
|
|
8908
|
+
const earJwkEmpty = "ear_jwk_empty";
|
|
8909
|
+
const earJweEmpty = "ear_jwe_empty";
|
|
8896
8910
|
const cryptoNonExistent = "crypto_nonexistent";
|
|
8897
8911
|
const emptyNavigateUri = "empty_navigate_uri";
|
|
8898
8912
|
const hashEmptyError = "hash_empty_error";
|
|
@@ -8915,7 +8929,6 @@
|
|
|
8915
8929
|
const silentPromptValueError = "silent_prompt_value_error";
|
|
8916
8930
|
const noTokenRequestCacheError = "no_token_request_cache_error";
|
|
8917
8931
|
const unableToParseTokenRequestCacheError = "unable_to_parse_token_request_cache_error";
|
|
8918
|
-
const noCachedAuthorityError = "no_cached_authority_error";
|
|
8919
8932
|
const authRequestNotSetError = "auth_request_not_set_error";
|
|
8920
8933
|
const invalidCacheType = "invalid_cache_type";
|
|
8921
8934
|
const nonBrowserEnvironment = "non_browser_environment";
|
|
@@ -8939,7 +8952,8 @@
|
|
|
8939
8952
|
const invalidBase64String = "invalid_base64_string";
|
|
8940
8953
|
const invalidPopTokenRequest = "invalid_pop_token_request";
|
|
8941
8954
|
const failedToBuildHeaders = "failed_to_build_headers";
|
|
8942
|
-
const failedToParseHeaders = "failed_to_parse_headers";
|
|
8955
|
+
const failedToParseHeaders = "failed_to_parse_headers";
|
|
8956
|
+
const failedToDecryptEarResponse = "failed_to_decrypt_ear_response";
|
|
8943
8957
|
|
|
8944
8958
|
var BrowserAuthErrorCodes = /*#__PURE__*/Object.freeze({
|
|
8945
8959
|
__proto__: null,
|
|
@@ -8952,9 +8966,12 @@
|
|
|
8952
8966
|
cryptoNonExistent: cryptoNonExistent,
|
|
8953
8967
|
databaseNotOpen: databaseNotOpen,
|
|
8954
8968
|
databaseUnavailable: databaseUnavailable,
|
|
8969
|
+
earJweEmpty: earJweEmpty,
|
|
8970
|
+
earJwkEmpty: earJwkEmpty,
|
|
8955
8971
|
emptyNavigateUri: emptyNavigateUri,
|
|
8956
8972
|
emptyWindowError: emptyWindowError,
|
|
8957
8973
|
failedToBuildHeaders: failedToBuildHeaders,
|
|
8974
|
+
failedToDecryptEarResponse: failedToDecryptEarResponse,
|
|
8958
8975
|
failedToParseHeaders: failedToParseHeaders,
|
|
8959
8976
|
failedToParseResponse: failedToParseResponse,
|
|
8960
8977
|
getRequestFailed: getRequestFailed,
|
|
@@ -8972,7 +8989,6 @@
|
|
|
8972
8989
|
nativeHandshakeTimeout: nativeHandshakeTimeout,
|
|
8973
8990
|
nativePromptNotSupported: nativePromptNotSupported,
|
|
8974
8991
|
noAccountError: noAccountError,
|
|
8975
|
-
noCachedAuthorityError: noCachedAuthorityError,
|
|
8976
8992
|
noNetworkConnectivity: noNetworkConnectivity,
|
|
8977
8993
|
noStateInHash: noStateInHash,
|
|
8978
8994
|
noTokenRequestCacheError: noTokenRequestCacheError,
|
|
@@ -9003,6 +9019,8 @@
|
|
|
9003
9019
|
*/
|
|
9004
9020
|
const BrowserAuthErrorMessages = {
|
|
9005
9021
|
[pkceNotCreated]: "The PKCE code challenge and verifier could not be generated.",
|
|
9022
|
+
[earJwkEmpty]: "No EAR encryption key provided. This is unexpected.",
|
|
9023
|
+
[earJweEmpty]: "Server response does not contain ear_jwe property. This is unexpected.",
|
|
9006
9024
|
[cryptoNonExistent]: "The crypto object or function is not available.",
|
|
9007
9025
|
[emptyNavigateUri]: "Navigation URI is empty. Please check stack trace for more info.",
|
|
9008
9026
|
[hashEmptyError]: `Hash value cannot be processed because it is empty. Please verify that your redirectUri is not clearing the hash. ${ErrorLink}`,
|
|
@@ -9025,7 +9043,6 @@
|
|
|
9025
9043
|
[silentPromptValueError]: "The value given for the prompt value is not valid for silent requests - must be set to 'none' or 'no_session'.",
|
|
9026
9044
|
[noTokenRequestCacheError]: "No token request found in cache.",
|
|
9027
9045
|
[unableToParseTokenRequestCacheError]: "The cached token request could not be parsed.",
|
|
9028
|
-
[noCachedAuthorityError]: "No cached authority found.",
|
|
9029
9046
|
[authRequestNotSetError]: "Auth Request not set. Please ensure initiateAuthRequest was called from the InteractionHandler",
|
|
9030
9047
|
[invalidCacheType]: "Invalid cache type",
|
|
9031
9048
|
[nonBrowserEnvironment]: "Login and token requests are not supported in non-browser environments.",
|
|
@@ -9050,6 +9067,7 @@
|
|
|
9050
9067
|
[invalidPopTokenRequest]: "Invalid PoP token request. The request should not have both a popKid value and signPopToken set to true.",
|
|
9051
9068
|
[failedToBuildHeaders]: "Failed to build request headers object.",
|
|
9052
9069
|
[failedToParseHeaders]: "Failed to parse response headers",
|
|
9070
|
+
[failedToDecryptEarResponse]: "Failed to decrypt ear response",
|
|
9053
9071
|
};
|
|
9054
9072
|
/**
|
|
9055
9073
|
* BrowserAuthErrorMessage class containing string constants used by error codes and messages.
|
|
@@ -9152,10 +9170,6 @@
|
|
|
9152
9170
|
code: unableToParseTokenRequestCacheError,
|
|
9153
9171
|
desc: BrowserAuthErrorMessages[unableToParseTokenRequestCacheError],
|
|
9154
9172
|
},
|
|
9155
|
-
noCachedAuthorityError: {
|
|
9156
|
-
code: noCachedAuthorityError,
|
|
9157
|
-
desc: BrowserAuthErrorMessages[noCachedAuthorityError],
|
|
9158
|
-
},
|
|
9159
9173
|
authRequestNotSet: {
|
|
9160
9174
|
code: authRequestNotSetError,
|
|
9161
9175
|
desc: BrowserAuthErrorMessages[authRequestNotSetError],
|
|
@@ -9267,10 +9281,6 @@
|
|
|
9267
9281
|
* Constants
|
|
9268
9282
|
*/
|
|
9269
9283
|
const BrowserConstants = {
|
|
9270
|
-
/**
|
|
9271
|
-
* Interaction in progress cache value
|
|
9272
|
-
*/
|
|
9273
|
-
INTERACTION_IN_PROGRESS_VALUE: "interaction_in_progress",
|
|
9274
9284
|
/**
|
|
9275
9285
|
* Invalid grant error code
|
|
9276
9286
|
*/
|
|
@@ -9323,21 +9333,12 @@
|
|
|
9323
9333
|
* Temporary cache keys for MSAL, deleted after any request.
|
|
9324
9334
|
*/
|
|
9325
9335
|
const TemporaryCacheKeys = {
|
|
9326
|
-
AUTHORITY: "authority",
|
|
9327
|
-
ACQUIRE_TOKEN_ACCOUNT: "acquireToken.account",
|
|
9328
|
-
SESSION_STATE: "session.state",
|
|
9329
|
-
REQUEST_STATE: "request.state",
|
|
9330
|
-
NONCE_IDTOKEN: "nonce.id_token",
|
|
9331
9336
|
ORIGIN_URI: "request.origin",
|
|
9332
|
-
RENEW_STATUS: "token.renew.status",
|
|
9333
9337
|
URL_HASH: "urlHash",
|
|
9334
9338
|
REQUEST_PARAMS: "request.params",
|
|
9335
|
-
|
|
9339
|
+
VERIFIER: "code.verifier",
|
|
9336
9340
|
INTERACTION_STATUS_KEY: "interaction.status",
|
|
9337
|
-
CCS_CREDENTIAL: "ccs.credential",
|
|
9338
|
-
CORRELATION_ID: "request.correlationId",
|
|
9339
9341
|
NATIVE_REQUEST: "request.native",
|
|
9340
|
-
REDIRECT_CONTEXT: "request.redirect.context",
|
|
9341
9342
|
};
|
|
9342
9343
|
const StaticCacheKeys = {
|
|
9343
9344
|
ACCOUNT_KEYS: "msal.account.keys",
|
|
@@ -9707,6 +9708,69 @@
|
|
|
9707
9708
|
async function sign(key, data) {
|
|
9708
9709
|
return window.crypto.subtle.sign(keygenAlgorithmOptions, key, data);
|
|
9709
9710
|
}
|
|
9711
|
+
/**
|
|
9712
|
+
* Generates Base64 encoded jwk used in the Encrypted Authorize Response (EAR) flow
|
|
9713
|
+
*/
|
|
9714
|
+
async function generateEarKey() {
|
|
9715
|
+
const key = await generateBaseKey();
|
|
9716
|
+
const keyStr = urlEncodeArr(new Uint8Array(key));
|
|
9717
|
+
const jwk = {
|
|
9718
|
+
alg: "dir",
|
|
9719
|
+
kty: "oct",
|
|
9720
|
+
k: keyStr,
|
|
9721
|
+
};
|
|
9722
|
+
return base64Encode(JSON.stringify(jwk));
|
|
9723
|
+
}
|
|
9724
|
+
/**
|
|
9725
|
+
* Parses earJwk for encryption key and returns CryptoKey object
|
|
9726
|
+
* @param earJwk
|
|
9727
|
+
* @returns
|
|
9728
|
+
*/
|
|
9729
|
+
async function importEarKey(earJwk) {
|
|
9730
|
+
const b64DecodedJwk = base64Decode(earJwk);
|
|
9731
|
+
const jwkJson = JSON.parse(b64DecodedJwk);
|
|
9732
|
+
const rawKey = jwkJson.k;
|
|
9733
|
+
const keyBuffer = base64DecToArr(rawKey);
|
|
9734
|
+
return window.crypto.subtle.importKey(RAW, keyBuffer, AES_GCM, false, [
|
|
9735
|
+
DECRYPT,
|
|
9736
|
+
]);
|
|
9737
|
+
}
|
|
9738
|
+
/**
|
|
9739
|
+
* Decrypt ear_jwe response returned in the Encrypted Authorize Response (EAR) flow
|
|
9740
|
+
* @param earJwk
|
|
9741
|
+
* @param earJwe
|
|
9742
|
+
* @returns
|
|
9743
|
+
*/
|
|
9744
|
+
async function decryptEarResponse(earJwk, earJwe) {
|
|
9745
|
+
const earJweParts = earJwe.split(".");
|
|
9746
|
+
if (earJweParts.length !== 5) {
|
|
9747
|
+
throw createBrowserAuthError(failedToDecryptEarResponse, "jwe_length");
|
|
9748
|
+
}
|
|
9749
|
+
const key = await importEarKey(earJwk).catch(() => {
|
|
9750
|
+
throw createBrowserAuthError(failedToDecryptEarResponse, "import_key");
|
|
9751
|
+
});
|
|
9752
|
+
try {
|
|
9753
|
+
const header = new TextEncoder().encode(earJweParts[0]);
|
|
9754
|
+
const iv = base64DecToArr(earJweParts[2]);
|
|
9755
|
+
const ciphertext = base64DecToArr(earJweParts[3]);
|
|
9756
|
+
const tag = base64DecToArr(earJweParts[4]);
|
|
9757
|
+
const tagLengthBits = tag.byteLength * 8;
|
|
9758
|
+
// Concat ciphertext and tag
|
|
9759
|
+
const encryptedData = new Uint8Array(ciphertext.length + tag.length);
|
|
9760
|
+
encryptedData.set(ciphertext);
|
|
9761
|
+
encryptedData.set(tag, ciphertext.length);
|
|
9762
|
+
const decryptedData = await window.crypto.subtle.decrypt({
|
|
9763
|
+
name: AES_GCM,
|
|
9764
|
+
iv: iv,
|
|
9765
|
+
tagLength: tagLengthBits,
|
|
9766
|
+
additionalData: header,
|
|
9767
|
+
}, key, encryptedData);
|
|
9768
|
+
return new TextDecoder().decode(decryptedData);
|
|
9769
|
+
}
|
|
9770
|
+
catch (e) {
|
|
9771
|
+
throw createBrowserAuthError(failedToDecryptEarResponse, "decrypt");
|
|
9772
|
+
}
|
|
9773
|
+
}
|
|
9710
9774
|
/**
|
|
9711
9775
|
* Generates symmetric base encryption key. This may be stored as all encryption/decryption keys will be derived from this one.
|
|
9712
9776
|
*/
|
|
@@ -10292,9 +10356,9 @@
|
|
|
10292
10356
|
const logger = new Logger(providedSystemOptions.loggerOptions);
|
|
10293
10357
|
logger.warning(JSON.stringify(createClientConfigurationError(cannotSetOIDCOptions)));
|
|
10294
10358
|
}
|
|
10295
|
-
// Throw an error if user has set allowPlatformBroker to true
|
|
10359
|
+
// Throw an error if user has set allowPlatformBroker to true with OIDC protocol mode
|
|
10296
10360
|
if (userInputAuth?.protocolMode &&
|
|
10297
|
-
userInputAuth.protocolMode
|
|
10361
|
+
userInputAuth.protocolMode === ProtocolMode.OIDC &&
|
|
10298
10362
|
providedSystemOptions?.allowPlatformBroker) {
|
|
10299
10363
|
throw createClientConfigurationError(cannotAllowPlatformBroker);
|
|
10300
10364
|
}
|
|
@@ -10316,7 +10380,7 @@
|
|
|
10316
10380
|
|
|
10317
10381
|
/* eslint-disable header/header */
|
|
10318
10382
|
const name = "@azure/msal-browser";
|
|
10319
|
-
const version = "4.
|
|
10383
|
+
const version = "4.9.1";
|
|
10320
10384
|
|
|
10321
10385
|
/*
|
|
10322
10386
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -11637,28 +11701,6 @@
|
|
|
11637
11701
|
}
|
|
11638
11702
|
}
|
|
11639
11703
|
|
|
11640
|
-
/*
|
|
11641
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
11642
|
-
* Licensed under the MIT License.
|
|
11643
|
-
*/
|
|
11644
|
-
/**
|
|
11645
|
-
* Extracts the BrowserStateObject from the state string.
|
|
11646
|
-
* @param browserCrypto
|
|
11647
|
-
* @param state
|
|
11648
|
-
*/
|
|
11649
|
-
function extractBrowserRequestState(browserCrypto, state) {
|
|
11650
|
-
if (!state) {
|
|
11651
|
-
return null;
|
|
11652
|
-
}
|
|
11653
|
-
try {
|
|
11654
|
-
const requestStateObj = ProtocolUtils.parseRequestState(browserCrypto, state);
|
|
11655
|
-
return requestStateObj.libraryState.meta;
|
|
11656
|
-
}
|
|
11657
|
-
catch (e) {
|
|
11658
|
-
throw createClientAuthError(invalidState);
|
|
11659
|
-
}
|
|
11660
|
-
}
|
|
11661
|
-
|
|
11662
11704
|
/*
|
|
11663
11705
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
11664
11706
|
* Licensed under the MIT License.
|
|
@@ -12358,177 +12400,53 @@
|
|
|
12358
12400
|
}
|
|
12359
12401
|
return JSON.stringify(key);
|
|
12360
12402
|
}
|
|
12361
|
-
/**
|
|
12362
|
-
* Create authorityKey to cache authority
|
|
12363
|
-
* @param state
|
|
12364
|
-
*/
|
|
12365
|
-
generateAuthorityKey(stateString) {
|
|
12366
|
-
const { libraryState: { id: stateId }, } = ProtocolUtils.parseRequestState(this.cryptoImpl, stateString);
|
|
12367
|
-
return this.generateCacheKey(`${TemporaryCacheKeys.AUTHORITY}.${stateId}`);
|
|
12368
|
-
}
|
|
12369
|
-
/**
|
|
12370
|
-
* Create Nonce key to cache nonce
|
|
12371
|
-
* @param state
|
|
12372
|
-
*/
|
|
12373
|
-
generateNonceKey(stateString) {
|
|
12374
|
-
const { libraryState: { id: stateId }, } = ProtocolUtils.parseRequestState(this.cryptoImpl, stateString);
|
|
12375
|
-
return this.generateCacheKey(`${TemporaryCacheKeys.NONCE_IDTOKEN}.${stateId}`);
|
|
12376
|
-
}
|
|
12377
|
-
/**
|
|
12378
|
-
* Creates full cache key for the request state
|
|
12379
|
-
* @param stateString State string for the request
|
|
12380
|
-
*/
|
|
12381
|
-
generateStateKey(stateString) {
|
|
12382
|
-
// Use the library state id to key temp storage for uniqueness for multiple concurrent requests
|
|
12383
|
-
const { libraryState: { id: stateId }, } = ProtocolUtils.parseRequestState(this.cryptoImpl, stateString);
|
|
12384
|
-
return this.generateCacheKey(`${TemporaryCacheKeys.REQUEST_STATE}.${stateId}`);
|
|
12385
|
-
}
|
|
12386
|
-
/**
|
|
12387
|
-
* Gets the cached authority based on the cached state. Returns empty if no cached state found.
|
|
12388
|
-
*/
|
|
12389
|
-
getCachedAuthority(cachedState) {
|
|
12390
|
-
const stateCacheKey = this.generateStateKey(cachedState);
|
|
12391
|
-
const state = this.getTemporaryCache(stateCacheKey);
|
|
12392
|
-
if (!state) {
|
|
12393
|
-
return null;
|
|
12394
|
-
}
|
|
12395
|
-
const authorityCacheKey = this.generateAuthorityKey(state);
|
|
12396
|
-
return this.getTemporaryCache(authorityCacheKey);
|
|
12397
|
-
}
|
|
12398
|
-
/**
|
|
12399
|
-
* Updates account, authority, and state in cache
|
|
12400
|
-
* @param serverAuthenticationRequest
|
|
12401
|
-
* @param account
|
|
12402
|
-
*/
|
|
12403
|
-
updateCacheEntries(state, nonce, authorityInstance, loginHint, account) {
|
|
12404
|
-
this.logger.trace("BrowserCacheManager.updateCacheEntries called");
|
|
12405
|
-
// Cache the request state
|
|
12406
|
-
const stateCacheKey = this.generateStateKey(state);
|
|
12407
|
-
this.setTemporaryCache(stateCacheKey, state, false);
|
|
12408
|
-
// Cache the nonce
|
|
12409
|
-
const nonceCacheKey = this.generateNonceKey(state);
|
|
12410
|
-
this.setTemporaryCache(nonceCacheKey, nonce, false);
|
|
12411
|
-
// Cache authorityKey
|
|
12412
|
-
const authorityCacheKey = this.generateAuthorityKey(state);
|
|
12413
|
-
this.setTemporaryCache(authorityCacheKey, authorityInstance, false);
|
|
12414
|
-
if (account) {
|
|
12415
|
-
const ccsCredential = {
|
|
12416
|
-
credential: account.homeAccountId,
|
|
12417
|
-
type: CcsCredentialType.HOME_ACCOUNT_ID,
|
|
12418
|
-
};
|
|
12419
|
-
this.setTemporaryCache(TemporaryCacheKeys.CCS_CREDENTIAL, JSON.stringify(ccsCredential), true);
|
|
12420
|
-
}
|
|
12421
|
-
else if (loginHint) {
|
|
12422
|
-
const ccsCredential = {
|
|
12423
|
-
credential: loginHint,
|
|
12424
|
-
type: CcsCredentialType.UPN,
|
|
12425
|
-
};
|
|
12426
|
-
this.setTemporaryCache(TemporaryCacheKeys.CCS_CREDENTIAL, JSON.stringify(ccsCredential), true);
|
|
12427
|
-
}
|
|
12428
|
-
}
|
|
12429
12403
|
/**
|
|
12430
12404
|
* Reset all temporary cache items
|
|
12431
12405
|
* @param state
|
|
12432
12406
|
*/
|
|
12433
|
-
resetRequestCache(
|
|
12407
|
+
resetRequestCache() {
|
|
12434
12408
|
this.logger.trace("BrowserCacheManager.resetRequestCache called");
|
|
12435
|
-
// check state and remove associated cache items
|
|
12436
|
-
if (state) {
|
|
12437
|
-
this.temporaryCacheStorage.getKeys().forEach((key) => {
|
|
12438
|
-
if (key.indexOf(state) !== -1) {
|
|
12439
|
-
this.removeTemporaryItem(key);
|
|
12440
|
-
}
|
|
12441
|
-
});
|
|
12442
|
-
// delete generic interactive request parameters
|
|
12443
|
-
this.removeTemporaryItem(this.generateStateKey(state));
|
|
12444
|
-
this.removeTemporaryItem(this.generateNonceKey(state));
|
|
12445
|
-
this.removeTemporaryItem(this.generateAuthorityKey(state));
|
|
12446
|
-
}
|
|
12447
12409
|
this.removeTemporaryItem(this.generateCacheKey(TemporaryCacheKeys.REQUEST_PARAMS));
|
|
12410
|
+
this.removeTemporaryItem(this.generateCacheKey(TemporaryCacheKeys.VERIFIER));
|
|
12448
12411
|
this.removeTemporaryItem(this.generateCacheKey(TemporaryCacheKeys.ORIGIN_URI));
|
|
12449
12412
|
this.removeTemporaryItem(this.generateCacheKey(TemporaryCacheKeys.URL_HASH));
|
|
12450
|
-
this.removeTemporaryItem(this.generateCacheKey(TemporaryCacheKeys.CORRELATION_ID));
|
|
12451
|
-
this.removeTemporaryItem(this.generateCacheKey(TemporaryCacheKeys.CCS_CREDENTIAL));
|
|
12452
12413
|
this.removeTemporaryItem(this.generateCacheKey(TemporaryCacheKeys.NATIVE_REQUEST));
|
|
12453
12414
|
this.setInteractionInProgress(false);
|
|
12454
12415
|
}
|
|
12455
|
-
|
|
12456
|
-
|
|
12457
|
-
* @param stateString
|
|
12458
|
-
*/
|
|
12459
|
-
cleanRequestByState(stateString) {
|
|
12460
|
-
this.logger.trace("BrowserCacheManager.cleanRequestByState called");
|
|
12461
|
-
// Interaction is completed - remove interaction status.
|
|
12462
|
-
if (stateString) {
|
|
12463
|
-
const stateKey = this.generateStateKey(stateString);
|
|
12464
|
-
const cachedState = this.temporaryCacheStorage.getItem(stateKey);
|
|
12465
|
-
this.logger.infoPii(`BrowserCacheManager.cleanRequestByState: Removing temporary cache items for state: ${cachedState}`);
|
|
12466
|
-
this.resetRequestCache(cachedState || Constants.EMPTY_STRING);
|
|
12467
|
-
}
|
|
12468
|
-
}
|
|
12469
|
-
/**
|
|
12470
|
-
* Looks in temporary cache for any state values with the provided interactionType and removes all temporary cache items for that state
|
|
12471
|
-
* Used in scenarios where temp cache needs to be cleaned but state is not known, such as clicking browser back button.
|
|
12472
|
-
* @param interactionType
|
|
12473
|
-
*/
|
|
12474
|
-
cleanRequestByInteractionType(interactionType) {
|
|
12475
|
-
this.logger.trace("BrowserCacheManager.cleanRequestByInteractionType called");
|
|
12476
|
-
// Loop through all keys to find state key
|
|
12477
|
-
this.temporaryCacheStorage.getKeys().forEach((key) => {
|
|
12478
|
-
// If this key is not the state key, move on
|
|
12479
|
-
if (key.indexOf(TemporaryCacheKeys.REQUEST_STATE) === -1) {
|
|
12480
|
-
return;
|
|
12481
|
-
}
|
|
12482
|
-
// Retrieve state value, return if not a valid value
|
|
12483
|
-
const stateValue = this.temporaryCacheStorage.getItem(key);
|
|
12484
|
-
if (!stateValue) {
|
|
12485
|
-
return;
|
|
12486
|
-
}
|
|
12487
|
-
// Extract state and ensure it matches given InteractionType, then clean request cache
|
|
12488
|
-
const parsedState = extractBrowserRequestState(this.cryptoImpl, stateValue);
|
|
12489
|
-
if (parsedState &&
|
|
12490
|
-
parsedState.interactionType === interactionType) {
|
|
12491
|
-
this.logger.infoPii(`BrowserCacheManager.cleanRequestByInteractionType: Removing temporary cache items for state: ${stateValue}`);
|
|
12492
|
-
this.resetRequestCache(stateValue);
|
|
12493
|
-
}
|
|
12494
|
-
});
|
|
12495
|
-
this.setInteractionInProgress(false);
|
|
12496
|
-
}
|
|
12497
|
-
cacheCodeRequest(authCodeRequest) {
|
|
12498
|
-
this.logger.trace("BrowserCacheManager.cacheCodeRequest called");
|
|
12416
|
+
cacheAuthorizeRequest(authCodeRequest, codeVerifier) {
|
|
12417
|
+
this.logger.trace("BrowserCacheManager.cacheAuthorizeRequest called");
|
|
12499
12418
|
const encodedValue = base64Encode(JSON.stringify(authCodeRequest));
|
|
12500
12419
|
this.setTemporaryCache(TemporaryCacheKeys.REQUEST_PARAMS, encodedValue, true);
|
|
12420
|
+
if (codeVerifier) {
|
|
12421
|
+
const encodedVerifier = base64Encode(codeVerifier);
|
|
12422
|
+
this.setTemporaryCache(TemporaryCacheKeys.VERIFIER, encodedVerifier, true);
|
|
12423
|
+
}
|
|
12501
12424
|
}
|
|
12502
12425
|
/**
|
|
12503
12426
|
* Gets the token exchange parameters from the cache. Throws an error if nothing is found.
|
|
12504
12427
|
*/
|
|
12505
|
-
getCachedRequest(
|
|
12428
|
+
getCachedRequest() {
|
|
12506
12429
|
this.logger.trace("BrowserCacheManager.getCachedRequest called");
|
|
12507
12430
|
// Get token request from cache and parse as TokenExchangeParameters.
|
|
12508
12431
|
const encodedTokenRequest = this.getTemporaryCache(TemporaryCacheKeys.REQUEST_PARAMS, true);
|
|
12509
12432
|
if (!encodedTokenRequest) {
|
|
12510
12433
|
throw createBrowserAuthError(noTokenRequestCacheError);
|
|
12511
12434
|
}
|
|
12435
|
+
const encodedVerifier = this.getTemporaryCache(TemporaryCacheKeys.VERIFIER, true);
|
|
12512
12436
|
let parsedRequest;
|
|
12437
|
+
let verifier = "";
|
|
12513
12438
|
try {
|
|
12514
12439
|
parsedRequest = JSON.parse(base64Decode(encodedTokenRequest));
|
|
12440
|
+
if (encodedVerifier) {
|
|
12441
|
+
verifier = base64Decode(encodedVerifier);
|
|
12442
|
+
}
|
|
12515
12443
|
}
|
|
12516
12444
|
catch (e) {
|
|
12517
12445
|
this.logger.errorPii(`Attempted to parse: ${encodedTokenRequest}`);
|
|
12518
12446
|
this.logger.error(`Parsing cached token request threw with error: ${e}`);
|
|
12519
12447
|
throw createBrowserAuthError(unableToParseTokenRequestCacheError);
|
|
12520
12448
|
}
|
|
12521
|
-
|
|
12522
|
-
// Get cached authority and use if no authority is cached with request.
|
|
12523
|
-
if (!parsedRequest.authority) {
|
|
12524
|
-
const authorityCacheKey = this.generateAuthorityKey(state);
|
|
12525
|
-
const cachedAuthority = this.getTemporaryCache(authorityCacheKey);
|
|
12526
|
-
if (!cachedAuthority) {
|
|
12527
|
-
throw createBrowserAuthError(noCachedAuthorityError);
|
|
12528
|
-
}
|
|
12529
|
-
parsedRequest.authority = cachedAuthority;
|
|
12530
|
-
}
|
|
12531
|
-
return parsedRequest;
|
|
12449
|
+
return [parsedRequest, verifier];
|
|
12532
12450
|
}
|
|
12533
12451
|
/**
|
|
12534
12452
|
* Gets cached native request for redirect flows
|
|
@@ -13354,1083 +13272,1103 @@
|
|
|
13354
13272
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
13355
13273
|
* Licensed under the MIT License.
|
|
13356
13274
|
*/
|
|
13357
|
-
class
|
|
13275
|
+
class NativeMessageHandler {
|
|
13276
|
+
constructor(logger, handshakeTimeoutMs, performanceClient, extensionId) {
|
|
13277
|
+
this.logger = logger;
|
|
13278
|
+
this.handshakeTimeoutMs = handshakeTimeoutMs;
|
|
13279
|
+
this.extensionId = extensionId;
|
|
13280
|
+
this.resolvers = new Map(); // Used for non-handshake messages
|
|
13281
|
+
this.handshakeResolvers = new Map(); // Used for handshake messages
|
|
13282
|
+
this.messageChannel = new MessageChannel();
|
|
13283
|
+
this.windowListener = this.onWindowMessage.bind(this); // Window event callback doesn't have access to 'this' unless it's bound
|
|
13284
|
+
this.performanceClient = performanceClient;
|
|
13285
|
+
this.handshakeEvent = performanceClient.startMeasurement(PerformanceEvents.NativeMessageHandlerHandshake);
|
|
13286
|
+
}
|
|
13358
13287
|
/**
|
|
13359
|
-
*
|
|
13360
|
-
* @param
|
|
13288
|
+
* Sends a given message to the extension and resolves with the extension response
|
|
13289
|
+
* @param body
|
|
13361
13290
|
*/
|
|
13362
|
-
async
|
|
13363
|
-
this.
|
|
13364
|
-
|
|
13365
|
-
|
|
13366
|
-
|
|
13367
|
-
|
|
13368
|
-
|
|
13369
|
-
|
|
13370
|
-
|
|
13291
|
+
async sendMessage(body) {
|
|
13292
|
+
this.logger.trace("NativeMessageHandler - sendMessage called.");
|
|
13293
|
+
const req = {
|
|
13294
|
+
channel: NativeConstants.CHANNEL_ID,
|
|
13295
|
+
extensionId: this.extensionId,
|
|
13296
|
+
responseId: createNewGuid(),
|
|
13297
|
+
body: body,
|
|
13298
|
+
};
|
|
13299
|
+
this.logger.trace("NativeMessageHandler - Sending request to browser extension");
|
|
13300
|
+
this.logger.tracePii(`NativeMessageHandler - Sending request to browser extension: ${JSON.stringify(req)}`);
|
|
13301
|
+
this.messageChannel.port1.postMessage(req);
|
|
13302
|
+
return new Promise((resolve, reject) => {
|
|
13303
|
+
this.resolvers.set(req.responseId, { resolve, reject });
|
|
13371
13304
|
});
|
|
13372
|
-
|
|
13373
|
-
|
|
13305
|
+
}
|
|
13306
|
+
/**
|
|
13307
|
+
* Returns an instance of the MessageHandler that has successfully established a connection with an extension
|
|
13308
|
+
* @param {Logger} logger
|
|
13309
|
+
* @param {number} handshakeTimeoutMs
|
|
13310
|
+
* @param {IPerformanceClient} performanceClient
|
|
13311
|
+
* @param {ICrypto} crypto
|
|
13312
|
+
*/
|
|
13313
|
+
static async createProvider(logger, handshakeTimeoutMs, performanceClient) {
|
|
13314
|
+
logger.trace("NativeMessageHandler - createProvider called.");
|
|
13374
13315
|
try {
|
|
13375
|
-
const
|
|
13376
|
-
|
|
13377
|
-
|
|
13378
|
-
fromCache: true,
|
|
13379
|
-
}, silentRequest.correlationId);
|
|
13380
|
-
return authResponse;
|
|
13316
|
+
const preferredProvider = new NativeMessageHandler(logger, handshakeTimeoutMs, performanceClient, NativeConstants.PREFERRED_EXTENSION_ID);
|
|
13317
|
+
await preferredProvider.sendHandshakeRequest();
|
|
13318
|
+
return preferredProvider;
|
|
13381
13319
|
}
|
|
13382
|
-
catch (
|
|
13383
|
-
|
|
13384
|
-
|
|
13385
|
-
|
|
13386
|
-
|
|
13387
|
-
throw error;
|
|
13320
|
+
catch (e) {
|
|
13321
|
+
// If preferred extension fails for whatever reason, fallback to using any installed extension
|
|
13322
|
+
const backupProvider = new NativeMessageHandler(logger, handshakeTimeoutMs, performanceClient);
|
|
13323
|
+
await backupProvider.sendHandshakeRequest();
|
|
13324
|
+
return backupProvider;
|
|
13388
13325
|
}
|
|
13389
13326
|
}
|
|
13390
13327
|
/**
|
|
13391
|
-
*
|
|
13392
|
-
* @param logoutRequest
|
|
13328
|
+
* Send handshake request helper.
|
|
13393
13329
|
*/
|
|
13394
|
-
|
|
13395
|
-
this.logger.
|
|
13396
|
-
|
|
13397
|
-
|
|
13398
|
-
|
|
13399
|
-
|
|
13400
|
-
|
|
13401
|
-
|
|
13402
|
-
|
|
13403
|
-
|
|
13404
|
-
|
|
13405
|
-
|
|
13406
|
-
|
|
13407
|
-
|
|
13408
|
-
|
|
13409
|
-
this.accountId = accountId;
|
|
13410
|
-
this.nativeMessageHandler = provider;
|
|
13411
|
-
this.nativeStorageManager = nativeStorageImpl;
|
|
13412
|
-
this.silentCacheClient = new SilentCacheClient(config, this.nativeStorageManager, browserCrypto, logger, eventHandler, navigationClient, performanceClient, provider, correlationId);
|
|
13413
|
-
const extensionName = this.nativeMessageHandler.getExtensionId() ===
|
|
13414
|
-
NativeConstants.PREFERRED_EXTENSION_ID
|
|
13415
|
-
? "chrome"
|
|
13416
|
-
: this.nativeMessageHandler.getExtensionId()?.length
|
|
13417
|
-
? "unknown"
|
|
13418
|
-
: undefined;
|
|
13419
|
-
this.skus = ServerTelemetryManager.makeExtraSkuString({
|
|
13420
|
-
libraryName: BrowserConstants.MSAL_SKU,
|
|
13421
|
-
libraryVersion: version,
|
|
13422
|
-
extensionName: extensionName,
|
|
13423
|
-
extensionVersion: this.nativeMessageHandler.getExtensionVersion(),
|
|
13330
|
+
async sendHandshakeRequest() {
|
|
13331
|
+
this.logger.trace("NativeMessageHandler - sendHandshakeRequest called.");
|
|
13332
|
+
// Register this event listener before sending handshake
|
|
13333
|
+
window.addEventListener("message", this.windowListener, false); // false is important, because content script message processing should work first
|
|
13334
|
+
const req = {
|
|
13335
|
+
channel: NativeConstants.CHANNEL_ID,
|
|
13336
|
+
extensionId: this.extensionId,
|
|
13337
|
+
responseId: createNewGuid(),
|
|
13338
|
+
body: {
|
|
13339
|
+
method: NativeExtensionMethod.HandshakeRequest,
|
|
13340
|
+
},
|
|
13341
|
+
};
|
|
13342
|
+
this.handshakeEvent.add({
|
|
13343
|
+
extensionId: this.extensionId,
|
|
13344
|
+
extensionHandshakeTimeoutMs: this.handshakeTimeoutMs,
|
|
13424
13345
|
});
|
|
13425
|
-
|
|
13426
|
-
|
|
13427
|
-
* Adds SKUs to request extra query parameters
|
|
13428
|
-
* @param request {NativeTokenRequest}
|
|
13429
|
-
* @private
|
|
13430
|
-
*/
|
|
13431
|
-
addRequestSKUs(request) {
|
|
13432
|
-
request.extraParameters = {
|
|
13433
|
-
...request.extraParameters,
|
|
13434
|
-
[X_CLIENT_EXTRA_SKU]: this.skus,
|
|
13346
|
+
this.messageChannel.port1.onmessage = (event) => {
|
|
13347
|
+
this.onChannelMessage(event);
|
|
13435
13348
|
};
|
|
13436
|
-
|
|
13437
|
-
|
|
13438
|
-
|
|
13439
|
-
|
|
13440
|
-
|
|
13441
|
-
|
|
13442
|
-
|
|
13443
|
-
|
|
13444
|
-
|
|
13445
|
-
|
|
13446
|
-
|
|
13447
|
-
|
|
13448
|
-
|
|
13449
|
-
// initialize native request
|
|
13450
|
-
const nativeRequest = await this.initializeNativeRequest(request);
|
|
13451
|
-
// check if the tokens can be retrieved from internal cache
|
|
13452
|
-
try {
|
|
13453
|
-
const result = await this.acquireTokensFromCache(this.accountId, nativeRequest);
|
|
13454
|
-
nativeATMeasurement.end({
|
|
13455
|
-
success: true,
|
|
13456
|
-
isNativeBroker: false,
|
|
13457
|
-
fromCache: true,
|
|
13458
|
-
});
|
|
13459
|
-
return result;
|
|
13460
|
-
}
|
|
13461
|
-
catch (e) {
|
|
13462
|
-
if (cacheLookupPolicy === CacheLookupPolicy.AccessToken) {
|
|
13463
|
-
this.logger.info("MSAL internal Cache does not contain tokens, return error as per cache policy");
|
|
13464
|
-
throw e;
|
|
13465
|
-
}
|
|
13466
|
-
// continue with a native call for any and all errors
|
|
13467
|
-
this.logger.info("MSAL internal Cache does not contain tokens, proceed to make a native call");
|
|
13468
|
-
}
|
|
13469
|
-
const { ...nativeTokenRequest } = nativeRequest;
|
|
13470
|
-
// fall back to native calls
|
|
13471
|
-
const messageBody = {
|
|
13472
|
-
method: NativeExtensionMethod.GetToken,
|
|
13473
|
-
request: nativeTokenRequest,
|
|
13474
|
-
};
|
|
13475
|
-
const response = await this.nativeMessageHandler.sendMessage(messageBody);
|
|
13476
|
-
const validatedResponse = this.validateNativeResponse(response);
|
|
13477
|
-
return await this.handleNativeResponse(validatedResponse, nativeRequest, reqTimestamp)
|
|
13478
|
-
.then((result) => {
|
|
13479
|
-
nativeATMeasurement.end({
|
|
13480
|
-
success: true,
|
|
13481
|
-
isNativeBroker: true,
|
|
13482
|
-
requestId: result.requestId,
|
|
13483
|
-
});
|
|
13484
|
-
serverTelemetryManager.clearNativeBrokerErrorCode();
|
|
13485
|
-
return result;
|
|
13486
|
-
})
|
|
13487
|
-
.catch((error) => {
|
|
13488
|
-
nativeATMeasurement.end({
|
|
13349
|
+
window.postMessage(req, window.origin, [this.messageChannel.port2]);
|
|
13350
|
+
return new Promise((resolve, reject) => {
|
|
13351
|
+
this.handshakeResolvers.set(req.responseId, { resolve, reject });
|
|
13352
|
+
this.timeoutId = window.setTimeout(() => {
|
|
13353
|
+
/*
|
|
13354
|
+
* Throw an error if neither HandshakeResponse nor original Handshake request are received in a reasonable timeframe.
|
|
13355
|
+
* This typically suggests an event handler stopped propagation of the Handshake request but did not respond to it on the MessageChannel port
|
|
13356
|
+
*/
|
|
13357
|
+
window.removeEventListener("message", this.windowListener, false);
|
|
13358
|
+
this.messageChannel.port1.close();
|
|
13359
|
+
this.messageChannel.port2.close();
|
|
13360
|
+
this.handshakeEvent.end({
|
|
13361
|
+
extensionHandshakeTimedOut: true,
|
|
13489
13362
|
success: false,
|
|
13490
|
-
errorCode: error.errorCode,
|
|
13491
|
-
subErrorCode: error.subError,
|
|
13492
|
-
isNativeBroker: true,
|
|
13493
13363
|
});
|
|
13494
|
-
|
|
13495
|
-
|
|
13496
|
-
|
|
13497
|
-
|
|
13498
|
-
if (e instanceof NativeAuthError) {
|
|
13499
|
-
serverTelemetryManager.setNativeBrokerErrorCode(e.errorCode);
|
|
13500
|
-
}
|
|
13501
|
-
throw e;
|
|
13502
|
-
}
|
|
13503
|
-
}
|
|
13504
|
-
/**
|
|
13505
|
-
* Creates silent flow request
|
|
13506
|
-
* @param request
|
|
13507
|
-
* @param cachedAccount
|
|
13508
|
-
* @returns CommonSilentFlowRequest
|
|
13509
|
-
*/
|
|
13510
|
-
createSilentCacheRequest(request, cachedAccount) {
|
|
13511
|
-
return {
|
|
13512
|
-
authority: request.authority,
|
|
13513
|
-
correlationId: this.correlationId,
|
|
13514
|
-
scopes: ScopeSet.fromString(request.scope).asArray(),
|
|
13515
|
-
account: cachedAccount,
|
|
13516
|
-
forceRefresh: false,
|
|
13517
|
-
};
|
|
13364
|
+
reject(createBrowserAuthError(nativeHandshakeTimeout));
|
|
13365
|
+
this.handshakeResolvers.delete(req.responseId);
|
|
13366
|
+
}, this.handshakeTimeoutMs); // Use a reasonable timeout in milliseconds here
|
|
13367
|
+
});
|
|
13518
13368
|
}
|
|
13519
13369
|
/**
|
|
13520
|
-
*
|
|
13521
|
-
* @param
|
|
13522
|
-
* @param request
|
|
13523
|
-
* @returns authenticationResult
|
|
13370
|
+
* Invoked when a message is posted to the window. If a handshake request is received it means the extension is not installed.
|
|
13371
|
+
* @param event
|
|
13524
13372
|
*/
|
|
13525
|
-
|
|
13526
|
-
|
|
13527
|
-
|
|
13528
|
-
|
|
13373
|
+
onWindowMessage(event) {
|
|
13374
|
+
this.logger.trace("NativeMessageHandler - onWindowMessage called");
|
|
13375
|
+
// We only accept messages from ourselves
|
|
13376
|
+
if (event.source !== window) {
|
|
13377
|
+
return;
|
|
13529
13378
|
}
|
|
13530
|
-
|
|
13531
|
-
|
|
13532
|
-
|
|
13533
|
-
|
|
13534
|
-
if (!account) {
|
|
13535
|
-
throw createClientAuthError(noAccountFound);
|
|
13379
|
+
const request = event.data;
|
|
13380
|
+
if (!request.channel ||
|
|
13381
|
+
request.channel !== NativeConstants.CHANNEL_ID) {
|
|
13382
|
+
return;
|
|
13536
13383
|
}
|
|
13537
|
-
|
|
13538
|
-
|
|
13539
|
-
const silentRequest = this.createSilentCacheRequest(request, account);
|
|
13540
|
-
const result = await this.silentCacheClient.acquireToken(silentRequest);
|
|
13541
|
-
const fullAccount = {
|
|
13542
|
-
...account,
|
|
13543
|
-
idTokenClaims: result?.idTokenClaims,
|
|
13544
|
-
idToken: result?.idToken,
|
|
13545
|
-
};
|
|
13546
|
-
return {
|
|
13547
|
-
...result,
|
|
13548
|
-
account: fullAccount,
|
|
13549
|
-
};
|
|
13384
|
+
if (request.extensionId && request.extensionId !== this.extensionId) {
|
|
13385
|
+
return;
|
|
13550
13386
|
}
|
|
13551
|
-
|
|
13552
|
-
|
|
13387
|
+
if (request.body.method === NativeExtensionMethod.HandshakeRequest) {
|
|
13388
|
+
const handshakeResolver = this.handshakeResolvers.get(request.responseId);
|
|
13389
|
+
/*
|
|
13390
|
+
* Filter out responses with no matched resolvers sooner to keep channel ports open while waiting for
|
|
13391
|
+
* the proper response.
|
|
13392
|
+
*/
|
|
13393
|
+
if (!handshakeResolver) {
|
|
13394
|
+
this.logger.trace(`NativeMessageHandler.onWindowMessage - resolver can't be found for request ${request.responseId}`);
|
|
13395
|
+
return;
|
|
13396
|
+
}
|
|
13397
|
+
// If we receive this message back it means no extension intercepted the request, meaning no extension supporting handshake protocol is installed
|
|
13398
|
+
this.logger.verbose(request.extensionId
|
|
13399
|
+
? `Extension with id: ${request.extensionId} not installed`
|
|
13400
|
+
: "No extension installed");
|
|
13401
|
+
clearTimeout(this.timeoutId);
|
|
13402
|
+
this.messageChannel.port1.close();
|
|
13403
|
+
this.messageChannel.port2.close();
|
|
13404
|
+
window.removeEventListener("message", this.windowListener, false);
|
|
13405
|
+
this.handshakeEvent.end({
|
|
13406
|
+
success: false,
|
|
13407
|
+
extensionInstalled: false,
|
|
13408
|
+
});
|
|
13409
|
+
handshakeResolver.reject(createBrowserAuthError(nativeExtensionNotInstalled));
|
|
13553
13410
|
}
|
|
13554
13411
|
}
|
|
13555
13412
|
/**
|
|
13556
|
-
*
|
|
13557
|
-
* @param
|
|
13558
|
-
* @param {InProgressPerformanceEvent} rootMeasurement
|
|
13413
|
+
* Invoked when a message is received from the extension on the MessageChannel port
|
|
13414
|
+
* @param event
|
|
13559
13415
|
*/
|
|
13560
|
-
|
|
13561
|
-
this.logger.trace("
|
|
13562
|
-
const
|
|
13563
|
-
|
|
13564
|
-
const
|
|
13565
|
-
const messageBody = {
|
|
13566
|
-
method: NativeExtensionMethod.GetToken,
|
|
13567
|
-
request: nativeRequest,
|
|
13568
|
-
};
|
|
13416
|
+
onChannelMessage(event) {
|
|
13417
|
+
this.logger.trace("NativeMessageHandler - onChannelMessage called.");
|
|
13418
|
+
const request = event.data;
|
|
13419
|
+
const resolver = this.resolvers.get(request.responseId);
|
|
13420
|
+
const handshakeResolver = this.handshakeResolvers.get(request.responseId);
|
|
13569
13421
|
try {
|
|
13570
|
-
const
|
|
13571
|
-
|
|
13572
|
-
|
|
13573
|
-
|
|
13574
|
-
|
|
13575
|
-
|
|
13576
|
-
|
|
13577
|
-
|
|
13578
|
-
if (
|
|
13579
|
-
|
|
13422
|
+
const method = request.body.method;
|
|
13423
|
+
if (method === NativeExtensionMethod.Response) {
|
|
13424
|
+
if (!resolver) {
|
|
13425
|
+
return;
|
|
13426
|
+
}
|
|
13427
|
+
const response = request.body.response;
|
|
13428
|
+
this.logger.trace("NativeMessageHandler - Received response from browser extension");
|
|
13429
|
+
this.logger.tracePii(`NativeMessageHandler - Received response from browser extension: ${JSON.stringify(response)}`);
|
|
13430
|
+
if (response.status !== "Success") {
|
|
13431
|
+
resolver.reject(createNativeAuthError(response.code, response.description, response.ext));
|
|
13432
|
+
}
|
|
13433
|
+
else if (response.result) {
|
|
13434
|
+
if (response.result["code"] &&
|
|
13435
|
+
response.result["description"]) {
|
|
13436
|
+
resolver.reject(createNativeAuthError(response.result["code"], response.result["description"], response.result["ext"]));
|
|
13437
|
+
}
|
|
13438
|
+
else {
|
|
13439
|
+
resolver.resolve(response.result);
|
|
13440
|
+
}
|
|
13441
|
+
}
|
|
13442
|
+
else {
|
|
13443
|
+
throw createAuthError(unexpectedError, "Event does not contain result.");
|
|
13580
13444
|
}
|
|
13445
|
+
this.resolvers.delete(request.responseId);
|
|
13446
|
+
}
|
|
13447
|
+
else if (method === NativeExtensionMethod.HandshakeResponse) {
|
|
13448
|
+
if (!handshakeResolver) {
|
|
13449
|
+
this.logger.trace(`NativeMessageHandler.onChannelMessage - resolver can't be found for request ${request.responseId}`);
|
|
13450
|
+
return;
|
|
13451
|
+
}
|
|
13452
|
+
clearTimeout(this.timeoutId); // Clear setTimeout
|
|
13453
|
+
window.removeEventListener("message", this.windowListener, false); // Remove 'No extension' listener
|
|
13454
|
+
this.extensionId = request.extensionId;
|
|
13455
|
+
this.extensionVersion = request.body.version;
|
|
13456
|
+
this.logger.verbose(`NativeMessageHandler - Received HandshakeResponse from extension: ${this.extensionId}`);
|
|
13457
|
+
this.handshakeEvent.end({
|
|
13458
|
+
extensionInstalled: true,
|
|
13459
|
+
success: true,
|
|
13460
|
+
});
|
|
13461
|
+
handshakeResolver.resolve();
|
|
13462
|
+
this.handshakeResolvers.delete(request.responseId);
|
|
13463
|
+
}
|
|
13464
|
+
// Do nothing if method is not Response or HandshakeResponse
|
|
13465
|
+
}
|
|
13466
|
+
catch (err) {
|
|
13467
|
+
this.logger.error("Error parsing response from WAM Extension");
|
|
13468
|
+
this.logger.errorPii(`Error parsing response from WAM Extension: ${err}`);
|
|
13469
|
+
this.logger.errorPii(`Unable to parse ${event}`);
|
|
13470
|
+
if (resolver) {
|
|
13471
|
+
resolver.reject(err);
|
|
13472
|
+
}
|
|
13473
|
+
else if (handshakeResolver) {
|
|
13474
|
+
handshakeResolver.reject(err);
|
|
13581
13475
|
}
|
|
13582
13476
|
}
|
|
13583
|
-
this.browserStorage.setTemporaryCache(TemporaryCacheKeys.NATIVE_REQUEST, JSON.stringify(nativeRequest), true);
|
|
13584
|
-
const navigationOptions = {
|
|
13585
|
-
apiId: ApiId.acquireTokenRedirect,
|
|
13586
|
-
timeout: this.config.system.redirectNavigationTimeout,
|
|
13587
|
-
noHistory: false,
|
|
13588
|
-
};
|
|
13589
|
-
const redirectUri = this.config.auth.navigateToLoginRequestUrl
|
|
13590
|
-
? window.location.href
|
|
13591
|
-
: this.getRedirectUri(request.redirectUri);
|
|
13592
|
-
rootMeasurement.end({ success: true });
|
|
13593
|
-
await this.navigationClient.navigateExternal(redirectUri, navigationOptions); // Need to treat this as external to ensure handleRedirectPromise is run again
|
|
13594
13477
|
}
|
|
13595
13478
|
/**
|
|
13596
|
-
*
|
|
13597
|
-
* @
|
|
13598
|
-
* @param correlationId {string?} correlation identifier
|
|
13479
|
+
* Returns the Id for the browser extension this handler is communicating with
|
|
13480
|
+
* @returns
|
|
13599
13481
|
*/
|
|
13600
|
-
|
|
13601
|
-
this.
|
|
13602
|
-
if (!this.browserStorage.isInteractionInProgress(true)) {
|
|
13603
|
-
this.logger.info("handleRedirectPromise called but there is no interaction in progress, returning null.");
|
|
13604
|
-
return null;
|
|
13605
|
-
}
|
|
13606
|
-
// remove prompt from the request to prevent WAM from prompting twice
|
|
13607
|
-
const cachedRequest = this.browserStorage.getCachedNativeRequest();
|
|
13608
|
-
if (!cachedRequest) {
|
|
13609
|
-
this.logger.verbose("NativeInteractionClient - handleRedirectPromise called but there is no cached request, returning null.");
|
|
13610
|
-
if (performanceClient && correlationId) {
|
|
13611
|
-
performanceClient?.addFields({ errorCode: "no_cached_request" }, correlationId);
|
|
13612
|
-
}
|
|
13613
|
-
return null;
|
|
13614
|
-
}
|
|
13615
|
-
const { prompt, ...request } = cachedRequest;
|
|
13616
|
-
if (prompt) {
|
|
13617
|
-
this.logger.verbose("NativeInteractionClient - handleRedirectPromise called and prompt was included in the original request, removing prompt from cached request to prevent second interaction with native broker window.");
|
|
13618
|
-
}
|
|
13619
|
-
this.browserStorage.removeItem(this.browserStorage.generateCacheKey(TemporaryCacheKeys.NATIVE_REQUEST));
|
|
13620
|
-
const messageBody = {
|
|
13621
|
-
method: NativeExtensionMethod.GetToken,
|
|
13622
|
-
request: request,
|
|
13623
|
-
};
|
|
13624
|
-
const reqTimestamp = nowSeconds();
|
|
13625
|
-
try {
|
|
13626
|
-
this.logger.verbose("NativeInteractionClient - handleRedirectPromise sending message to native broker.");
|
|
13627
|
-
const response = await this.nativeMessageHandler.sendMessage(messageBody);
|
|
13628
|
-
this.validateNativeResponse(response);
|
|
13629
|
-
const result = this.handleNativeResponse(response, request, reqTimestamp);
|
|
13630
|
-
this.browserStorage.setInteractionInProgress(false);
|
|
13631
|
-
const res = await result;
|
|
13632
|
-
const serverTelemetryManager = this.initializeServerTelemetryManager(this.apiId);
|
|
13633
|
-
serverTelemetryManager.clearNativeBrokerErrorCode();
|
|
13634
|
-
return res;
|
|
13635
|
-
}
|
|
13636
|
-
catch (e) {
|
|
13637
|
-
this.browserStorage.setInteractionInProgress(false);
|
|
13638
|
-
throw e;
|
|
13639
|
-
}
|
|
13482
|
+
getExtensionId() {
|
|
13483
|
+
return this.extensionId;
|
|
13640
13484
|
}
|
|
13641
13485
|
/**
|
|
13642
|
-
*
|
|
13643
|
-
* @
|
|
13486
|
+
* Returns the version for the browser extension this handler is communicating with
|
|
13487
|
+
* @returns
|
|
13644
13488
|
*/
|
|
13645
|
-
|
|
13646
|
-
this.
|
|
13647
|
-
return Promise.reject("Logout not implemented yet");
|
|
13489
|
+
getExtensionVersion() {
|
|
13490
|
+
return this.extensionVersion;
|
|
13648
13491
|
}
|
|
13649
13492
|
/**
|
|
13650
|
-
*
|
|
13651
|
-
* @param
|
|
13652
|
-
* @param
|
|
13653
|
-
* @param
|
|
13493
|
+
* Returns boolean indicating whether or not the request should attempt to use native broker
|
|
13494
|
+
* @param logger
|
|
13495
|
+
* @param config
|
|
13496
|
+
* @param nativeExtensionProvider
|
|
13497
|
+
* @param authenticationScheme
|
|
13654
13498
|
*/
|
|
13655
|
-
|
|
13656
|
-
|
|
13657
|
-
|
|
13658
|
-
|
|
13659
|
-
|
|
13660
|
-
|
|
13661
|
-
nativeAccountId: request.accountId,
|
|
13662
|
-
})?.homeAccountId;
|
|
13663
|
-
// add exception for double brokering, please note this is temporary and will be fortified in future
|
|
13664
|
-
if (request.extraParameters?.child_client_id &&
|
|
13665
|
-
response.account.id !== request.accountId) {
|
|
13666
|
-
this.logger.info("handleNativeServerResponse: Double broker flow detected, ignoring accountId mismatch");
|
|
13499
|
+
static isPlatformBrokerAvailable(config, logger, nativeExtensionProvider, authenticationScheme) {
|
|
13500
|
+
logger.trace("isPlatformBrokerAvailable called");
|
|
13501
|
+
if (!config.system.allowPlatformBroker) {
|
|
13502
|
+
logger.trace("isPlatformBrokerAvailable: allowPlatformBroker is not enabled, returning false");
|
|
13503
|
+
// Developer disabled WAM
|
|
13504
|
+
return false;
|
|
13667
13505
|
}
|
|
13668
|
-
|
|
13669
|
-
|
|
13670
|
-
//
|
|
13671
|
-
|
|
13506
|
+
if (!nativeExtensionProvider) {
|
|
13507
|
+
logger.trace("isPlatformBrokerAvailable: Platform extension provider is not initialized, returning false");
|
|
13508
|
+
// Extension is not available
|
|
13509
|
+
return false;
|
|
13672
13510
|
}
|
|
13673
|
-
|
|
13674
|
-
|
|
13675
|
-
|
|
13676
|
-
|
|
13677
|
-
|
|
13678
|
-
|
|
13679
|
-
|
|
13680
|
-
|
|
13681
|
-
|
|
13682
|
-
|
|
13683
|
-
|
|
13684
|
-
|
|
13685
|
-
await this.cacheAccount(baseAccount);
|
|
13686
|
-
await this.cacheNativeTokens(response, request, homeAccountIdentifier, idTokenClaims, response.access_token, result.tenantId, reqTimestamp);
|
|
13687
|
-
return result;
|
|
13511
|
+
if (authenticationScheme) {
|
|
13512
|
+
switch (authenticationScheme) {
|
|
13513
|
+
case AuthenticationScheme.BEARER:
|
|
13514
|
+
case AuthenticationScheme.POP:
|
|
13515
|
+
logger.trace("isPlatformBrokerAvailable: authenticationScheme is supported, returning true");
|
|
13516
|
+
return true;
|
|
13517
|
+
default:
|
|
13518
|
+
logger.trace("isPlatformBrokerAvailable: authenticationScheme is not supported, returning false");
|
|
13519
|
+
return false;
|
|
13520
|
+
}
|
|
13521
|
+
}
|
|
13522
|
+
return true;
|
|
13688
13523
|
}
|
|
13689
|
-
|
|
13690
|
-
|
|
13691
|
-
|
|
13692
|
-
|
|
13693
|
-
|
|
13694
|
-
|
|
13695
|
-
|
|
13696
|
-
|
|
13697
|
-
|
|
13698
|
-
|
|
13524
|
+
}
|
|
13525
|
+
|
|
13526
|
+
/*
|
|
13527
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
13528
|
+
* Licensed under the MIT License.
|
|
13529
|
+
*/
|
|
13530
|
+
/**
|
|
13531
|
+
* Extracts the BrowserStateObject from the state string.
|
|
13532
|
+
* @param browserCrypto
|
|
13533
|
+
* @param state
|
|
13534
|
+
*/
|
|
13535
|
+
function extractBrowserRequestState(browserCrypto, state) {
|
|
13536
|
+
if (!state) {
|
|
13537
|
+
return null;
|
|
13699
13538
|
}
|
|
13700
|
-
|
|
13701
|
-
|
|
13702
|
-
|
|
13703
|
-
|
|
13704
|
-
|
|
13705
|
-
|
|
13706
|
-
|
|
13707
|
-
|
|
13708
|
-
|
|
13709
|
-
|
|
13539
|
+
try {
|
|
13540
|
+
const requestStateObj = ProtocolUtils.parseRequestState(browserCrypto, state);
|
|
13541
|
+
return requestStateObj.libraryState.meta;
|
|
13542
|
+
}
|
|
13543
|
+
catch (e) {
|
|
13544
|
+
throw createClientAuthError(invalidState);
|
|
13545
|
+
}
|
|
13546
|
+
}
|
|
13547
|
+
|
|
13548
|
+
/*
|
|
13549
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
13550
|
+
* Licensed under the MIT License.
|
|
13551
|
+
*/
|
|
13552
|
+
function deserializeResponse(responseString, responseLocation, logger) {
|
|
13553
|
+
// Deserialize hash fragment response parameters.
|
|
13554
|
+
const serverParams = getDeserializedResponse(responseString);
|
|
13555
|
+
if (!serverParams) {
|
|
13556
|
+
if (!stripLeadingHashOrQuery(responseString)) {
|
|
13557
|
+
// Hash or Query string is empty
|
|
13558
|
+
logger.error(`The request has returned to the redirectUri but a ${responseLocation} is not present. It's likely that the ${responseLocation} has been removed or the page has been redirected by code running on the redirectUri page.`);
|
|
13559
|
+
throw createBrowserAuthError(hashEmptyError);
|
|
13560
|
+
}
|
|
13561
|
+
else {
|
|
13562
|
+
logger.error(`A ${responseLocation} is present in the iframe but it does not contain known properties. It's likely that the ${responseLocation} has been replaced by code running on the redirectUri page.`);
|
|
13563
|
+
logger.errorPii(`The ${responseLocation} detected is: ${responseString}`);
|
|
13564
|
+
throw createBrowserAuthError(hashDoesNotContainKnownProperties);
|
|
13565
|
+
}
|
|
13566
|
+
}
|
|
13567
|
+
return serverParams;
|
|
13568
|
+
}
|
|
13569
|
+
/**
|
|
13570
|
+
* Returns the interaction type that the response object belongs to
|
|
13571
|
+
*/
|
|
13572
|
+
function validateInteractionType(response, browserCrypto, interactionType) {
|
|
13573
|
+
if (!response.state) {
|
|
13574
|
+
throw createBrowserAuthError(noStateInHash);
|
|
13575
|
+
}
|
|
13576
|
+
const platformStateObj = extractBrowserRequestState(browserCrypto, response.state);
|
|
13577
|
+
if (!platformStateObj) {
|
|
13578
|
+
throw createBrowserAuthError(unableToParseState);
|
|
13579
|
+
}
|
|
13580
|
+
if (platformStateObj.interactionType !== interactionType) {
|
|
13581
|
+
throw createBrowserAuthError(stateInteractionTypeMismatch);
|
|
13582
|
+
}
|
|
13583
|
+
}
|
|
13584
|
+
|
|
13585
|
+
/*
|
|
13586
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
13587
|
+
* Licensed under the MIT License.
|
|
13588
|
+
*/
|
|
13589
|
+
/**
|
|
13590
|
+
* Abstract class which defines operations for a browser interaction handling class.
|
|
13591
|
+
*/
|
|
13592
|
+
class InteractionHandler {
|
|
13593
|
+
constructor(authCodeModule, storageImpl, authCodeRequest, logger, performanceClient) {
|
|
13594
|
+
this.authModule = authCodeModule;
|
|
13595
|
+
this.browserStorage = storageImpl;
|
|
13596
|
+
this.authCodeRequest = authCodeRequest;
|
|
13597
|
+
this.logger = logger;
|
|
13598
|
+
this.performanceClient = performanceClient;
|
|
13710
13599
|
}
|
|
13711
13600
|
/**
|
|
13712
|
-
*
|
|
13713
|
-
* @param
|
|
13714
|
-
* @param response
|
|
13601
|
+
* Function to handle response parameters from hash.
|
|
13602
|
+
* @param locationHash
|
|
13715
13603
|
*/
|
|
13716
|
-
async
|
|
13717
|
-
|
|
13718
|
-
|
|
13719
|
-
|
|
13720
|
-
|
|
13721
|
-
|
|
13722
|
-
|
|
13723
|
-
|
|
13724
|
-
|
|
13725
|
-
|
|
13726
|
-
|
|
13604
|
+
async handleCodeResponse(response, request) {
|
|
13605
|
+
this.performanceClient.addQueueMeasurement(PerformanceEvents.HandleCodeResponse, request.correlationId);
|
|
13606
|
+
let authCodeResponse;
|
|
13607
|
+
try {
|
|
13608
|
+
authCodeResponse = getAuthorizationCodePayload(response, request.state);
|
|
13609
|
+
}
|
|
13610
|
+
catch (e) {
|
|
13611
|
+
if (e instanceof ServerError &&
|
|
13612
|
+
e.subError === userCancelled) {
|
|
13613
|
+
// Translate server error caused by user closing native prompt to corresponding first class MSAL error
|
|
13614
|
+
throw createBrowserAuthError(userCancelled);
|
|
13727
13615
|
}
|
|
13728
|
-
|
|
13729
|
-
|
|
13730
|
-
const shrParameters = {
|
|
13731
|
-
resourceRequestMethod: request.resourceRequestMethod,
|
|
13732
|
-
resourceRequestUri: request.resourceRequestUri,
|
|
13733
|
-
shrClaims: request.shrClaims,
|
|
13734
|
-
shrNonce: request.shrNonce,
|
|
13735
|
-
};
|
|
13736
|
-
/**
|
|
13737
|
-
* KeyID must be present in the native request from when the PoP key was generated in order for
|
|
13738
|
-
* PopTokenGenerator to query the full key for signing
|
|
13739
|
-
*/
|
|
13740
|
-
if (!request.keyId) {
|
|
13741
|
-
throw createClientAuthError(keyIdMissing);
|
|
13616
|
+
else {
|
|
13617
|
+
throw e;
|
|
13742
13618
|
}
|
|
13743
|
-
|
|
13619
|
+
}
|
|
13620
|
+
return invokeAsync(this.handleCodeResponseFromServer.bind(this), PerformanceEvents.HandleCodeResponseFromServer, this.logger, this.performanceClient, request.correlationId)(authCodeResponse, request);
|
|
13621
|
+
}
|
|
13622
|
+
/**
|
|
13623
|
+
* Process auth code response from AAD
|
|
13624
|
+
* @param authCodeResponse
|
|
13625
|
+
* @param state
|
|
13626
|
+
* @param authority
|
|
13627
|
+
* @param networkModule
|
|
13628
|
+
* @returns
|
|
13629
|
+
*/
|
|
13630
|
+
async handleCodeResponseFromServer(authCodeResponse, request, validateNonce = true) {
|
|
13631
|
+
this.performanceClient.addQueueMeasurement(PerformanceEvents.HandleCodeResponseFromServer, request.correlationId);
|
|
13632
|
+
this.logger.trace("InteractionHandler.handleCodeResponseFromServer called");
|
|
13633
|
+
// Assign code to request
|
|
13634
|
+
this.authCodeRequest.code = authCodeResponse.code;
|
|
13635
|
+
// Check for new cloud instance
|
|
13636
|
+
if (authCodeResponse.cloud_instance_host_name) {
|
|
13637
|
+
await invokeAsync(this.authModule.updateAuthority.bind(this.authModule), PerformanceEvents.UpdateTokenEndpointAuthority, this.logger, this.performanceClient, request.correlationId)(authCodeResponse.cloud_instance_host_name, request.correlationId);
|
|
13638
|
+
}
|
|
13639
|
+
// Nonce validation not needed when redirect not involved (e.g. hybrid spa, renewing token via rt)
|
|
13640
|
+
if (validateNonce) {
|
|
13641
|
+
// TODO: Assigning "response nonce" to "request nonce" is confusing. Refactor the function doing validation to accept request nonce directly
|
|
13642
|
+
authCodeResponse.nonce = request.nonce || undefined;
|
|
13643
|
+
}
|
|
13644
|
+
authCodeResponse.state = request.state;
|
|
13645
|
+
// Add CCS parameters if available
|
|
13646
|
+
if (authCodeResponse.client_info) {
|
|
13647
|
+
this.authCodeRequest.clientInfo = authCodeResponse.client_info;
|
|
13744
13648
|
}
|
|
13745
13649
|
else {
|
|
13746
|
-
|
|
13650
|
+
const ccsCred = this.createCcsCredentials(request);
|
|
13651
|
+
if (ccsCred) {
|
|
13652
|
+
this.authCodeRequest.ccsCredential = ccsCred;
|
|
13653
|
+
}
|
|
13747
13654
|
}
|
|
13655
|
+
// Acquire token with retrieved code.
|
|
13656
|
+
const tokenResponse = (await invokeAsync(this.authModule.acquireToken.bind(this.authModule), PerformanceEvents.AuthClientAcquireToken, this.logger, this.performanceClient, request.correlationId)(this.authCodeRequest, authCodeResponse));
|
|
13657
|
+
return tokenResponse;
|
|
13748
13658
|
}
|
|
13749
13659
|
/**
|
|
13750
|
-
*
|
|
13751
|
-
* @param response
|
|
13752
|
-
* @param request
|
|
13753
|
-
* @param idTokenObj
|
|
13754
|
-
* @param accountEntity
|
|
13755
|
-
* @param authority
|
|
13756
|
-
* @param reqTimestamp
|
|
13757
|
-
* @returns
|
|
13660
|
+
* Build ccs creds if available
|
|
13758
13661
|
*/
|
|
13759
|
-
|
|
13760
|
-
|
|
13761
|
-
|
|
13762
|
-
|
|
13763
|
-
|
|
13764
|
-
|
|
13765
|
-
: ScopeSet.fromString(request.scope);
|
|
13766
|
-
const accountProperties = response.account.properties || {};
|
|
13767
|
-
const uid = accountProperties["UID"] ||
|
|
13768
|
-
idTokenClaims.oid ||
|
|
13769
|
-
idTokenClaims.sub ||
|
|
13770
|
-
Constants.EMPTY_STRING;
|
|
13771
|
-
const tid = accountProperties["TenantId"] ||
|
|
13772
|
-
idTokenClaims.tid ||
|
|
13773
|
-
Constants.EMPTY_STRING;
|
|
13774
|
-
const accountInfo = updateAccountTenantProfileData(accountEntity.getAccountInfo(), undefined, // tenantProfile optional
|
|
13775
|
-
idTokenClaims, response.id_token);
|
|
13776
|
-
/**
|
|
13777
|
-
* In pairwise broker flows, this check prevents the broker's native account id
|
|
13778
|
-
* from being returned over the embedded app's account id.
|
|
13779
|
-
*/
|
|
13780
|
-
if (accountInfo.nativeAccountId !== response.account.id) {
|
|
13781
|
-
accountInfo.nativeAccountId = response.account.id;
|
|
13662
|
+
createCcsCredentials(request) {
|
|
13663
|
+
if (request.account) {
|
|
13664
|
+
return {
|
|
13665
|
+
credential: request.account.homeAccountId,
|
|
13666
|
+
type: CcsCredentialType.HOME_ACCOUNT_ID,
|
|
13667
|
+
};
|
|
13782
13668
|
}
|
|
13783
|
-
|
|
13784
|
-
|
|
13785
|
-
|
|
13786
|
-
|
|
13787
|
-
|
|
13788
|
-
|
|
13789
|
-
|
|
13790
|
-
uniqueId: uid,
|
|
13791
|
-
tenantId: tid,
|
|
13792
|
-
scopes: responseScopes.asArray(),
|
|
13793
|
-
account: accountInfo,
|
|
13794
|
-
idToken: response.id_token,
|
|
13795
|
-
idTokenClaims: idTokenClaims,
|
|
13796
|
-
accessToken: responseAccessToken,
|
|
13797
|
-
fromCache: mats ? this.isResponseFromCache(mats) : false,
|
|
13798
|
-
// Request timestamp and NativeResponse expires_in are in seconds, converting to Date for AuthenticationResult
|
|
13799
|
-
expiresOn: toDateFromSeconds(reqTimestamp + response.expires_in),
|
|
13800
|
-
tokenType: tokenType,
|
|
13801
|
-
correlationId: this.correlationId,
|
|
13802
|
-
state: response.state,
|
|
13803
|
-
fromNativeBroker: true,
|
|
13804
|
-
};
|
|
13805
|
-
return result;
|
|
13669
|
+
else if (request.loginHint) {
|
|
13670
|
+
return {
|
|
13671
|
+
credential: request.loginHint,
|
|
13672
|
+
type: CcsCredentialType.UPN,
|
|
13673
|
+
};
|
|
13674
|
+
}
|
|
13675
|
+
return null;
|
|
13806
13676
|
}
|
|
13677
|
+
}
|
|
13678
|
+
|
|
13679
|
+
/*
|
|
13680
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
13681
|
+
* Licensed under the MIT License.
|
|
13682
|
+
*/
|
|
13683
|
+
class SilentCacheClient extends StandardInteractionClient {
|
|
13807
13684
|
/**
|
|
13808
|
-
*
|
|
13809
|
-
* @param
|
|
13685
|
+
* Returns unexpired tokens from the cache, if available
|
|
13686
|
+
* @param silentRequest
|
|
13810
13687
|
*/
|
|
13811
|
-
async
|
|
13812
|
-
|
|
13813
|
-
|
|
13814
|
-
|
|
13815
|
-
this.
|
|
13816
|
-
|
|
13688
|
+
async acquireToken(silentRequest) {
|
|
13689
|
+
this.performanceClient.addQueueMeasurement(PerformanceEvents.SilentCacheClientAcquireToken, silentRequest.correlationId);
|
|
13690
|
+
// Telemetry manager only used to increment cacheHits here
|
|
13691
|
+
const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenSilent_silentFlow);
|
|
13692
|
+
const clientConfig = await invokeAsync(this.getClientConfiguration.bind(this), PerformanceEvents.StandardInteractionClientGetClientConfiguration, this.logger, this.performanceClient, this.correlationId)({
|
|
13693
|
+
serverTelemetryManager,
|
|
13694
|
+
requestAuthority: silentRequest.authority,
|
|
13695
|
+
requestAzureCloudOptions: silentRequest.azureCloudOptions,
|
|
13696
|
+
account: silentRequest.account,
|
|
13817
13697
|
});
|
|
13698
|
+
const silentAuthClient = new SilentFlowClient(clientConfig, this.performanceClient);
|
|
13699
|
+
this.logger.verbose("Silent auth client created");
|
|
13700
|
+
try {
|
|
13701
|
+
const response = await invokeAsync(silentAuthClient.acquireCachedToken.bind(silentAuthClient), PerformanceEvents.SilentFlowClientAcquireCachedToken, this.logger, this.performanceClient, silentRequest.correlationId)(silentRequest);
|
|
13702
|
+
const authResponse = response[0];
|
|
13703
|
+
this.performanceClient.addFields({
|
|
13704
|
+
fromCache: true,
|
|
13705
|
+
}, silentRequest.correlationId);
|
|
13706
|
+
return authResponse;
|
|
13707
|
+
}
|
|
13708
|
+
catch (error) {
|
|
13709
|
+
if (error instanceof BrowserAuthError &&
|
|
13710
|
+
error.errorCode === cryptoKeyNotFound) {
|
|
13711
|
+
this.logger.verbose("Signing keypair for bound access token not found. Refreshing bound access token and generating a new crypto keypair.");
|
|
13712
|
+
}
|
|
13713
|
+
throw error;
|
|
13714
|
+
}
|
|
13818
13715
|
}
|
|
13819
13716
|
/**
|
|
13820
|
-
*
|
|
13821
|
-
* @param
|
|
13822
|
-
* @param request
|
|
13823
|
-
* @param homeAccountIdentifier
|
|
13824
|
-
* @param idTokenObj
|
|
13825
|
-
* @param responseAccessToken
|
|
13826
|
-
* @param tenantId
|
|
13827
|
-
* @param reqTimestamp
|
|
13717
|
+
* API to silenty clear the browser cache.
|
|
13718
|
+
* @param logoutRequest
|
|
13828
13719
|
*/
|
|
13829
|
-
|
|
13830
|
-
|
|
13831
|
-
|
|
13832
|
-
|
|
13833
|
-
? Constants.SHR_NONCE_VALIDITY
|
|
13834
|
-
: (typeof response.expires_in === "string"
|
|
13835
|
-
? parseInt(response.expires_in, 10)
|
|
13836
|
-
: response.expires_in) || 0;
|
|
13837
|
-
const tokenExpirationSeconds = reqTimestamp + expiresIn;
|
|
13838
|
-
const responseScopes = this.generateScopes(response, request);
|
|
13839
|
-
const cachedAccessToken = createAccessTokenEntity(homeAccountIdentifier, request.authority, responseAccessToken, request.clientId, idTokenClaims.tid || tenantId, responseScopes.printScopes(), tokenExpirationSeconds, 0, base64Decode, undefined, request.tokenType, undefined, request.keyId);
|
|
13840
|
-
const nativeCacheRecord = {
|
|
13841
|
-
idToken: cachedIdToken,
|
|
13842
|
-
accessToken: cachedAccessToken,
|
|
13843
|
-
};
|
|
13844
|
-
return this.nativeStorageManager.saveCacheRecord(nativeCacheRecord, this.correlationId, request.storeInCache);
|
|
13720
|
+
logout(logoutRequest) {
|
|
13721
|
+
this.logger.verbose("logoutRedirect called");
|
|
13722
|
+
const validLogoutRequest = this.initializeLogoutRequest(logoutRequest);
|
|
13723
|
+
return this.clearCacheOnLogout(validLogoutRequest?.account);
|
|
13845
13724
|
}
|
|
13846
|
-
|
|
13847
|
-
|
|
13848
|
-
|
|
13849
|
-
|
|
13850
|
-
|
|
13851
|
-
|
|
13852
|
-
|
|
13725
|
+
}
|
|
13726
|
+
|
|
13727
|
+
/*
|
|
13728
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
13729
|
+
* Licensed under the MIT License.
|
|
13730
|
+
*/
|
|
13731
|
+
class NativeInteractionClient extends BaseInteractionClient {
|
|
13732
|
+
constructor(config, browserStorage, browserCrypto, logger, eventHandler, navigationClient, apiId, performanceClient, provider, accountId, nativeStorageImpl, correlationId) {
|
|
13733
|
+
super(config, browserStorage, browserCrypto, logger, eventHandler, navigationClient, performanceClient, provider, correlationId);
|
|
13734
|
+
this.apiId = apiId;
|
|
13735
|
+
this.accountId = accountId;
|
|
13736
|
+
this.nativeMessageHandler = provider;
|
|
13737
|
+
this.nativeStorageManager = nativeStorageImpl;
|
|
13738
|
+
this.silentCacheClient = new SilentCacheClient(config, this.nativeStorageManager, browserCrypto, logger, eventHandler, navigationClient, performanceClient, provider, correlationId);
|
|
13739
|
+
const extensionName = this.nativeMessageHandler.getExtensionId() ===
|
|
13740
|
+
NativeConstants.PREFERRED_EXTENSION_ID
|
|
13741
|
+
? "chrome"
|
|
13742
|
+
: this.nativeMessageHandler.getExtensionId()?.length
|
|
13743
|
+
? "unknown"
|
|
13744
|
+
: undefined;
|
|
13745
|
+
this.skus = ServerTelemetryManager.makeExtraSkuString({
|
|
13746
|
+
libraryName: BrowserConstants.MSAL_SKU,
|
|
13747
|
+
libraryVersion: version,
|
|
13748
|
+
extensionName: extensionName,
|
|
13853
13749
|
extensionVersion: this.nativeMessageHandler.getExtensionVersion(),
|
|
13854
|
-
|
|
13855
|
-
matsAccountJoinOnStart: mats.account_join_on_start,
|
|
13856
|
-
matsAccountJoinOnEnd: mats.account_join_on_end,
|
|
13857
|
-
matsDeviceJoin: mats.device_join,
|
|
13858
|
-
matsPromptBehavior: mats.prompt_behavior,
|
|
13859
|
-
matsApiErrorCode: mats.api_error_code,
|
|
13860
|
-
matsUiVisible: mats.ui_visible,
|
|
13861
|
-
matsSilentCode: mats.silent_code,
|
|
13862
|
-
matsSilentBiSubCode: mats.silent_bi_sub_code,
|
|
13863
|
-
matsSilentMessage: mats.silent_message,
|
|
13864
|
-
matsSilentStatus: mats.silent_status,
|
|
13865
|
-
matsHttpStatus: mats.http_status,
|
|
13866
|
-
matsHttpEventCount: mats.http_event_count,
|
|
13867
|
-
}, this.correlationId);
|
|
13868
|
-
return mats;
|
|
13750
|
+
});
|
|
13869
13751
|
}
|
|
13870
13752
|
/**
|
|
13871
|
-
*
|
|
13872
|
-
* @param
|
|
13753
|
+
* Adds SKUs to request extra query parameters
|
|
13754
|
+
* @param request {NativeTokenRequest}
|
|
13755
|
+
* @private
|
|
13873
13756
|
*/
|
|
13874
|
-
|
|
13875
|
-
|
|
13876
|
-
|
|
13877
|
-
|
|
13878
|
-
|
|
13879
|
-
response.hasOwnProperty("scope") &&
|
|
13880
|
-
response.hasOwnProperty("expires_in")) {
|
|
13881
|
-
return response;
|
|
13882
|
-
}
|
|
13883
|
-
else {
|
|
13884
|
-
throw createAuthError(unexpectedError, "Response missing expected properties.");
|
|
13885
|
-
}
|
|
13757
|
+
addRequestSKUs(request) {
|
|
13758
|
+
request.extraParameters = {
|
|
13759
|
+
...request.extraParameters,
|
|
13760
|
+
[X_CLIENT_EXTRA_SKU]: this.skus,
|
|
13761
|
+
};
|
|
13886
13762
|
}
|
|
13887
13763
|
/**
|
|
13888
|
-
*
|
|
13889
|
-
* @param
|
|
13890
|
-
* @returns
|
|
13764
|
+
* Acquire token from native platform via browser extension
|
|
13765
|
+
* @param request
|
|
13891
13766
|
*/
|
|
13892
|
-
|
|
13893
|
-
|
|
13767
|
+
async acquireToken(request, cacheLookupPolicy) {
|
|
13768
|
+
this.performanceClient.addQueueMeasurement(PerformanceEvents.NativeInteractionClientAcquireToken, request.correlationId);
|
|
13769
|
+
this.logger.trace("NativeInteractionClient - acquireToken called.");
|
|
13770
|
+
// start the perf measurement
|
|
13771
|
+
const nativeATMeasurement = this.performanceClient.startMeasurement(PerformanceEvents.NativeInteractionClientAcquireToken, request.correlationId);
|
|
13772
|
+
const reqTimestamp = nowSeconds();
|
|
13773
|
+
const serverTelemetryManager = this.initializeServerTelemetryManager(this.apiId);
|
|
13774
|
+
try {
|
|
13775
|
+
// initialize native request
|
|
13776
|
+
const nativeRequest = await this.initializeNativeRequest(request);
|
|
13777
|
+
// check if the tokens can be retrieved from internal cache
|
|
13894
13778
|
try {
|
|
13895
|
-
|
|
13779
|
+
const result = await this.acquireTokensFromCache(this.accountId, nativeRequest);
|
|
13780
|
+
nativeATMeasurement.end({
|
|
13781
|
+
success: true,
|
|
13782
|
+
isNativeBroker: false,
|
|
13783
|
+
fromCache: true,
|
|
13784
|
+
});
|
|
13785
|
+
return result;
|
|
13896
13786
|
}
|
|
13897
13787
|
catch (e) {
|
|
13898
|
-
|
|
13788
|
+
if (cacheLookupPolicy === CacheLookupPolicy.AccessToken) {
|
|
13789
|
+
this.logger.info("MSAL internal Cache does not contain tokens, return error as per cache policy");
|
|
13790
|
+
throw e;
|
|
13791
|
+
}
|
|
13792
|
+
// continue with a native call for any and all errors
|
|
13793
|
+
this.logger.info("MSAL internal Cache does not contain tokens, proceed to make a native call");
|
|
13899
13794
|
}
|
|
13795
|
+
const { ...nativeTokenRequest } = nativeRequest;
|
|
13796
|
+
// fall back to native calls
|
|
13797
|
+
const messageBody = {
|
|
13798
|
+
method: NativeExtensionMethod.GetToken,
|
|
13799
|
+
request: nativeTokenRequest,
|
|
13800
|
+
};
|
|
13801
|
+
const response = await this.nativeMessageHandler.sendMessage(messageBody);
|
|
13802
|
+
const validatedResponse = this.validateNativeResponse(response);
|
|
13803
|
+
return await this.handleNativeResponse(validatedResponse, nativeRequest, reqTimestamp)
|
|
13804
|
+
.then((result) => {
|
|
13805
|
+
nativeATMeasurement.end({
|
|
13806
|
+
success: true,
|
|
13807
|
+
isNativeBroker: true,
|
|
13808
|
+
requestId: result.requestId,
|
|
13809
|
+
});
|
|
13810
|
+
serverTelemetryManager.clearNativeBrokerErrorCode();
|
|
13811
|
+
return result;
|
|
13812
|
+
})
|
|
13813
|
+
.catch((error) => {
|
|
13814
|
+
nativeATMeasurement.end({
|
|
13815
|
+
success: false,
|
|
13816
|
+
errorCode: error.errorCode,
|
|
13817
|
+
subErrorCode: error.subError,
|
|
13818
|
+
isNativeBroker: true,
|
|
13819
|
+
});
|
|
13820
|
+
throw error;
|
|
13821
|
+
});
|
|
13900
13822
|
}
|
|
13901
|
-
|
|
13902
|
-
|
|
13903
|
-
|
|
13904
|
-
|
|
13905
|
-
|
|
13906
|
-
* @returns
|
|
13907
|
-
*/
|
|
13908
|
-
isResponseFromCache(mats) {
|
|
13909
|
-
if (typeof mats.is_cached === "undefined") {
|
|
13910
|
-
this.logger.verbose("NativeInteractionClient - MATS telemetry does not contain field indicating if response was served from cache. Returning false.");
|
|
13911
|
-
return false;
|
|
13823
|
+
catch (e) {
|
|
13824
|
+
if (e instanceof NativeAuthError) {
|
|
13825
|
+
serverTelemetryManager.setNativeBrokerErrorCode(e.errorCode);
|
|
13826
|
+
}
|
|
13827
|
+
throw e;
|
|
13912
13828
|
}
|
|
13913
|
-
return !!mats.is_cached;
|
|
13914
13829
|
}
|
|
13915
13830
|
/**
|
|
13916
|
-
*
|
|
13831
|
+
* Creates silent flow request
|
|
13917
13832
|
* @param request
|
|
13833
|
+
* @param cachedAccount
|
|
13834
|
+
* @returns CommonSilentFlowRequest
|
|
13918
13835
|
*/
|
|
13919
|
-
|
|
13920
|
-
|
|
13921
|
-
|
|
13922
|
-
if (request.account) {
|
|
13923
|
-
// validate authority
|
|
13924
|
-
await this.getDiscoveredAuthority({
|
|
13925
|
-
requestAuthority,
|
|
13926
|
-
requestAzureCloudOptions: request.azureCloudOptions,
|
|
13927
|
-
account: request.account,
|
|
13928
|
-
});
|
|
13929
|
-
}
|
|
13930
|
-
const canonicalAuthority = new UrlString(requestAuthority);
|
|
13931
|
-
canonicalAuthority.validateAsUri();
|
|
13932
|
-
// scopes are expected to be received by the native broker as "scope" and will be added to the request below. Other properties that should be dropped from the request to the native broker can be included in the object destructuring here.
|
|
13933
|
-
const { scopes, ...remainingProperties } = request;
|
|
13934
|
-
const scopeSet = new ScopeSet(scopes || []);
|
|
13935
|
-
scopeSet.appendScopes(OIDC_DEFAULT_SCOPES);
|
|
13936
|
-
const getPrompt = () => {
|
|
13937
|
-
// If request is silent, prompt is always none
|
|
13938
|
-
switch (this.apiId) {
|
|
13939
|
-
case ApiId.ssoSilent:
|
|
13940
|
-
case ApiId.acquireTokenSilent_silentFlow:
|
|
13941
|
-
this.logger.trace("initializeNativeRequest: silent request sets prompt to none");
|
|
13942
|
-
return PromptValue.NONE;
|
|
13943
|
-
}
|
|
13944
|
-
// Prompt not provided, request may proceed and native broker decides if it needs to prompt
|
|
13945
|
-
if (!request.prompt) {
|
|
13946
|
-
this.logger.trace("initializeNativeRequest: prompt was not provided");
|
|
13947
|
-
return undefined;
|
|
13948
|
-
}
|
|
13949
|
-
// If request is interactive, check if prompt provided is allowed to go directly to native broker
|
|
13950
|
-
switch (request.prompt) {
|
|
13951
|
-
case PromptValue.NONE:
|
|
13952
|
-
case PromptValue.CONSENT:
|
|
13953
|
-
case PromptValue.LOGIN:
|
|
13954
|
-
this.logger.trace("initializeNativeRequest: prompt is compatible with native flow");
|
|
13955
|
-
return request.prompt;
|
|
13956
|
-
default:
|
|
13957
|
-
this.logger.trace(`initializeNativeRequest: prompt = ${request.prompt} is not compatible with native flow`);
|
|
13958
|
-
throw createBrowserAuthError(nativePromptNotSupported);
|
|
13959
|
-
}
|
|
13960
|
-
};
|
|
13961
|
-
const validatedRequest = {
|
|
13962
|
-
...remainingProperties,
|
|
13963
|
-
accountId: this.accountId,
|
|
13964
|
-
clientId: this.config.auth.clientId,
|
|
13965
|
-
authority: canonicalAuthority.urlString,
|
|
13966
|
-
scope: scopeSet.printScopes(),
|
|
13967
|
-
redirectUri: this.getRedirectUri(request.redirectUri),
|
|
13968
|
-
prompt: getPrompt(),
|
|
13836
|
+
createSilentCacheRequest(request, cachedAccount) {
|
|
13837
|
+
return {
|
|
13838
|
+
authority: request.authority,
|
|
13969
13839
|
correlationId: this.correlationId,
|
|
13970
|
-
|
|
13971
|
-
|
|
13972
|
-
|
|
13973
|
-
...request.extraQueryParameters,
|
|
13974
|
-
...request.tokenQueryParameters,
|
|
13975
|
-
},
|
|
13976
|
-
extendedExpiryToken: false,
|
|
13977
|
-
keyId: request.popKid,
|
|
13840
|
+
scopes: ScopeSet.fromString(request.scope).asArray(),
|
|
13841
|
+
account: cachedAccount,
|
|
13842
|
+
forceRefresh: false,
|
|
13978
13843
|
};
|
|
13979
|
-
// Check for PoP token requests: signPopToken should only be set to true if popKid is not set
|
|
13980
|
-
if (validatedRequest.signPopToken && !!request.popKid) {
|
|
13981
|
-
throw createBrowserAuthError(invalidPopTokenRequest);
|
|
13982
|
-
}
|
|
13983
|
-
this.handleExtraBrokerParams(validatedRequest);
|
|
13984
|
-
validatedRequest.extraParameters =
|
|
13985
|
-
validatedRequest.extraParameters || {};
|
|
13986
|
-
validatedRequest.extraParameters.telemetry =
|
|
13987
|
-
NativeConstants.MATS_TELEMETRY;
|
|
13988
|
-
if (request.authenticationScheme === AuthenticationScheme.POP) {
|
|
13989
|
-
// add POP request type
|
|
13990
|
-
const shrParameters = {
|
|
13991
|
-
resourceRequestUri: request.resourceRequestUri,
|
|
13992
|
-
resourceRequestMethod: request.resourceRequestMethod,
|
|
13993
|
-
shrClaims: request.shrClaims,
|
|
13994
|
-
shrNonce: request.shrNonce,
|
|
13995
|
-
};
|
|
13996
|
-
const popTokenGenerator = new PopTokenGenerator(this.browserCrypto);
|
|
13997
|
-
// generate reqCnf if not provided in the request
|
|
13998
|
-
let reqCnfData;
|
|
13999
|
-
if (!validatedRequest.keyId) {
|
|
14000
|
-
const generatedReqCnfData = await invokeAsync(popTokenGenerator.generateCnf.bind(popTokenGenerator), PerformanceEvents.PopTokenGenerateCnf, this.logger, this.performanceClient, request.correlationId)(shrParameters, this.logger);
|
|
14001
|
-
reqCnfData = generatedReqCnfData.reqCnfString;
|
|
14002
|
-
validatedRequest.keyId = generatedReqCnfData.kid;
|
|
14003
|
-
validatedRequest.signPopToken = true;
|
|
14004
|
-
}
|
|
14005
|
-
else {
|
|
14006
|
-
reqCnfData = this.browserCrypto.base64UrlEncode(JSON.stringify({ kid: validatedRequest.keyId }));
|
|
14007
|
-
validatedRequest.signPopToken = false;
|
|
14008
|
-
}
|
|
14009
|
-
// SPAs require whole string to be passed to broker
|
|
14010
|
-
validatedRequest.reqCnf = reqCnfData;
|
|
14011
|
-
}
|
|
14012
|
-
this.addRequestSKUs(validatedRequest);
|
|
14013
|
-
return validatedRequest;
|
|
14014
13844
|
}
|
|
14015
13845
|
/**
|
|
14016
|
-
*
|
|
14017
|
-
* @param
|
|
14018
|
-
* @
|
|
13846
|
+
* Fetches the tokens from the cache if un-expired
|
|
13847
|
+
* @param nativeAccountId
|
|
13848
|
+
* @param request
|
|
13849
|
+
* @returns authenticationResult
|
|
14019
13850
|
*/
|
|
14020
|
-
|
|
14021
|
-
|
|
14022
|
-
|
|
14023
|
-
|
|
14024
|
-
request.extraParameters.hasOwnProperty(CLIENT_ID);
|
|
14025
|
-
if (!request.embeddedClientId && !hasExtraBrokerParams) {
|
|
14026
|
-
return;
|
|
13851
|
+
async acquireTokensFromCache(nativeAccountId, request) {
|
|
13852
|
+
if (!nativeAccountId) {
|
|
13853
|
+
this.logger.warning("NativeInteractionClient:acquireTokensFromCache - No nativeAccountId provided");
|
|
13854
|
+
throw createClientAuthError(noAccountFound);
|
|
14027
13855
|
}
|
|
14028
|
-
|
|
14029
|
-
const
|
|
14030
|
-
|
|
14031
|
-
|
|
14032
|
-
|
|
13856
|
+
// fetch the account from browser cache
|
|
13857
|
+
const account = this.browserStorage.getBaseAccountInfo({
|
|
13858
|
+
nativeAccountId,
|
|
13859
|
+
});
|
|
13860
|
+
if (!account) {
|
|
13861
|
+
throw createClientAuthError(noAccountFound);
|
|
14033
13862
|
}
|
|
14034
|
-
|
|
14035
|
-
|
|
14036
|
-
|
|
14037
|
-
|
|
14038
|
-
|
|
13863
|
+
// leverage silent flow for cached tokens retrieval
|
|
13864
|
+
try {
|
|
13865
|
+
const silentRequest = this.createSilentCacheRequest(request, account);
|
|
13866
|
+
const result = await this.silentCacheClient.acquireToken(silentRequest);
|
|
13867
|
+
const fullAccount = {
|
|
13868
|
+
...account,
|
|
13869
|
+
idTokenClaims: result?.idTokenClaims,
|
|
13870
|
+
idToken: result?.idToken,
|
|
13871
|
+
};
|
|
13872
|
+
return {
|
|
13873
|
+
...result,
|
|
13874
|
+
account: fullAccount,
|
|
13875
|
+
};
|
|
13876
|
+
}
|
|
13877
|
+
catch (e) {
|
|
13878
|
+
throw e;
|
|
14039
13879
|
}
|
|
14040
|
-
request.extraParameters = {
|
|
14041
|
-
child_client_id,
|
|
14042
|
-
child_redirect_uri,
|
|
14043
|
-
};
|
|
14044
|
-
this.performanceClient?.addFields({
|
|
14045
|
-
embeddedClientId: child_client_id,
|
|
14046
|
-
embeddedRedirectUri: child_redirect_uri,
|
|
14047
|
-
}, request.correlationId);
|
|
14048
|
-
}
|
|
14049
|
-
}
|
|
14050
|
-
|
|
14051
|
-
/*
|
|
14052
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
14053
|
-
* Licensed under the MIT License.
|
|
14054
|
-
*/
|
|
14055
|
-
class NativeMessageHandler {
|
|
14056
|
-
constructor(logger, handshakeTimeoutMs, performanceClient, extensionId) {
|
|
14057
|
-
this.logger = logger;
|
|
14058
|
-
this.handshakeTimeoutMs = handshakeTimeoutMs;
|
|
14059
|
-
this.extensionId = extensionId;
|
|
14060
|
-
this.resolvers = new Map(); // Used for non-handshake messages
|
|
14061
|
-
this.handshakeResolvers = new Map(); // Used for handshake messages
|
|
14062
|
-
this.messageChannel = new MessageChannel();
|
|
14063
|
-
this.windowListener = this.onWindowMessage.bind(this); // Window event callback doesn't have access to 'this' unless it's bound
|
|
14064
|
-
this.performanceClient = performanceClient;
|
|
14065
|
-
this.handshakeEvent = performanceClient.startMeasurement(PerformanceEvents.NativeMessageHandlerHandshake);
|
|
14066
13880
|
}
|
|
14067
13881
|
/**
|
|
14068
|
-
*
|
|
14069
|
-
* @param
|
|
13882
|
+
* Acquires a token from native platform then redirects to the redirectUri instead of returning the response
|
|
13883
|
+
* @param {RedirectRequest} request
|
|
13884
|
+
* @param {InProgressPerformanceEvent} rootMeasurement
|
|
14070
13885
|
*/
|
|
14071
|
-
async
|
|
14072
|
-
this.logger.trace("
|
|
14073
|
-
const
|
|
14074
|
-
|
|
14075
|
-
|
|
14076
|
-
|
|
14077
|
-
|
|
13886
|
+
async acquireTokenRedirect(request, rootMeasurement) {
|
|
13887
|
+
this.logger.trace("NativeInteractionClient - acquireTokenRedirect called.");
|
|
13888
|
+
const { ...remainingParameters } = request;
|
|
13889
|
+
delete remainingParameters.onRedirectNavigate;
|
|
13890
|
+
const nativeRequest = await this.initializeNativeRequest(remainingParameters);
|
|
13891
|
+
const messageBody = {
|
|
13892
|
+
method: NativeExtensionMethod.GetToken,
|
|
13893
|
+
request: nativeRequest,
|
|
14078
13894
|
};
|
|
14079
|
-
|
|
14080
|
-
|
|
14081
|
-
|
|
14082
|
-
|
|
14083
|
-
|
|
14084
|
-
|
|
13895
|
+
try {
|
|
13896
|
+
const response = await this.nativeMessageHandler.sendMessage(messageBody);
|
|
13897
|
+
this.validateNativeResponse(response);
|
|
13898
|
+
}
|
|
13899
|
+
catch (e) {
|
|
13900
|
+
// Only throw fatal errors here to allow application to fallback to regular redirect. Otherwise proceed and the error will be thrown in handleRedirectPromise
|
|
13901
|
+
if (e instanceof NativeAuthError) {
|
|
13902
|
+
const serverTelemetryManager = this.initializeServerTelemetryManager(this.apiId);
|
|
13903
|
+
serverTelemetryManager.setNativeBrokerErrorCode(e.errorCode);
|
|
13904
|
+
if (isFatalNativeAuthError(e)) {
|
|
13905
|
+
throw e;
|
|
13906
|
+
}
|
|
13907
|
+
}
|
|
13908
|
+
}
|
|
13909
|
+
this.browserStorage.setTemporaryCache(TemporaryCacheKeys.NATIVE_REQUEST, JSON.stringify(nativeRequest), true);
|
|
13910
|
+
const navigationOptions = {
|
|
13911
|
+
apiId: ApiId.acquireTokenRedirect,
|
|
13912
|
+
timeout: this.config.system.redirectNavigationTimeout,
|
|
13913
|
+
noHistory: false,
|
|
13914
|
+
};
|
|
13915
|
+
const redirectUri = this.config.auth.navigateToLoginRequestUrl
|
|
13916
|
+
? window.location.href
|
|
13917
|
+
: this.getRedirectUri(request.redirectUri);
|
|
13918
|
+
rootMeasurement.end({ success: true });
|
|
13919
|
+
await this.navigationClient.navigateExternal(redirectUri, navigationOptions); // Need to treat this as external to ensure handleRedirectPromise is run again
|
|
14085
13920
|
}
|
|
14086
13921
|
/**
|
|
14087
|
-
*
|
|
14088
|
-
* @param {
|
|
14089
|
-
* @param {
|
|
14090
|
-
* @param {IPerformanceClient} performanceClient
|
|
14091
|
-
* @param {ICrypto} crypto
|
|
13922
|
+
* If the previous page called native platform for a token using redirect APIs, send the same request again and return the response
|
|
13923
|
+
* @param performanceClient {IPerformanceClient?}
|
|
13924
|
+
* @param correlationId {string?} correlation identifier
|
|
14092
13925
|
*/
|
|
14093
|
-
|
|
14094
|
-
logger.trace("
|
|
13926
|
+
async handleRedirectPromise(performanceClient, correlationId) {
|
|
13927
|
+
this.logger.trace("NativeInteractionClient - handleRedirectPromise called.");
|
|
13928
|
+
if (!this.browserStorage.isInteractionInProgress(true)) {
|
|
13929
|
+
this.logger.info("handleRedirectPromise called but there is no interaction in progress, returning null.");
|
|
13930
|
+
return null;
|
|
13931
|
+
}
|
|
13932
|
+
// remove prompt from the request to prevent WAM from prompting twice
|
|
13933
|
+
const cachedRequest = this.browserStorage.getCachedNativeRequest();
|
|
13934
|
+
if (!cachedRequest) {
|
|
13935
|
+
this.logger.verbose("NativeInteractionClient - handleRedirectPromise called but there is no cached request, returning null.");
|
|
13936
|
+
if (performanceClient && correlationId) {
|
|
13937
|
+
performanceClient?.addFields({ errorCode: "no_cached_request" }, correlationId);
|
|
13938
|
+
}
|
|
13939
|
+
return null;
|
|
13940
|
+
}
|
|
13941
|
+
const { prompt, ...request } = cachedRequest;
|
|
13942
|
+
if (prompt) {
|
|
13943
|
+
this.logger.verbose("NativeInteractionClient - handleRedirectPromise called and prompt was included in the original request, removing prompt from cached request to prevent second interaction with native broker window.");
|
|
13944
|
+
}
|
|
13945
|
+
this.browserStorage.removeItem(this.browserStorage.generateCacheKey(TemporaryCacheKeys.NATIVE_REQUEST));
|
|
13946
|
+
const messageBody = {
|
|
13947
|
+
method: NativeExtensionMethod.GetToken,
|
|
13948
|
+
request: request,
|
|
13949
|
+
};
|
|
13950
|
+
const reqTimestamp = nowSeconds();
|
|
14095
13951
|
try {
|
|
14096
|
-
|
|
14097
|
-
await
|
|
14098
|
-
|
|
13952
|
+
this.logger.verbose("NativeInteractionClient - handleRedirectPromise sending message to native broker.");
|
|
13953
|
+
const response = await this.nativeMessageHandler.sendMessage(messageBody);
|
|
13954
|
+
this.validateNativeResponse(response);
|
|
13955
|
+
const result = this.handleNativeResponse(response, request, reqTimestamp);
|
|
13956
|
+
const res = await result;
|
|
13957
|
+
const serverTelemetryManager = this.initializeServerTelemetryManager(this.apiId);
|
|
13958
|
+
serverTelemetryManager.clearNativeBrokerErrorCode();
|
|
13959
|
+
return res;
|
|
14099
13960
|
}
|
|
14100
13961
|
catch (e) {
|
|
14101
|
-
|
|
14102
|
-
const backupProvider = new NativeMessageHandler(logger, handshakeTimeoutMs, performanceClient);
|
|
14103
|
-
await backupProvider.sendHandshakeRequest();
|
|
14104
|
-
return backupProvider;
|
|
13962
|
+
throw e;
|
|
14105
13963
|
}
|
|
14106
13964
|
}
|
|
14107
13965
|
/**
|
|
14108
|
-
*
|
|
13966
|
+
* Logout from native platform via browser extension
|
|
13967
|
+
* @param request
|
|
14109
13968
|
*/
|
|
14110
|
-
|
|
14111
|
-
this.logger.trace("
|
|
14112
|
-
|
|
14113
|
-
window.addEventListener("message", this.windowListener, false); // false is important, because content script message processing should work first
|
|
14114
|
-
const req = {
|
|
14115
|
-
channel: NativeConstants.CHANNEL_ID,
|
|
14116
|
-
extensionId: this.extensionId,
|
|
14117
|
-
responseId: createNewGuid(),
|
|
14118
|
-
body: {
|
|
14119
|
-
method: NativeExtensionMethod.HandshakeRequest,
|
|
14120
|
-
},
|
|
14121
|
-
};
|
|
14122
|
-
this.handshakeEvent.add({
|
|
14123
|
-
extensionId: this.extensionId,
|
|
14124
|
-
extensionHandshakeTimeoutMs: this.handshakeTimeoutMs,
|
|
14125
|
-
});
|
|
14126
|
-
this.messageChannel.port1.onmessage = (event) => {
|
|
14127
|
-
this.onChannelMessage(event);
|
|
14128
|
-
};
|
|
14129
|
-
window.postMessage(req, window.origin, [this.messageChannel.port2]);
|
|
14130
|
-
return new Promise((resolve, reject) => {
|
|
14131
|
-
this.handshakeResolvers.set(req.responseId, { resolve, reject });
|
|
14132
|
-
this.timeoutId = window.setTimeout(() => {
|
|
14133
|
-
/*
|
|
14134
|
-
* Throw an error if neither HandshakeResponse nor original Handshake request are received in a reasonable timeframe.
|
|
14135
|
-
* This typically suggests an event handler stopped propagation of the Handshake request but did not respond to it on the MessageChannel port
|
|
14136
|
-
*/
|
|
14137
|
-
window.removeEventListener("message", this.windowListener, false);
|
|
14138
|
-
this.messageChannel.port1.close();
|
|
14139
|
-
this.messageChannel.port2.close();
|
|
14140
|
-
this.handshakeEvent.end({
|
|
14141
|
-
extensionHandshakeTimedOut: true,
|
|
14142
|
-
success: false,
|
|
14143
|
-
});
|
|
14144
|
-
reject(createBrowserAuthError(nativeHandshakeTimeout));
|
|
14145
|
-
this.handshakeResolvers.delete(req.responseId);
|
|
14146
|
-
}, this.handshakeTimeoutMs); // Use a reasonable timeout in milliseconds here
|
|
14147
|
-
});
|
|
13969
|
+
logout() {
|
|
13970
|
+
this.logger.trace("NativeInteractionClient - logout called.");
|
|
13971
|
+
return Promise.reject("Logout not implemented yet");
|
|
14148
13972
|
}
|
|
14149
13973
|
/**
|
|
14150
|
-
*
|
|
14151
|
-
* @param
|
|
13974
|
+
* Transform response from native platform into AuthenticationResult object which will be returned to the end user
|
|
13975
|
+
* @param response
|
|
13976
|
+
* @param request
|
|
13977
|
+
* @param reqTimestamp
|
|
14152
13978
|
*/
|
|
14153
|
-
|
|
14154
|
-
this.logger.trace("
|
|
14155
|
-
//
|
|
14156
|
-
|
|
14157
|
-
|
|
14158
|
-
|
|
14159
|
-
|
|
14160
|
-
|
|
14161
|
-
|
|
14162
|
-
|
|
14163
|
-
|
|
14164
|
-
|
|
14165
|
-
return;
|
|
13979
|
+
async handleNativeResponse(response, request, reqTimestamp) {
|
|
13980
|
+
this.logger.trace("NativeInteractionClient - handleNativeResponse called.");
|
|
13981
|
+
// generate identifiers
|
|
13982
|
+
const idTokenClaims = extractTokenClaims(response.id_token, base64Decode);
|
|
13983
|
+
const homeAccountIdentifier = this.createHomeAccountIdentifier(response, idTokenClaims);
|
|
13984
|
+
const cachedhomeAccountId = this.browserStorage.getAccountInfoFilteredBy({
|
|
13985
|
+
nativeAccountId: request.accountId,
|
|
13986
|
+
})?.homeAccountId;
|
|
13987
|
+
// add exception for double brokering, please note this is temporary and will be fortified in future
|
|
13988
|
+
if (request.extraParameters?.child_client_id &&
|
|
13989
|
+
response.account.id !== request.accountId) {
|
|
13990
|
+
this.logger.info("handleNativeServerResponse: Double broker flow detected, ignoring accountId mismatch");
|
|
14166
13991
|
}
|
|
14167
|
-
if (
|
|
14168
|
-
|
|
14169
|
-
|
|
14170
|
-
|
|
14171
|
-
* the proper response.
|
|
14172
|
-
*/
|
|
14173
|
-
if (!handshakeResolver) {
|
|
14174
|
-
this.logger.trace(`NativeMessageHandler.onWindowMessage - resolver can't be found for request ${request.responseId}`);
|
|
14175
|
-
return;
|
|
14176
|
-
}
|
|
14177
|
-
// If we receive this message back it means no extension intercepted the request, meaning no extension supporting handshake protocol is installed
|
|
14178
|
-
this.logger.verbose(request.extensionId
|
|
14179
|
-
? `Extension with id: ${request.extensionId} not installed`
|
|
14180
|
-
: "No extension installed");
|
|
14181
|
-
clearTimeout(this.timeoutId);
|
|
14182
|
-
this.messageChannel.port1.close();
|
|
14183
|
-
this.messageChannel.port2.close();
|
|
14184
|
-
window.removeEventListener("message", this.windowListener, false);
|
|
14185
|
-
this.handshakeEvent.end({
|
|
14186
|
-
success: false,
|
|
14187
|
-
extensionInstalled: false,
|
|
14188
|
-
});
|
|
14189
|
-
handshakeResolver.reject(createBrowserAuthError(nativeExtensionNotInstalled));
|
|
13992
|
+
else if (homeAccountIdentifier !== cachedhomeAccountId &&
|
|
13993
|
+
response.account.id !== request.accountId) {
|
|
13994
|
+
// User switch in native broker prompt is not supported. All users must first sign in through web flow to ensure server state is in sync
|
|
13995
|
+
throw createNativeAuthError(userSwitch);
|
|
14190
13996
|
}
|
|
13997
|
+
// Get the preferred_cache domain for the given authority
|
|
13998
|
+
const authority = await this.getDiscoveredAuthority({
|
|
13999
|
+
requestAuthority: request.authority,
|
|
14000
|
+
});
|
|
14001
|
+
const baseAccount = buildAccountToCache(this.browserStorage, authority, homeAccountIdentifier, base64Decode, idTokenClaims, response.client_info, undefined, // environment
|
|
14002
|
+
idTokenClaims.tid, undefined, // auth code payload
|
|
14003
|
+
response.account.id, this.logger);
|
|
14004
|
+
// Ensure expires_in is in number format
|
|
14005
|
+
response.expires_in = Number(response.expires_in);
|
|
14006
|
+
// generate authenticationResult
|
|
14007
|
+
const result = await this.generateAuthenticationResult(response, request, idTokenClaims, baseAccount, authority.canonicalAuthority, reqTimestamp);
|
|
14008
|
+
// cache accounts and tokens in the appropriate storage
|
|
14009
|
+
await this.cacheAccount(baseAccount);
|
|
14010
|
+
await this.cacheNativeTokens(response, request, homeAccountIdentifier, idTokenClaims, response.access_token, result.tenantId, reqTimestamp);
|
|
14011
|
+
return result;
|
|
14191
14012
|
}
|
|
14192
14013
|
/**
|
|
14193
|
-
*
|
|
14194
|
-
* @param
|
|
14014
|
+
* creates an homeAccountIdentifier for the account
|
|
14015
|
+
* @param response
|
|
14016
|
+
* @param idTokenObj
|
|
14017
|
+
* @returns
|
|
14195
14018
|
*/
|
|
14196
|
-
|
|
14197
|
-
|
|
14198
|
-
const
|
|
14199
|
-
|
|
14200
|
-
|
|
14201
|
-
|
|
14202
|
-
|
|
14203
|
-
|
|
14204
|
-
|
|
14205
|
-
|
|
14206
|
-
|
|
14207
|
-
|
|
14208
|
-
|
|
14209
|
-
|
|
14210
|
-
|
|
14211
|
-
|
|
14212
|
-
|
|
14213
|
-
|
|
14214
|
-
|
|
14215
|
-
|
|
14216
|
-
|
|
14217
|
-
|
|
14218
|
-
|
|
14219
|
-
|
|
14220
|
-
|
|
14221
|
-
|
|
14222
|
-
|
|
14223
|
-
|
|
14224
|
-
|
|
14225
|
-
|
|
14019
|
+
createHomeAccountIdentifier(response, idTokenClaims) {
|
|
14020
|
+
// Save account in browser storage
|
|
14021
|
+
const homeAccountIdentifier = AccountEntity.generateHomeAccountId(response.client_info || Constants.EMPTY_STRING, AuthorityType.Default, this.logger, this.browserCrypto, idTokenClaims);
|
|
14022
|
+
return homeAccountIdentifier;
|
|
14023
|
+
}
|
|
14024
|
+
/**
|
|
14025
|
+
* Helper to generate scopes
|
|
14026
|
+
* @param response
|
|
14027
|
+
* @param request
|
|
14028
|
+
* @returns
|
|
14029
|
+
*/
|
|
14030
|
+
generateScopes(response, request) {
|
|
14031
|
+
return response.scope
|
|
14032
|
+
? ScopeSet.fromString(response.scope)
|
|
14033
|
+
: ScopeSet.fromString(request.scope);
|
|
14034
|
+
}
|
|
14035
|
+
/**
|
|
14036
|
+
* If PoP token is requesred, records the PoP token if returned from the WAM, else generates one in the browser
|
|
14037
|
+
* @param request
|
|
14038
|
+
* @param response
|
|
14039
|
+
*/
|
|
14040
|
+
async generatePopAccessToken(response, request) {
|
|
14041
|
+
if (request.tokenType === AuthenticationScheme.POP &&
|
|
14042
|
+
request.signPopToken) {
|
|
14043
|
+
/**
|
|
14044
|
+
* This code prioritizes SHR returned from the native layer. In case of error/SHR not calculated from WAM and the AT
|
|
14045
|
+
* is still received, SHR is calculated locally
|
|
14046
|
+
*/
|
|
14047
|
+
// Check if native layer returned an SHR token
|
|
14048
|
+
if (response.shr) {
|
|
14049
|
+
this.logger.trace("handleNativeServerResponse: SHR is enabled in native layer");
|
|
14050
|
+
return response.shr;
|
|
14226
14051
|
}
|
|
14227
|
-
|
|
14228
|
-
|
|
14229
|
-
|
|
14230
|
-
|
|
14231
|
-
|
|
14232
|
-
|
|
14233
|
-
|
|
14234
|
-
|
|
14235
|
-
|
|
14236
|
-
|
|
14237
|
-
|
|
14238
|
-
|
|
14239
|
-
|
|
14240
|
-
|
|
14241
|
-
handshakeResolver.resolve();
|
|
14242
|
-
this.handshakeResolvers.delete(request.responseId);
|
|
14052
|
+
// Generate SHR in msal js if WAM does not compute it when POP is enabled
|
|
14053
|
+
const popTokenGenerator = new PopTokenGenerator(this.browserCrypto);
|
|
14054
|
+
const shrParameters = {
|
|
14055
|
+
resourceRequestMethod: request.resourceRequestMethod,
|
|
14056
|
+
resourceRequestUri: request.resourceRequestUri,
|
|
14057
|
+
shrClaims: request.shrClaims,
|
|
14058
|
+
shrNonce: request.shrNonce,
|
|
14059
|
+
};
|
|
14060
|
+
/**
|
|
14061
|
+
* KeyID must be present in the native request from when the PoP key was generated in order for
|
|
14062
|
+
* PopTokenGenerator to query the full key for signing
|
|
14063
|
+
*/
|
|
14064
|
+
if (!request.keyId) {
|
|
14065
|
+
throw createClientAuthError(keyIdMissing);
|
|
14243
14066
|
}
|
|
14244
|
-
|
|
14067
|
+
return popTokenGenerator.signPopToken(response.access_token, request.keyId, shrParameters);
|
|
14245
14068
|
}
|
|
14246
|
-
|
|
14247
|
-
|
|
14248
|
-
this.logger.errorPii(`Error parsing response from WAM Extension: ${err}`);
|
|
14249
|
-
this.logger.errorPii(`Unable to parse ${event}`);
|
|
14250
|
-
if (resolver) {
|
|
14251
|
-
resolver.reject(err);
|
|
14252
|
-
}
|
|
14253
|
-
else if (handshakeResolver) {
|
|
14254
|
-
handshakeResolver.reject(err);
|
|
14255
|
-
}
|
|
14069
|
+
else {
|
|
14070
|
+
return response.access_token;
|
|
14256
14071
|
}
|
|
14257
14072
|
}
|
|
14258
14073
|
/**
|
|
14259
|
-
*
|
|
14074
|
+
* Generates authentication result
|
|
14075
|
+
* @param response
|
|
14076
|
+
* @param request
|
|
14077
|
+
* @param idTokenObj
|
|
14078
|
+
* @param accountEntity
|
|
14079
|
+
* @param authority
|
|
14080
|
+
* @param reqTimestamp
|
|
14260
14081
|
* @returns
|
|
14261
14082
|
*/
|
|
14262
|
-
|
|
14263
|
-
|
|
14083
|
+
async generateAuthenticationResult(response, request, idTokenClaims, accountEntity, authority, reqTimestamp) {
|
|
14084
|
+
// Add Native Broker fields to Telemetry
|
|
14085
|
+
const mats = this.addTelemetryFromNativeResponse(response);
|
|
14086
|
+
// If scopes not returned in server response, use request scopes
|
|
14087
|
+
const responseScopes = response.scope
|
|
14088
|
+
? ScopeSet.fromString(response.scope)
|
|
14089
|
+
: ScopeSet.fromString(request.scope);
|
|
14090
|
+
const accountProperties = response.account.properties || {};
|
|
14091
|
+
const uid = accountProperties["UID"] ||
|
|
14092
|
+
idTokenClaims.oid ||
|
|
14093
|
+
idTokenClaims.sub ||
|
|
14094
|
+
Constants.EMPTY_STRING;
|
|
14095
|
+
const tid = accountProperties["TenantId"] ||
|
|
14096
|
+
idTokenClaims.tid ||
|
|
14097
|
+
Constants.EMPTY_STRING;
|
|
14098
|
+
const accountInfo = updateAccountTenantProfileData(accountEntity.getAccountInfo(), undefined, // tenantProfile optional
|
|
14099
|
+
idTokenClaims, response.id_token);
|
|
14100
|
+
/**
|
|
14101
|
+
* In pairwise broker flows, this check prevents the broker's native account id
|
|
14102
|
+
* from being returned over the embedded app's account id.
|
|
14103
|
+
*/
|
|
14104
|
+
if (accountInfo.nativeAccountId !== response.account.id) {
|
|
14105
|
+
accountInfo.nativeAccountId = response.account.id;
|
|
14106
|
+
}
|
|
14107
|
+
// generate PoP token as needed
|
|
14108
|
+
const responseAccessToken = await this.generatePopAccessToken(response, request);
|
|
14109
|
+
const tokenType = request.tokenType === AuthenticationScheme.POP
|
|
14110
|
+
? AuthenticationScheme.POP
|
|
14111
|
+
: AuthenticationScheme.BEARER;
|
|
14112
|
+
const result = {
|
|
14113
|
+
authority: authority,
|
|
14114
|
+
uniqueId: uid,
|
|
14115
|
+
tenantId: tid,
|
|
14116
|
+
scopes: responseScopes.asArray(),
|
|
14117
|
+
account: accountInfo,
|
|
14118
|
+
idToken: response.id_token,
|
|
14119
|
+
idTokenClaims: idTokenClaims,
|
|
14120
|
+
accessToken: responseAccessToken,
|
|
14121
|
+
fromCache: mats ? this.isResponseFromCache(mats) : false,
|
|
14122
|
+
// Request timestamp and NativeResponse expires_in are in seconds, converting to Date for AuthenticationResult
|
|
14123
|
+
expiresOn: toDateFromSeconds(reqTimestamp + response.expires_in),
|
|
14124
|
+
tokenType: tokenType,
|
|
14125
|
+
correlationId: this.correlationId,
|
|
14126
|
+
state: response.state,
|
|
14127
|
+
fromNativeBroker: true,
|
|
14128
|
+
};
|
|
14129
|
+
return result;
|
|
14264
14130
|
}
|
|
14265
14131
|
/**
|
|
14266
|
-
*
|
|
14267
|
-
* @
|
|
14132
|
+
* cache the account entity in browser storage
|
|
14133
|
+
* @param accountEntity
|
|
14268
14134
|
*/
|
|
14269
|
-
|
|
14270
|
-
|
|
14135
|
+
async cacheAccount(accountEntity) {
|
|
14136
|
+
// Store the account info and hence `nativeAccountId` in browser cache
|
|
14137
|
+
await this.browserStorage.setAccount(accountEntity, this.correlationId);
|
|
14138
|
+
// Remove any existing cached tokens for this account in browser storage
|
|
14139
|
+
this.browserStorage.removeAccountContext(accountEntity).catch((e) => {
|
|
14140
|
+
this.logger.error(`Error occurred while removing account context from browser storage. ${e}`);
|
|
14141
|
+
});
|
|
14271
14142
|
}
|
|
14272
14143
|
/**
|
|
14273
|
-
*
|
|
14274
|
-
* @param
|
|
14275
|
-
* @param
|
|
14276
|
-
* @param
|
|
14277
|
-
* @param
|
|
14144
|
+
* Stores the access_token and id_token in inmemory storage
|
|
14145
|
+
* @param response
|
|
14146
|
+
* @param request
|
|
14147
|
+
* @param homeAccountIdentifier
|
|
14148
|
+
* @param idTokenObj
|
|
14149
|
+
* @param responseAccessToken
|
|
14150
|
+
* @param tenantId
|
|
14151
|
+
* @param reqTimestamp
|
|
14278
14152
|
*/
|
|
14279
|
-
|
|
14280
|
-
|
|
14281
|
-
|
|
14282
|
-
|
|
14283
|
-
|
|
14284
|
-
|
|
14153
|
+
cacheNativeTokens(response, request, homeAccountIdentifier, idTokenClaims, responseAccessToken, tenantId, reqTimestamp) {
|
|
14154
|
+
const cachedIdToken = createIdTokenEntity(homeAccountIdentifier, request.authority, response.id_token || "", request.clientId, idTokenClaims.tid || "");
|
|
14155
|
+
// cache accessToken in inmemory storage
|
|
14156
|
+
const expiresIn = request.tokenType === AuthenticationScheme.POP
|
|
14157
|
+
? Constants.SHR_NONCE_VALIDITY
|
|
14158
|
+
: (typeof response.expires_in === "string"
|
|
14159
|
+
? parseInt(response.expires_in, 10)
|
|
14160
|
+
: response.expires_in) || 0;
|
|
14161
|
+
const tokenExpirationSeconds = reqTimestamp + expiresIn;
|
|
14162
|
+
const responseScopes = this.generateScopes(response, request);
|
|
14163
|
+
const cachedAccessToken = createAccessTokenEntity(homeAccountIdentifier, request.authority, responseAccessToken, request.clientId, idTokenClaims.tid || tenantId, responseScopes.printScopes(), tokenExpirationSeconds, 0, base64Decode, undefined, request.tokenType, undefined, request.keyId);
|
|
14164
|
+
const nativeCacheRecord = {
|
|
14165
|
+
idToken: cachedIdToken,
|
|
14166
|
+
accessToken: cachedAccessToken,
|
|
14167
|
+
};
|
|
14168
|
+
return this.nativeStorageManager.saveCacheRecord(nativeCacheRecord, this.correlationId, request.storeInCache);
|
|
14169
|
+
}
|
|
14170
|
+
addTelemetryFromNativeResponse(response) {
|
|
14171
|
+
const mats = this.getMATSFromResponse(response);
|
|
14172
|
+
if (!mats) {
|
|
14173
|
+
return null;
|
|
14285
14174
|
}
|
|
14286
|
-
|
|
14287
|
-
|
|
14288
|
-
|
|
14289
|
-
|
|
14175
|
+
this.performanceClient.addFields({
|
|
14176
|
+
extensionId: this.nativeMessageHandler.getExtensionId(),
|
|
14177
|
+
extensionVersion: this.nativeMessageHandler.getExtensionVersion(),
|
|
14178
|
+
matsBrokerVersion: mats.broker_version,
|
|
14179
|
+
matsAccountJoinOnStart: mats.account_join_on_start,
|
|
14180
|
+
matsAccountJoinOnEnd: mats.account_join_on_end,
|
|
14181
|
+
matsDeviceJoin: mats.device_join,
|
|
14182
|
+
matsPromptBehavior: mats.prompt_behavior,
|
|
14183
|
+
matsApiErrorCode: mats.api_error_code,
|
|
14184
|
+
matsUiVisible: mats.ui_visible,
|
|
14185
|
+
matsSilentCode: mats.silent_code,
|
|
14186
|
+
matsSilentBiSubCode: mats.silent_bi_sub_code,
|
|
14187
|
+
matsSilentMessage: mats.silent_message,
|
|
14188
|
+
matsSilentStatus: mats.silent_status,
|
|
14189
|
+
matsHttpStatus: mats.http_status,
|
|
14190
|
+
matsHttpEventCount: mats.http_event_count,
|
|
14191
|
+
}, this.correlationId);
|
|
14192
|
+
return mats;
|
|
14193
|
+
}
|
|
14194
|
+
/**
|
|
14195
|
+
* Validates native platform response before processing
|
|
14196
|
+
* @param response
|
|
14197
|
+
*/
|
|
14198
|
+
validateNativeResponse(response) {
|
|
14199
|
+
if (response.hasOwnProperty("access_token") &&
|
|
14200
|
+
response.hasOwnProperty("id_token") &&
|
|
14201
|
+
response.hasOwnProperty("client_info") &&
|
|
14202
|
+
response.hasOwnProperty("account") &&
|
|
14203
|
+
response.hasOwnProperty("scope") &&
|
|
14204
|
+
response.hasOwnProperty("expires_in")) {
|
|
14205
|
+
return response;
|
|
14290
14206
|
}
|
|
14291
|
-
|
|
14292
|
-
|
|
14293
|
-
case AuthenticationScheme.BEARER:
|
|
14294
|
-
case AuthenticationScheme.POP:
|
|
14295
|
-
logger.trace("isPlatformBrokerAvailable: authenticationScheme is supported, returning true");
|
|
14296
|
-
return true;
|
|
14297
|
-
default:
|
|
14298
|
-
logger.trace("isPlatformBrokerAvailable: authenticationScheme is not supported, returning false");
|
|
14299
|
-
return false;
|
|
14300
|
-
}
|
|
14207
|
+
else {
|
|
14208
|
+
throw createAuthError(unexpectedError, "Response missing expected properties.");
|
|
14301
14209
|
}
|
|
14302
|
-
return true;
|
|
14303
|
-
}
|
|
14304
|
-
}
|
|
14305
|
-
|
|
14306
|
-
/*
|
|
14307
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
14308
|
-
* Licensed under the MIT License.
|
|
14309
|
-
*/
|
|
14310
|
-
/**
|
|
14311
|
-
* Abstract class which defines operations for a browser interaction handling class.
|
|
14312
|
-
*/
|
|
14313
|
-
class InteractionHandler {
|
|
14314
|
-
constructor(authCodeModule, storageImpl, authCodeRequest, logger, performanceClient) {
|
|
14315
|
-
this.authModule = authCodeModule;
|
|
14316
|
-
this.browserStorage = storageImpl;
|
|
14317
|
-
this.authCodeRequest = authCodeRequest;
|
|
14318
|
-
this.logger = logger;
|
|
14319
|
-
this.performanceClient = performanceClient;
|
|
14320
14210
|
}
|
|
14321
14211
|
/**
|
|
14322
|
-
*
|
|
14323
|
-
* @param
|
|
14212
|
+
* Gets MATS telemetry from native response
|
|
14213
|
+
* @param response
|
|
14214
|
+
* @returns
|
|
14324
14215
|
*/
|
|
14325
|
-
|
|
14326
|
-
|
|
14327
|
-
|
|
14328
|
-
|
|
14329
|
-
authCodeResponse = getAuthorizationCodePayload(response, request.state);
|
|
14330
|
-
}
|
|
14331
|
-
catch (e) {
|
|
14332
|
-
if (e instanceof ServerError &&
|
|
14333
|
-
e.subError === userCancelled) {
|
|
14334
|
-
// Translate server error caused by user closing native prompt to corresponding first class MSAL error
|
|
14335
|
-
throw createBrowserAuthError(userCancelled);
|
|
14216
|
+
getMATSFromResponse(response) {
|
|
14217
|
+
if (response.properties.MATS) {
|
|
14218
|
+
try {
|
|
14219
|
+
return JSON.parse(response.properties.MATS);
|
|
14336
14220
|
}
|
|
14337
|
-
|
|
14338
|
-
|
|
14221
|
+
catch (e) {
|
|
14222
|
+
this.logger.error("NativeInteractionClient - Error parsing MATS telemetry, returning null instead");
|
|
14339
14223
|
}
|
|
14340
14224
|
}
|
|
14341
|
-
return
|
|
14225
|
+
return null;
|
|
14342
14226
|
}
|
|
14343
14227
|
/**
|
|
14344
|
-
*
|
|
14345
|
-
* @param
|
|
14346
|
-
* @param state
|
|
14347
|
-
* @param authority
|
|
14348
|
-
* @param networkModule
|
|
14228
|
+
* Returns whether or not response came from native cache
|
|
14229
|
+
* @param response
|
|
14349
14230
|
* @returns
|
|
14350
14231
|
*/
|
|
14351
|
-
|
|
14352
|
-
|
|
14353
|
-
|
|
14354
|
-
|
|
14355
|
-
this.authCodeRequest.code = authCodeResponse.code;
|
|
14356
|
-
// Check for new cloud instance
|
|
14357
|
-
if (authCodeResponse.cloud_instance_host_name) {
|
|
14358
|
-
await invokeAsync(this.authModule.updateAuthority.bind(this.authModule), PerformanceEvents.UpdateTokenEndpointAuthority, this.logger, this.performanceClient, request.correlationId)(authCodeResponse.cloud_instance_host_name, request.correlationId);
|
|
14359
|
-
}
|
|
14360
|
-
// Nonce validation not needed when redirect not involved (e.g. hybrid spa, renewing token via rt)
|
|
14361
|
-
if (validateNonce) {
|
|
14362
|
-
// TODO: Assigning "response nonce" to "request nonce" is confusing. Refactor the function doing validation to accept request nonce directly
|
|
14363
|
-
authCodeResponse.nonce = request.nonce || undefined;
|
|
14364
|
-
}
|
|
14365
|
-
authCodeResponse.state = request.state;
|
|
14366
|
-
// Add CCS parameters if available
|
|
14367
|
-
if (authCodeResponse.client_info) {
|
|
14368
|
-
this.authCodeRequest.clientInfo = authCodeResponse.client_info;
|
|
14369
|
-
}
|
|
14370
|
-
else {
|
|
14371
|
-
const ccsCred = this.createCcsCredentials(request);
|
|
14372
|
-
if (ccsCred) {
|
|
14373
|
-
this.authCodeRequest.ccsCredential = ccsCred;
|
|
14374
|
-
}
|
|
14232
|
+
isResponseFromCache(mats) {
|
|
14233
|
+
if (typeof mats.is_cached === "undefined") {
|
|
14234
|
+
this.logger.verbose("NativeInteractionClient - MATS telemetry does not contain field indicating if response was served from cache. Returning false.");
|
|
14235
|
+
return false;
|
|
14375
14236
|
}
|
|
14376
|
-
|
|
14377
|
-
const tokenResponse = (await invokeAsync(this.authModule.acquireToken.bind(this.authModule), PerformanceEvents.AuthClientAcquireToken, this.logger, this.performanceClient, request.correlationId)(this.authCodeRequest, authCodeResponse));
|
|
14378
|
-
return tokenResponse;
|
|
14237
|
+
return !!mats.is_cached;
|
|
14379
14238
|
}
|
|
14380
14239
|
/**
|
|
14381
|
-
*
|
|
14240
|
+
* Translates developer provided request object into NativeRequest object
|
|
14241
|
+
* @param request
|
|
14382
14242
|
*/
|
|
14383
|
-
|
|
14243
|
+
async initializeNativeRequest(request) {
|
|
14244
|
+
this.logger.trace("NativeInteractionClient - initializeNativeRequest called");
|
|
14245
|
+
const requestAuthority = request.authority || this.config.auth.authority;
|
|
14384
14246
|
if (request.account) {
|
|
14385
|
-
|
|
14386
|
-
|
|
14387
|
-
|
|
14388
|
-
|
|
14247
|
+
// validate authority
|
|
14248
|
+
await this.getDiscoveredAuthority({
|
|
14249
|
+
requestAuthority,
|
|
14250
|
+
requestAzureCloudOptions: request.azureCloudOptions,
|
|
14251
|
+
account: request.account,
|
|
14252
|
+
});
|
|
14389
14253
|
}
|
|
14390
|
-
|
|
14391
|
-
|
|
14392
|
-
|
|
14393
|
-
|
|
14254
|
+
const canonicalAuthority = new UrlString(requestAuthority);
|
|
14255
|
+
canonicalAuthority.validateAsUri();
|
|
14256
|
+
// scopes are expected to be received by the native broker as "scope" and will be added to the request below. Other properties that should be dropped from the request to the native broker can be included in the object destructuring here.
|
|
14257
|
+
const { scopes, ...remainingProperties } = request;
|
|
14258
|
+
const scopeSet = new ScopeSet(scopes || []);
|
|
14259
|
+
scopeSet.appendScopes(OIDC_DEFAULT_SCOPES);
|
|
14260
|
+
const getPrompt = () => {
|
|
14261
|
+
// If request is silent, prompt is always none
|
|
14262
|
+
switch (this.apiId) {
|
|
14263
|
+
case ApiId.ssoSilent:
|
|
14264
|
+
case ApiId.acquireTokenSilent_silentFlow:
|
|
14265
|
+
this.logger.trace("initializeNativeRequest: silent request sets prompt to none");
|
|
14266
|
+
return PromptValue.NONE;
|
|
14267
|
+
}
|
|
14268
|
+
// Prompt not provided, request may proceed and native broker decides if it needs to prompt
|
|
14269
|
+
if (!request.prompt) {
|
|
14270
|
+
this.logger.trace("initializeNativeRequest: prompt was not provided");
|
|
14271
|
+
return undefined;
|
|
14272
|
+
}
|
|
14273
|
+
// If request is interactive, check if prompt provided is allowed to go directly to native broker
|
|
14274
|
+
switch (request.prompt) {
|
|
14275
|
+
case PromptValue.NONE:
|
|
14276
|
+
case PromptValue.CONSENT:
|
|
14277
|
+
case PromptValue.LOGIN:
|
|
14278
|
+
this.logger.trace("initializeNativeRequest: prompt is compatible with native flow");
|
|
14279
|
+
return request.prompt;
|
|
14280
|
+
default:
|
|
14281
|
+
this.logger.trace(`initializeNativeRequest: prompt = ${request.prompt} is not compatible with native flow`);
|
|
14282
|
+
throw createBrowserAuthError(nativePromptNotSupported);
|
|
14283
|
+
}
|
|
14284
|
+
};
|
|
14285
|
+
const validatedRequest = {
|
|
14286
|
+
...remainingProperties,
|
|
14287
|
+
accountId: this.accountId,
|
|
14288
|
+
clientId: this.config.auth.clientId,
|
|
14289
|
+
authority: canonicalAuthority.urlString,
|
|
14290
|
+
scope: scopeSet.printScopes(),
|
|
14291
|
+
redirectUri: this.getRedirectUri(request.redirectUri),
|
|
14292
|
+
prompt: getPrompt(),
|
|
14293
|
+
correlationId: this.correlationId,
|
|
14294
|
+
tokenType: request.authenticationScheme,
|
|
14295
|
+
windowTitleSubstring: document.title,
|
|
14296
|
+
extraParameters: {
|
|
14297
|
+
...request.extraQueryParameters,
|
|
14298
|
+
...request.tokenQueryParameters,
|
|
14299
|
+
},
|
|
14300
|
+
extendedExpiryToken: false,
|
|
14301
|
+
keyId: request.popKid,
|
|
14302
|
+
};
|
|
14303
|
+
// Check for PoP token requests: signPopToken should only be set to true if popKid is not set
|
|
14304
|
+
if (validatedRequest.signPopToken && !!request.popKid) {
|
|
14305
|
+
throw createBrowserAuthError(invalidPopTokenRequest);
|
|
14306
|
+
}
|
|
14307
|
+
this.handleExtraBrokerParams(validatedRequest);
|
|
14308
|
+
validatedRequest.extraParameters =
|
|
14309
|
+
validatedRequest.extraParameters || {};
|
|
14310
|
+
validatedRequest.extraParameters.telemetry =
|
|
14311
|
+
NativeConstants.MATS_TELEMETRY;
|
|
14312
|
+
if (request.authenticationScheme === AuthenticationScheme.POP) {
|
|
14313
|
+
// add POP request type
|
|
14314
|
+
const shrParameters = {
|
|
14315
|
+
resourceRequestUri: request.resourceRequestUri,
|
|
14316
|
+
resourceRequestMethod: request.resourceRequestMethod,
|
|
14317
|
+
shrClaims: request.shrClaims,
|
|
14318
|
+
shrNonce: request.shrNonce,
|
|
14394
14319
|
};
|
|
14320
|
+
const popTokenGenerator = new PopTokenGenerator(this.browserCrypto);
|
|
14321
|
+
// generate reqCnf if not provided in the request
|
|
14322
|
+
let reqCnfData;
|
|
14323
|
+
if (!validatedRequest.keyId) {
|
|
14324
|
+
const generatedReqCnfData = await invokeAsync(popTokenGenerator.generateCnf.bind(popTokenGenerator), PerformanceEvents.PopTokenGenerateCnf, this.logger, this.performanceClient, request.correlationId)(shrParameters, this.logger);
|
|
14325
|
+
reqCnfData = generatedReqCnfData.reqCnfString;
|
|
14326
|
+
validatedRequest.keyId = generatedReqCnfData.kid;
|
|
14327
|
+
validatedRequest.signPopToken = true;
|
|
14328
|
+
}
|
|
14329
|
+
else {
|
|
14330
|
+
reqCnfData = this.browserCrypto.base64UrlEncode(JSON.stringify({ kid: validatedRequest.keyId }));
|
|
14331
|
+
validatedRequest.signPopToken = false;
|
|
14332
|
+
}
|
|
14333
|
+
// SPAs require whole string to be passed to broker
|
|
14334
|
+
validatedRequest.reqCnf = reqCnfData;
|
|
14395
14335
|
}
|
|
14396
|
-
|
|
14336
|
+
this.addRequestSKUs(validatedRequest);
|
|
14337
|
+
return validatedRequest;
|
|
14397
14338
|
}
|
|
14398
|
-
|
|
14399
|
-
|
|
14400
|
-
|
|
14401
|
-
|
|
14402
|
-
|
|
14403
|
-
|
|
14404
|
-
|
|
14405
|
-
|
|
14406
|
-
|
|
14407
|
-
|
|
14408
|
-
if (!
|
|
14409
|
-
|
|
14410
|
-
logger.error(`The request has returned to the redirectUri but a ${responseLocation} is not present. It's likely that the ${responseLocation} has been removed or the page has been redirected by code running on the redirectUri page.`);
|
|
14411
|
-
throw createBrowserAuthError(hashEmptyError);
|
|
14339
|
+
/**
|
|
14340
|
+
* Handles extra broker request parameters
|
|
14341
|
+
* @param request {NativeTokenRequest}
|
|
14342
|
+
* @private
|
|
14343
|
+
*/
|
|
14344
|
+
handleExtraBrokerParams(request) {
|
|
14345
|
+
const hasExtraBrokerParams = request.extraParameters &&
|
|
14346
|
+
request.extraParameters.hasOwnProperty(BROKER_CLIENT_ID) &&
|
|
14347
|
+
request.extraParameters.hasOwnProperty(BROKER_REDIRECT_URI) &&
|
|
14348
|
+
request.extraParameters.hasOwnProperty(CLIENT_ID);
|
|
14349
|
+
if (!request.embeddedClientId && !hasExtraBrokerParams) {
|
|
14350
|
+
return;
|
|
14412
14351
|
}
|
|
14413
|
-
|
|
14414
|
-
|
|
14415
|
-
|
|
14416
|
-
|
|
14352
|
+
let child_client_id = "";
|
|
14353
|
+
const child_redirect_uri = request.redirectUri;
|
|
14354
|
+
if (request.embeddedClientId) {
|
|
14355
|
+
request.redirectUri = this.config.auth.redirectUri;
|
|
14356
|
+
child_client_id = request.embeddedClientId;
|
|
14417
14357
|
}
|
|
14418
|
-
|
|
14419
|
-
|
|
14420
|
-
|
|
14421
|
-
|
|
14422
|
-
|
|
14423
|
-
|
|
14424
|
-
|
|
14425
|
-
|
|
14426
|
-
|
|
14427
|
-
|
|
14428
|
-
|
|
14429
|
-
|
|
14430
|
-
|
|
14431
|
-
|
|
14432
|
-
if (platformStateObj.interactionType !== interactionType) {
|
|
14433
|
-
throw createBrowserAuthError(stateInteractionTypeMismatch);
|
|
14358
|
+
else if (request.extraParameters) {
|
|
14359
|
+
request.redirectUri =
|
|
14360
|
+
request.extraParameters[BROKER_REDIRECT_URI];
|
|
14361
|
+
child_client_id =
|
|
14362
|
+
request.extraParameters[CLIENT_ID];
|
|
14363
|
+
}
|
|
14364
|
+
request.extraParameters = {
|
|
14365
|
+
child_client_id,
|
|
14366
|
+
child_redirect_uri,
|
|
14367
|
+
};
|
|
14368
|
+
this.performanceClient?.addFields({
|
|
14369
|
+
embeddedClientId: child_client_id,
|
|
14370
|
+
embeddedRedirectUri: child_redirect_uri,
|
|
14371
|
+
}, request.correlationId);
|
|
14434
14372
|
}
|
|
14435
14373
|
}
|
|
14436
14374
|
|
|
@@ -14494,9 +14432,147 @@
|
|
|
14494
14432
|
throw createClientConfigurationError(pkceParamsMissing);
|
|
14495
14433
|
}
|
|
14496
14434
|
const parameters = await invokeAsync(getStandardParameters, PerformanceEvents.GetStandardParams, logger, performanceClient, request.correlationId)(config, authority, request, logger, performanceClient);
|
|
14497
|
-
|
|
14435
|
+
addResponseType(parameters, OAuthResponseType.CODE);
|
|
14498
14436
|
addCodeChallengeParams(parameters, request.codeChallenge, Constants.S256_CODE_CHALLENGE_METHOD);
|
|
14437
|
+
addExtraQueryParameters(parameters, request.extraQueryParameters || {});
|
|
14499
14438
|
return getAuthorizeUrl(authority, parameters);
|
|
14439
|
+
}
|
|
14440
|
+
/**
|
|
14441
|
+
* Gets the form that will be posted to /authorize with request parameters when using EAR
|
|
14442
|
+
*/
|
|
14443
|
+
async function getEARForm(frame, config, authority, request, logger, performanceClient) {
|
|
14444
|
+
if (!request.earJwk) {
|
|
14445
|
+
throw createBrowserAuthError(earJwkEmpty);
|
|
14446
|
+
}
|
|
14447
|
+
const parameters = await getStandardParameters(config, authority, request, logger, performanceClient);
|
|
14448
|
+
addResponseType(parameters, OAuthResponseType.IDTOKEN_TOKEN_REFRESHTOKEN);
|
|
14449
|
+
addEARParameters(parameters, request.earJwk);
|
|
14450
|
+
const queryParams = new Map();
|
|
14451
|
+
addExtraQueryParameters(queryParams, request.extraQueryParameters || {});
|
|
14452
|
+
const url = getAuthorizeUrl(authority, queryParams);
|
|
14453
|
+
return createForm(frame, url, parameters);
|
|
14454
|
+
}
|
|
14455
|
+
/**
|
|
14456
|
+
* Creates form element in the provided document with auth parameters in the post body
|
|
14457
|
+
* @param frame
|
|
14458
|
+
* @param authorizeUrl
|
|
14459
|
+
* @param parameters
|
|
14460
|
+
* @returns
|
|
14461
|
+
*/
|
|
14462
|
+
function createForm(frame, authorizeUrl, parameters) {
|
|
14463
|
+
const form = frame.createElement("form");
|
|
14464
|
+
form.method = "post";
|
|
14465
|
+
form.action = authorizeUrl;
|
|
14466
|
+
parameters.forEach((value, key) => {
|
|
14467
|
+
const param = frame.createElement("input");
|
|
14468
|
+
param.hidden = true;
|
|
14469
|
+
param.name = key;
|
|
14470
|
+
param.value = value;
|
|
14471
|
+
form.appendChild(param);
|
|
14472
|
+
});
|
|
14473
|
+
frame.body.appendChild(form);
|
|
14474
|
+
return form;
|
|
14475
|
+
}
|
|
14476
|
+
/**
|
|
14477
|
+
* Response handler when server returns accountId on the /authorize request
|
|
14478
|
+
* @param request
|
|
14479
|
+
* @param accountId
|
|
14480
|
+
* @param apiId
|
|
14481
|
+
* @param config
|
|
14482
|
+
* @param browserStorage
|
|
14483
|
+
* @param nativeStorage
|
|
14484
|
+
* @param eventHandler
|
|
14485
|
+
* @param logger
|
|
14486
|
+
* @param performanceClient
|
|
14487
|
+
* @param nativeMessageHandler
|
|
14488
|
+
* @returns
|
|
14489
|
+
*/
|
|
14490
|
+
async function handleResponsePlatformBroker(request, accountId, apiId, config, browserStorage, nativeStorage, eventHandler, logger, performanceClient, nativeMessageHandler) {
|
|
14491
|
+
if (!nativeMessageHandler) {
|
|
14492
|
+
throw createBrowserAuthError(nativeConnectionNotEstablished);
|
|
14493
|
+
}
|
|
14494
|
+
const browserCrypto = new CryptoOps(logger, performanceClient);
|
|
14495
|
+
const nativeInteractionClient = new NativeInteractionClient(config, browserStorage, browserCrypto, logger, eventHandler, config.system.navigationClient, apiId, performanceClient, nativeMessageHandler, accountId, nativeStorage, request.correlationId);
|
|
14496
|
+
const { userRequestState } = ProtocolUtils.parseRequestState(browserCrypto, request.state);
|
|
14497
|
+
return invokeAsync(nativeInteractionClient.acquireToken.bind(nativeInteractionClient), PerformanceEvents.NativeInteractionClientAcquireToken, logger, performanceClient, request.correlationId)({
|
|
14498
|
+
...request,
|
|
14499
|
+
state: userRequestState,
|
|
14500
|
+
prompt: undefined, // Server should handle the prompt, ideally native broker can do this part silently
|
|
14501
|
+
});
|
|
14502
|
+
}
|
|
14503
|
+
/**
|
|
14504
|
+
* Response handler when server returns code on the /authorize request
|
|
14505
|
+
* @param request
|
|
14506
|
+
* @param response
|
|
14507
|
+
* @param codeVerifier
|
|
14508
|
+
* @param authClient
|
|
14509
|
+
* @param browserStorage
|
|
14510
|
+
* @param logger
|
|
14511
|
+
* @param performanceClient
|
|
14512
|
+
* @returns
|
|
14513
|
+
*/
|
|
14514
|
+
async function handleResponseCode(request, response, codeVerifier, apiId, config, authClient, browserStorage, nativeStorage, eventHandler, logger, performanceClient, nativeMessageHandler) {
|
|
14515
|
+
// Remove throttle if it exists
|
|
14516
|
+
ThrottlingUtils.removeThrottle(browserStorage, config.auth.clientId, request);
|
|
14517
|
+
if (response.accountId) {
|
|
14518
|
+
return invokeAsync(handleResponsePlatformBroker, PerformanceEvents.HandleResponsePlatformBroker, logger, performanceClient, request.correlationId)(request, response.accountId, apiId, config, browserStorage, nativeStorage, eventHandler, logger, performanceClient, nativeMessageHandler);
|
|
14519
|
+
}
|
|
14520
|
+
const authCodeRequest = {
|
|
14521
|
+
...request,
|
|
14522
|
+
code: response.code || "",
|
|
14523
|
+
codeVerifier: codeVerifier,
|
|
14524
|
+
};
|
|
14525
|
+
// Create popup interaction handler.
|
|
14526
|
+
const interactionHandler = new InteractionHandler(authClient, browserStorage, authCodeRequest, logger, performanceClient);
|
|
14527
|
+
// Handle response from hash string.
|
|
14528
|
+
const result = await invokeAsync(interactionHandler.handleCodeResponse.bind(interactionHandler), PerformanceEvents.HandleCodeResponse, logger, performanceClient, request.correlationId)(response, request);
|
|
14529
|
+
return result;
|
|
14530
|
+
}
|
|
14531
|
+
/**
|
|
14532
|
+
* Response handler when server returns ear_jwe on the /authorize request
|
|
14533
|
+
* @param request
|
|
14534
|
+
* @param response
|
|
14535
|
+
* @param apiId
|
|
14536
|
+
* @param config
|
|
14537
|
+
* @param authority
|
|
14538
|
+
* @param browserStorage
|
|
14539
|
+
* @param nativeStorage
|
|
14540
|
+
* @param eventHandler
|
|
14541
|
+
* @param logger
|
|
14542
|
+
* @param performanceClient
|
|
14543
|
+
* @param nativeMessageHandler
|
|
14544
|
+
* @returns
|
|
14545
|
+
*/
|
|
14546
|
+
async function handleResponseEAR(request, response, apiId, config, authority, browserStorage, nativeStorage, eventHandler, logger, performanceClient, nativeMessageHandler) {
|
|
14547
|
+
// Remove throttle if it exists
|
|
14548
|
+
ThrottlingUtils.removeThrottle(browserStorage, config.auth.clientId, request);
|
|
14549
|
+
// Validate state & check response for errors
|
|
14550
|
+
validateAuthorizationResponse(response, request.state);
|
|
14551
|
+
if (!response.ear_jwe) {
|
|
14552
|
+
throw createBrowserAuthError(earJweEmpty);
|
|
14553
|
+
}
|
|
14554
|
+
if (!request.earJwk) {
|
|
14555
|
+
throw createBrowserAuthError(earJwkEmpty);
|
|
14556
|
+
}
|
|
14557
|
+
const decryptedData = JSON.parse(await invokeAsync(decryptEarResponse, PerformanceEvents.DecryptEarResponse, logger, performanceClient, request.correlationId)(request.earJwk, response.ear_jwe));
|
|
14558
|
+
if (decryptedData.accountId) {
|
|
14559
|
+
return invokeAsync(handleResponsePlatformBroker, PerformanceEvents.HandleResponsePlatformBroker, logger, performanceClient, request.correlationId)(request, decryptedData.accountId, apiId, config, browserStorage, nativeStorage, eventHandler, logger, performanceClient, nativeMessageHandler);
|
|
14560
|
+
}
|
|
14561
|
+
const responseHandler = new ResponseHandler(config.auth.clientId, browserStorage, new CryptoOps(logger, performanceClient), logger, null, null, performanceClient);
|
|
14562
|
+
// Validate response. This function throws a server error if an error is returned by the server.
|
|
14563
|
+
responseHandler.validateTokenResponse(decryptedData);
|
|
14564
|
+
// Temporary until response handler is refactored to be more flow agnostic.
|
|
14565
|
+
const additionalData = {
|
|
14566
|
+
code: "",
|
|
14567
|
+
state: request.state,
|
|
14568
|
+
nonce: request.nonce,
|
|
14569
|
+
client_info: decryptedData.client_info,
|
|
14570
|
+
cloud_graph_host_name: decryptedData.cloud_graph_host_name,
|
|
14571
|
+
cloud_instance_host_name: decryptedData.cloud_instance_host_name,
|
|
14572
|
+
cloud_instance_name: decryptedData.cloud_instance_name,
|
|
14573
|
+
msgraph_host: decryptedData.msgraph_host,
|
|
14574
|
+
};
|
|
14575
|
+
return (await invokeAsync(responseHandler.handleServerTokenResponse.bind(responseHandler), PerformanceEvents.HandleServerTokenResponse, logger, performanceClient, request.correlationId)(decryptedData, authority, nowSeconds(), request, additionalData, undefined, undefined, undefined, undefined));
|
|
14500
14576
|
}
|
|
14501
14577
|
|
|
14502
14578
|
/*
|
|
@@ -14564,6 +14640,7 @@
|
|
|
14564
14640
|
// Properly sets this reference for the unload event.
|
|
14565
14641
|
this.unloadWindow = this.unloadWindow.bind(this);
|
|
14566
14642
|
this.nativeStorage = nativeStorageImpl;
|
|
14643
|
+
this.eventHandler = eventHandler;
|
|
14567
14644
|
}
|
|
14568
14645
|
/**
|
|
14569
14646
|
* Acquires tokens by opening a popup window to the /authorize endpoint of the authority
|
|
@@ -14639,11 +14716,7 @@
|
|
|
14639
14716
|
*/
|
|
14640
14717
|
async acquireTokenPopupAsync(request, popupParams, pkceCodes) {
|
|
14641
14718
|
this.logger.verbose("acquireTokenPopupAsync called");
|
|
14642
|
-
const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenPopup);
|
|
14643
14719
|
const validRequest = await invokeAsync(this.initializeAuthorizationRequest.bind(this), PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest, this.logger, this.performanceClient, this.correlationId)(request, exports.InteractionType.Popup);
|
|
14644
|
-
const pkce = pkceCodes ||
|
|
14645
|
-
(await invokeAsync(generatePkceCodes, PerformanceEvents.GeneratePkceCodes, this.logger, this.performanceClient, this.correlationId)(this.performanceClient, this.logger, this.correlationId));
|
|
14646
|
-
validRequest.codeChallenge = pkce.challenge;
|
|
14647
14720
|
/*
|
|
14648
14721
|
* Skip pre-connect for async popups to reduce time between user interaction and popup window creation to avoid
|
|
14649
14722
|
* popup from being blocked by browsers with shorter popup timers
|
|
@@ -14651,65 +14724,49 @@
|
|
|
14651
14724
|
if (popupParams.popup) {
|
|
14652
14725
|
preconnect(validRequest.authority);
|
|
14653
14726
|
}
|
|
14727
|
+
const isPlatformBroker = NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeMessageHandler, request.authenticationScheme);
|
|
14728
|
+
validRequest.platformBroker = isPlatformBroker;
|
|
14729
|
+
if (this.config.auth.protocolMode === ProtocolMode.EAR) {
|
|
14730
|
+
return this.executeEarFlow(validRequest, popupParams);
|
|
14731
|
+
}
|
|
14732
|
+
else {
|
|
14733
|
+
return this.executeCodeFlow(validRequest, popupParams, pkceCodes);
|
|
14734
|
+
}
|
|
14735
|
+
}
|
|
14736
|
+
/**
|
|
14737
|
+
* Executes auth code + PKCE flow
|
|
14738
|
+
* @param request
|
|
14739
|
+
* @param popupParams
|
|
14740
|
+
* @param pkceCodes
|
|
14741
|
+
* @returns
|
|
14742
|
+
*/
|
|
14743
|
+
async executeCodeFlow(request, popupParams, pkceCodes) {
|
|
14744
|
+
const correlationId = request.correlationId;
|
|
14745
|
+
const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenPopup);
|
|
14746
|
+
const pkce = pkceCodes ||
|
|
14747
|
+
(await invokeAsync(generatePkceCodes, PerformanceEvents.GeneratePkceCodes, this.logger, this.performanceClient, correlationId)(this.performanceClient, this.logger, correlationId));
|
|
14748
|
+
const popupRequest = {
|
|
14749
|
+
...request,
|
|
14750
|
+
codeChallenge: pkce.challenge,
|
|
14751
|
+
};
|
|
14654
14752
|
try {
|
|
14655
14753
|
// Initialize the client
|
|
14656
|
-
const authClient = await invokeAsync(this.createAuthCodeClient.bind(this), PerformanceEvents.StandardInteractionClientCreateAuthCodeClient, this.logger, this.performanceClient,
|
|
14754
|
+
const authClient = await invokeAsync(this.createAuthCodeClient.bind(this), PerformanceEvents.StandardInteractionClientCreateAuthCodeClient, this.logger, this.performanceClient, correlationId)({
|
|
14657
14755
|
serverTelemetryManager,
|
|
14658
|
-
requestAuthority:
|
|
14659
|
-
requestAzureCloudOptions:
|
|
14660
|
-
requestExtraQueryParameters:
|
|
14661
|
-
account:
|
|
14756
|
+
requestAuthority: popupRequest.authority,
|
|
14757
|
+
requestAzureCloudOptions: popupRequest.azureCloudOptions,
|
|
14758
|
+
requestExtraQueryParameters: popupRequest.extraQueryParameters,
|
|
14759
|
+
account: popupRequest.account,
|
|
14662
14760
|
});
|
|
14663
|
-
const isPlatformBroker = NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeMessageHandler, request.authenticationScheme);
|
|
14664
|
-
// Start measurement for server calls with native brokering enabled
|
|
14665
|
-
let fetchNativeAccountIdMeasurement;
|
|
14666
|
-
if (isPlatformBroker) {
|
|
14667
|
-
fetchNativeAccountIdMeasurement =
|
|
14668
|
-
this.performanceClient.startMeasurement(PerformanceEvents.FetchAccountIdWithNativeBroker, request.correlationId);
|
|
14669
|
-
}
|
|
14670
14761
|
// Create acquire token url.
|
|
14671
|
-
const navigateUrl = await invokeAsync(getAuthCodeRequestUrl, PerformanceEvents.GetAuthCodeUrl, this.logger, this.performanceClient,
|
|
14672
|
-
...validRequest,
|
|
14673
|
-
platformBroker: isPlatformBroker,
|
|
14674
|
-
}, this.logger, this.performanceClient);
|
|
14762
|
+
const navigateUrl = await invokeAsync(getAuthCodeRequestUrl, PerformanceEvents.GetAuthCodeUrl, this.logger, this.performanceClient, correlationId)(this.config, authClient.authority, popupRequest, this.logger, this.performanceClient);
|
|
14675
14763
|
// Show the UI once the url has been created. Get the window handle for the popup.
|
|
14676
14764
|
const popupWindow = this.initiateAuthRequest(navigateUrl, popupParams);
|
|
14677
14765
|
this.eventHandler.emitEvent(EventType.POPUP_OPENED, exports.InteractionType.Popup, { popupWindow }, null);
|
|
14678
14766
|
// Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
|
|
14679
14767
|
const responseString = await this.monitorPopupForHash(popupWindow, popupParams.popupWindowParent);
|
|
14680
14768
|
const serverParams = invoke(deserializeResponse, PerformanceEvents.DeserializeResponse, this.logger, this.performanceClient, this.correlationId)(responseString, this.config.auth.OIDCOptions.serverResponseType, this.logger);
|
|
14681
|
-
|
|
14682
|
-
ThrottlingUtils.removeThrottle(this.browserStorage, this.config.auth.clientId, validRequest);
|
|
14683
|
-
if (serverParams.accountId) {
|
|
14684
|
-
this.logger.verbose("Account id found in hash, calling WAM for token");
|
|
14685
|
-
// end measurement for server call with native brokering enabled
|
|
14686
|
-
if (fetchNativeAccountIdMeasurement) {
|
|
14687
|
-
fetchNativeAccountIdMeasurement.end({
|
|
14688
|
-
success: true,
|
|
14689
|
-
isNativeBroker: true,
|
|
14690
|
-
});
|
|
14691
|
-
}
|
|
14692
|
-
if (!this.nativeMessageHandler) {
|
|
14693
|
-
throw createBrowserAuthError(nativeConnectionNotEstablished);
|
|
14694
|
-
}
|
|
14695
|
-
const nativeInteractionClient = new NativeInteractionClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, ApiId.acquireTokenPopup, this.performanceClient, this.nativeMessageHandler, serverParams.accountId, this.nativeStorage, validRequest.correlationId);
|
|
14696
|
-
const { userRequestState } = ProtocolUtils.parseRequestState(this.browserCrypto, validRequest.state);
|
|
14697
|
-
return await nativeInteractionClient.acquireToken({
|
|
14698
|
-
...validRequest,
|
|
14699
|
-
state: userRequestState,
|
|
14700
|
-
prompt: undefined, // Server should handle the prompt, ideally native broker can do this part silently
|
|
14701
|
-
});
|
|
14702
|
-
}
|
|
14703
|
-
const authCodeRequest = {
|
|
14704
|
-
...validRequest,
|
|
14705
|
-
code: serverParams.code || "",
|
|
14706
|
-
codeVerifier: pkce.verifier,
|
|
14707
|
-
};
|
|
14708
|
-
// Create popup interaction handler.
|
|
14709
|
-
const interactionHandler = new InteractionHandler(authClient, this.browserStorage, authCodeRequest, this.logger, this.performanceClient);
|
|
14710
|
-
// Handle response from hash string.
|
|
14711
|
-
const result = await interactionHandler.handleCodeResponse(serverParams, validRequest);
|
|
14712
|
-
return result;
|
|
14769
|
+
return await invokeAsync(handleResponseCode, PerformanceEvents.HandleResponseCode, this.logger, this.performanceClient, correlationId)(request, serverParams, pkce.verifier, ApiId.acquireTokenPopup, this.config, authClient, this.browserStorage, this.nativeStorage, this.eventHandler, this.logger, this.performanceClient, this.nativeMessageHandler);
|
|
14713
14770
|
}
|
|
14714
14771
|
catch (e) {
|
|
14715
14772
|
// Close the synchronous popup if an error is thrown before the window unload event is registered
|
|
@@ -14721,6 +14778,32 @@
|
|
|
14721
14778
|
throw e;
|
|
14722
14779
|
}
|
|
14723
14780
|
}
|
|
14781
|
+
/**
|
|
14782
|
+
* Executes EAR flow
|
|
14783
|
+
* @param request
|
|
14784
|
+
*/
|
|
14785
|
+
async executeEarFlow(request, popupParams) {
|
|
14786
|
+
const correlationId = request.correlationId;
|
|
14787
|
+
// Get the frame handle for the silent request
|
|
14788
|
+
const discoveredAuthority = await invokeAsync(this.getDiscoveredAuthority.bind(this), PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority, this.logger, this.performanceClient, correlationId)({
|
|
14789
|
+
requestAuthority: request.authority,
|
|
14790
|
+
requestAzureCloudOptions: request.azureCloudOptions,
|
|
14791
|
+
requestExtraQueryParameters: request.extraQueryParameters,
|
|
14792
|
+
account: request.account,
|
|
14793
|
+
});
|
|
14794
|
+
const earJwk = await invokeAsync(generateEarKey, PerformanceEvents.GenerateEarKey, this.logger, this.performanceClient, correlationId)();
|
|
14795
|
+
const popupRequest = {
|
|
14796
|
+
...request,
|
|
14797
|
+
earJwk: earJwk,
|
|
14798
|
+
};
|
|
14799
|
+
const popupWindow = popupParams.popup || this.openPopup("about:blank", popupParams);
|
|
14800
|
+
const form = await getEARForm(popupWindow.document, this.config, discoveredAuthority, popupRequest, this.logger, this.performanceClient);
|
|
14801
|
+
form.submit();
|
|
14802
|
+
// Monitor the popup for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
|
|
14803
|
+
const responseString = await invokeAsync(this.monitorPopupForHash.bind(this), PerformanceEvents.SilentHandlerMonitorIframeForHash, this.logger, this.performanceClient, correlationId)(popupWindow, popupParams.popupWindowParent);
|
|
14804
|
+
const serverParams = invoke(deserializeResponse, PerformanceEvents.DeserializeResponse, this.logger, this.performanceClient, this.correlationId)(responseString, this.config.auth.OIDCOptions.serverResponseType, this.logger);
|
|
14805
|
+
return invokeAsync(handleResponseEAR, PerformanceEvents.HandleResponseEar, this.logger, this.performanceClient, correlationId)(popupRequest, serverParams, ApiId.acquireTokenPopup, this.config, discoveredAuthority, this.browserStorage, this.nativeStorage, this.eventHandler, this.logger, this.performanceClient, this.nativeMessageHandler);
|
|
14806
|
+
}
|
|
14724
14807
|
/**
|
|
14725
14808
|
*
|
|
14726
14809
|
* @param validRequest
|
|
@@ -14796,7 +14879,6 @@
|
|
|
14796
14879
|
e.setCorrelationId(this.correlationId);
|
|
14797
14880
|
serverTelemetryManager.cacheFailedRequest(e);
|
|
14798
14881
|
}
|
|
14799
|
-
this.browserStorage.setInteractionInProgress(false);
|
|
14800
14882
|
this.eventHandler.emitEvent(EventType.LOGOUT_FAILURE, exports.InteractionType.Popup, null, e);
|
|
14801
14883
|
this.eventHandler.emitEvent(EventType.LOGOUT_END, exports.InteractionType.Popup);
|
|
14802
14884
|
throw e;
|
|
@@ -14908,7 +14990,6 @@
|
|
|
14908
14990
|
}
|
|
14909
14991
|
catch (e) {
|
|
14910
14992
|
this.logger.error("error opening popup " + e.message);
|
|
14911
|
-
this.browserStorage.setInteractionInProgress(false);
|
|
14912
14993
|
throw createBrowserAuthError(popupWindowError);
|
|
14913
14994
|
}
|
|
14914
14995
|
}
|
|
@@ -14966,7 +15047,6 @@
|
|
|
14966
15047
|
* Event callback to unload main window.
|
|
14967
15048
|
*/
|
|
14968
15049
|
unloadWindow(e) {
|
|
14969
|
-
this.browserStorage.cleanRequestByInteractionType(exports.InteractionType.Popup);
|
|
14970
15050
|
if (this.currentWindow) {
|
|
14971
15051
|
this.currentWindow.close();
|
|
14972
15052
|
}
|
|
@@ -14982,8 +15062,6 @@
|
|
|
14982
15062
|
popupWindow.close();
|
|
14983
15063
|
// Remove window unload function
|
|
14984
15064
|
popupWindowParent.removeEventListener("beforeunload", this.unloadWindow);
|
|
14985
|
-
// Interaction is completed - remove interaction status.
|
|
14986
|
-
this.browserStorage.setInteractionInProgress(false);
|
|
14987
15065
|
}
|
|
14988
15066
|
/**
|
|
14989
15067
|
* Generates the name for the popup based on the client id and request
|
|
@@ -15004,141 +15082,6 @@
|
|
|
15004
15082
|
}
|
|
15005
15083
|
}
|
|
15006
15084
|
|
|
15007
|
-
/*
|
|
15008
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
15009
|
-
* Licensed under the MIT License.
|
|
15010
|
-
*/
|
|
15011
|
-
class RedirectHandler {
|
|
15012
|
-
constructor(authCodeModule, storageImpl, authCodeRequest, logger, performanceClient) {
|
|
15013
|
-
this.authModule = authCodeModule;
|
|
15014
|
-
this.browserStorage = storageImpl;
|
|
15015
|
-
this.authCodeRequest = authCodeRequest;
|
|
15016
|
-
this.logger = logger;
|
|
15017
|
-
this.performanceClient = performanceClient;
|
|
15018
|
-
}
|
|
15019
|
-
/**
|
|
15020
|
-
* Redirects window to given URL.
|
|
15021
|
-
* @param urlNavigate
|
|
15022
|
-
*/
|
|
15023
|
-
async initiateAuthRequest(requestUrl, params) {
|
|
15024
|
-
this.logger.verbose("RedirectHandler.initiateAuthRequest called");
|
|
15025
|
-
// Navigate if valid URL
|
|
15026
|
-
if (requestUrl) {
|
|
15027
|
-
// Cache start page, returns to this page after redirectUri if navigateToLoginRequestUrl is true
|
|
15028
|
-
if (params.redirectStartPage) {
|
|
15029
|
-
this.logger.verbose("RedirectHandler.initiateAuthRequest: redirectStartPage set, caching start page");
|
|
15030
|
-
this.browserStorage.setTemporaryCache(TemporaryCacheKeys.ORIGIN_URI, params.redirectStartPage, true);
|
|
15031
|
-
}
|
|
15032
|
-
// Set interaction status in the library.
|
|
15033
|
-
this.browserStorage.setTemporaryCache(TemporaryCacheKeys.CORRELATION_ID, this.authCodeRequest.correlationId, true);
|
|
15034
|
-
this.browserStorage.cacheCodeRequest(this.authCodeRequest);
|
|
15035
|
-
this.logger.infoPii(`RedirectHandler.initiateAuthRequest: Navigate to: ${requestUrl}`);
|
|
15036
|
-
const navigationOptions = {
|
|
15037
|
-
apiId: ApiId.acquireTokenRedirect,
|
|
15038
|
-
timeout: params.redirectTimeout,
|
|
15039
|
-
noHistory: false,
|
|
15040
|
-
};
|
|
15041
|
-
// If onRedirectNavigate is implemented, invoke it and provide requestUrl
|
|
15042
|
-
if (typeof params.onRedirectNavigate === "function") {
|
|
15043
|
-
this.logger.verbose("RedirectHandler.initiateAuthRequest: Invoking onRedirectNavigate callback");
|
|
15044
|
-
const navigate = params.onRedirectNavigate(requestUrl);
|
|
15045
|
-
// Returning false from onRedirectNavigate will stop navigation
|
|
15046
|
-
if (navigate !== false) {
|
|
15047
|
-
this.logger.verbose("RedirectHandler.initiateAuthRequest: onRedirectNavigate did not return false, navigating");
|
|
15048
|
-
await params.navigationClient.navigateExternal(requestUrl, navigationOptions);
|
|
15049
|
-
return;
|
|
15050
|
-
}
|
|
15051
|
-
else {
|
|
15052
|
-
this.logger.verbose("RedirectHandler.initiateAuthRequest: onRedirectNavigate returned false, stopping navigation");
|
|
15053
|
-
return;
|
|
15054
|
-
}
|
|
15055
|
-
}
|
|
15056
|
-
else {
|
|
15057
|
-
// Navigate window to request URL
|
|
15058
|
-
this.logger.verbose("RedirectHandler.initiateAuthRequest: Navigating window to navigate url");
|
|
15059
|
-
await params.navigationClient.navigateExternal(requestUrl, navigationOptions);
|
|
15060
|
-
return;
|
|
15061
|
-
}
|
|
15062
|
-
}
|
|
15063
|
-
else {
|
|
15064
|
-
// Throw error if request URL is empty.
|
|
15065
|
-
this.logger.info("RedirectHandler.initiateAuthRequest: Navigate url is empty");
|
|
15066
|
-
throw createBrowserAuthError(emptyNavigateUri);
|
|
15067
|
-
}
|
|
15068
|
-
}
|
|
15069
|
-
/**
|
|
15070
|
-
* Handle authorization code response in the window.
|
|
15071
|
-
* @param hash
|
|
15072
|
-
*/
|
|
15073
|
-
async handleCodeResponse(response, state) {
|
|
15074
|
-
this.logger.verbose("RedirectHandler.handleCodeResponse called");
|
|
15075
|
-
// Interaction is completed - remove interaction status.
|
|
15076
|
-
this.browserStorage.setInteractionInProgress(false);
|
|
15077
|
-
// Handle code response.
|
|
15078
|
-
const stateKey = this.browserStorage.generateStateKey(state);
|
|
15079
|
-
const requestState = this.browserStorage.getTemporaryCache(stateKey);
|
|
15080
|
-
if (!requestState) {
|
|
15081
|
-
throw createClientAuthError(stateNotFound, "Cached State");
|
|
15082
|
-
}
|
|
15083
|
-
let authCodeResponse;
|
|
15084
|
-
try {
|
|
15085
|
-
authCodeResponse = getAuthorizationCodePayload(response, requestState);
|
|
15086
|
-
}
|
|
15087
|
-
catch (e) {
|
|
15088
|
-
if (e instanceof ServerError &&
|
|
15089
|
-
e.subError === userCancelled) {
|
|
15090
|
-
// Translate server error caused by user closing native prompt to corresponding first class MSAL error
|
|
15091
|
-
throw createBrowserAuthError(userCancelled);
|
|
15092
|
-
}
|
|
15093
|
-
else {
|
|
15094
|
-
throw e;
|
|
15095
|
-
}
|
|
15096
|
-
}
|
|
15097
|
-
// Get cached items
|
|
15098
|
-
const nonceKey = this.browserStorage.generateNonceKey(requestState);
|
|
15099
|
-
const cachedNonce = this.browserStorage.getTemporaryCache(nonceKey);
|
|
15100
|
-
// Assign code to request
|
|
15101
|
-
this.authCodeRequest.code = authCodeResponse.code;
|
|
15102
|
-
// Check for new cloud instance
|
|
15103
|
-
if (authCodeResponse.cloud_instance_host_name) {
|
|
15104
|
-
await invokeAsync(this.authModule.updateAuthority.bind(this.authModule), PerformanceEvents.UpdateTokenEndpointAuthority, this.logger, this.performanceClient, this.authCodeRequest.correlationId)(authCodeResponse.cloud_instance_host_name, this.authCodeRequest.correlationId);
|
|
15105
|
-
}
|
|
15106
|
-
authCodeResponse.nonce = cachedNonce || undefined;
|
|
15107
|
-
authCodeResponse.state = requestState;
|
|
15108
|
-
// Add CCS parameters if available
|
|
15109
|
-
if (authCodeResponse.client_info) {
|
|
15110
|
-
this.authCodeRequest.clientInfo = authCodeResponse.client_info;
|
|
15111
|
-
}
|
|
15112
|
-
else {
|
|
15113
|
-
const cachedCcsCred = this.checkCcsCredentials();
|
|
15114
|
-
if (cachedCcsCred) {
|
|
15115
|
-
this.authCodeRequest.ccsCredential = cachedCcsCred;
|
|
15116
|
-
}
|
|
15117
|
-
}
|
|
15118
|
-
// Acquire token with retrieved code.
|
|
15119
|
-
const tokenResponse = (await this.authModule.acquireToken(this.authCodeRequest, authCodeResponse));
|
|
15120
|
-
this.browserStorage.cleanRequestByState(state);
|
|
15121
|
-
return tokenResponse;
|
|
15122
|
-
}
|
|
15123
|
-
/**
|
|
15124
|
-
* Looks up ccs creds in the cache
|
|
15125
|
-
*/
|
|
15126
|
-
checkCcsCredentials() {
|
|
15127
|
-
// Look up ccs credential in temp cache
|
|
15128
|
-
const cachedCcsCred = this.browserStorage.getTemporaryCache(TemporaryCacheKeys.CCS_CREDENTIAL, true);
|
|
15129
|
-
if (cachedCcsCred) {
|
|
15130
|
-
try {
|
|
15131
|
-
return JSON.parse(cachedCcsCred);
|
|
15132
|
-
}
|
|
15133
|
-
catch (e) {
|
|
15134
|
-
this.authModule.logger.error("Cache credential could not be parsed");
|
|
15135
|
-
this.authModule.logger.errorPii(`Cache credential could not be parsed: ${cachedCcsCred}`);
|
|
15136
|
-
}
|
|
15137
|
-
}
|
|
15138
|
-
return null;
|
|
15139
|
-
}
|
|
15140
|
-
}
|
|
15141
|
-
|
|
15142
15085
|
/*
|
|
15143
15086
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
15144
15087
|
* Licensed under the MIT License.
|
|
@@ -15166,62 +15109,96 @@
|
|
|
15166
15109
|
*/
|
|
15167
15110
|
async acquireToken(request) {
|
|
15168
15111
|
const validRequest = await invokeAsync(this.initializeAuthorizationRequest.bind(this), PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest, this.logger, this.performanceClient, this.correlationId)(request, exports.InteractionType.Redirect);
|
|
15169
|
-
|
|
15170
|
-
|
|
15171
|
-
this.browserStorage.updateCacheEntries(validRequest.state, validRequest.nonce, validRequest.authority, validRequest.loginHint || "", validRequest.account || null);
|
|
15172
|
-
const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenRedirect);
|
|
15112
|
+
validRequest.platformBroker =
|
|
15113
|
+
NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeMessageHandler, request.authenticationScheme);
|
|
15173
15114
|
const handleBackButton = (event) => {
|
|
15174
15115
|
// Clear temporary cache if the back button is clicked during the redirect flow.
|
|
15175
15116
|
if (event.persisted) {
|
|
15176
15117
|
this.logger.verbose("Page was restored from back/forward cache. Clearing temporary cache.");
|
|
15177
|
-
this.browserStorage.
|
|
15118
|
+
this.browserStorage.resetRequestCache();
|
|
15178
15119
|
this.eventHandler.emitEvent(EventType.RESTORE_FROM_BFCACHE, exports.InteractionType.Redirect);
|
|
15179
15120
|
}
|
|
15180
15121
|
};
|
|
15122
|
+
const redirectStartPage = this.getRedirectStartPage(request.redirectStartPage);
|
|
15123
|
+
this.logger.verbosePii(`Redirect start page: ${redirectStartPage}`);
|
|
15124
|
+
// Cache start page, returns to this page after redirectUri if navigateToLoginRequestUrl is true
|
|
15125
|
+
this.browserStorage.setTemporaryCache(TemporaryCacheKeys.ORIGIN_URI, redirectStartPage, true);
|
|
15126
|
+
// Clear temporary cache if the back button is clicked during the redirect flow.
|
|
15127
|
+
window.addEventListener("pageshow", handleBackButton);
|
|
15128
|
+
try {
|
|
15129
|
+
if (this.config.auth.protocolMode === ProtocolMode.EAR) {
|
|
15130
|
+
await this.executeEarFlow(validRequest);
|
|
15131
|
+
}
|
|
15132
|
+
else {
|
|
15133
|
+
await this.executeCodeFlow(validRequest, request.onRedirectNavigate);
|
|
15134
|
+
}
|
|
15135
|
+
}
|
|
15136
|
+
catch (e) {
|
|
15137
|
+
if (e instanceof AuthError) {
|
|
15138
|
+
e.setCorrelationId(this.correlationId);
|
|
15139
|
+
}
|
|
15140
|
+
window.removeEventListener("pageshow", handleBackButton);
|
|
15141
|
+
throw e;
|
|
15142
|
+
}
|
|
15143
|
+
}
|
|
15144
|
+
/**
|
|
15145
|
+
* Executes auth code + PKCE flow
|
|
15146
|
+
* @param request
|
|
15147
|
+
* @returns
|
|
15148
|
+
*/
|
|
15149
|
+
async executeCodeFlow(request, onRedirectNavigate) {
|
|
15150
|
+
const correlationId = request.correlationId;
|
|
15151
|
+
const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenRedirect);
|
|
15152
|
+
const pkceCodes = await invokeAsync(generatePkceCodes, PerformanceEvents.GeneratePkceCodes, this.logger, this.performanceClient, correlationId)(this.performanceClient, this.logger, correlationId);
|
|
15153
|
+
const redirectRequest = {
|
|
15154
|
+
...request,
|
|
15155
|
+
codeChallenge: pkceCodes.challenge,
|
|
15156
|
+
};
|
|
15157
|
+
this.browserStorage.cacheAuthorizeRequest(redirectRequest, pkceCodes.verifier);
|
|
15181
15158
|
try {
|
|
15182
15159
|
// Initialize the client
|
|
15183
15160
|
const authClient = await invokeAsync(this.createAuthCodeClient.bind(this), PerformanceEvents.StandardInteractionClientCreateAuthCodeClient, this.logger, this.performanceClient, this.correlationId)({
|
|
15184
15161
|
serverTelemetryManager,
|
|
15185
|
-
requestAuthority:
|
|
15186
|
-
requestAzureCloudOptions:
|
|
15187
|
-
requestExtraQueryParameters:
|
|
15188
|
-
account:
|
|
15162
|
+
requestAuthority: redirectRequest.authority,
|
|
15163
|
+
requestAzureCloudOptions: redirectRequest.azureCloudOptions,
|
|
15164
|
+
requestExtraQueryParameters: redirectRequest.extraQueryParameters,
|
|
15165
|
+
account: redirectRequest.account,
|
|
15189
15166
|
});
|
|
15190
|
-
const authCodeRequest = {
|
|
15191
|
-
...validRequest,
|
|
15192
|
-
code: "",
|
|
15193
|
-
codeVerifier: pkceCodes.verifier,
|
|
15194
|
-
};
|
|
15195
|
-
// Create redirect interaction handler.
|
|
15196
|
-
const interactionHandler = new RedirectHandler(authClient, this.browserStorage, authCodeRequest, this.logger, this.performanceClient);
|
|
15197
15167
|
// Create acquire token url.
|
|
15198
|
-
const navigateUrl = await invokeAsync(getAuthCodeRequestUrl, PerformanceEvents.GetAuthCodeUrl, this.logger, this.performanceClient,
|
|
15199
|
-
...validRequest,
|
|
15200
|
-
platformBroker: NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeMessageHandler, request.authenticationScheme),
|
|
15201
|
-
}, this.logger, this.performanceClient);
|
|
15202
|
-
const redirectStartPage = this.getRedirectStartPage(request.redirectStartPage);
|
|
15203
|
-
this.logger.verbosePii(`Redirect start page: ${redirectStartPage}`);
|
|
15204
|
-
// Clear temporary cache if the back button is clicked during the redirect flow.
|
|
15205
|
-
window.addEventListener("pageshow", handleBackButton);
|
|
15168
|
+
const navigateUrl = await invokeAsync(getAuthCodeRequestUrl, PerformanceEvents.GetAuthCodeUrl, this.logger, this.performanceClient, request.correlationId)(this.config, authClient.authority, redirectRequest, this.logger, this.performanceClient);
|
|
15206
15169
|
// Show the UI once the url has been created. Response will come back in the hash, which will be handled in the handleRedirectCallback function.
|
|
15207
|
-
return await
|
|
15208
|
-
navigationClient: this.navigationClient,
|
|
15209
|
-
redirectTimeout: this.config.system.redirectNavigationTimeout,
|
|
15210
|
-
redirectStartPage: redirectStartPage,
|
|
15211
|
-
onRedirectNavigate: request.onRedirectNavigate ||
|
|
15212
|
-
this.config.auth.onRedirectNavigate,
|
|
15213
|
-
});
|
|
15170
|
+
return await this.initiateAuthRequest(navigateUrl, onRedirectNavigate);
|
|
15214
15171
|
}
|
|
15215
15172
|
catch (e) {
|
|
15216
15173
|
if (e instanceof AuthError) {
|
|
15217
15174
|
e.setCorrelationId(this.correlationId);
|
|
15218
15175
|
serverTelemetryManager.cacheFailedRequest(e);
|
|
15219
15176
|
}
|
|
15220
|
-
window.removeEventListener("pageshow", handleBackButton);
|
|
15221
|
-
this.browserStorage.cleanRequestByState(validRequest.state);
|
|
15222
15177
|
throw e;
|
|
15223
15178
|
}
|
|
15224
15179
|
}
|
|
15180
|
+
/**
|
|
15181
|
+
* Executes EAR flow
|
|
15182
|
+
* @param request
|
|
15183
|
+
*/
|
|
15184
|
+
async executeEarFlow(request) {
|
|
15185
|
+
const correlationId = request.correlationId;
|
|
15186
|
+
// Get the frame handle for the silent request
|
|
15187
|
+
const discoveredAuthority = await invokeAsync(this.getDiscoveredAuthority.bind(this), PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority, this.logger, this.performanceClient, correlationId)({
|
|
15188
|
+
requestAuthority: request.authority,
|
|
15189
|
+
requestAzureCloudOptions: request.azureCloudOptions,
|
|
15190
|
+
requestExtraQueryParameters: request.extraQueryParameters,
|
|
15191
|
+
account: request.account,
|
|
15192
|
+
});
|
|
15193
|
+
const earJwk = await invokeAsync(generateEarKey, PerformanceEvents.GenerateEarKey, this.logger, this.performanceClient, correlationId)();
|
|
15194
|
+
const redirectRequest = {
|
|
15195
|
+
...request,
|
|
15196
|
+
earJwk: earJwk,
|
|
15197
|
+
};
|
|
15198
|
+
this.browserStorage.cacheAuthorizeRequest(redirectRequest);
|
|
15199
|
+
const form = await getEARForm(document, this.config, discoveredAuthority, redirectRequest, this.logger, this.performanceClient);
|
|
15200
|
+
form.submit();
|
|
15201
|
+
}
|
|
15225
15202
|
/**
|
|
15226
15203
|
* Checks if navigateToLoginRequestUrl is set, and:
|
|
15227
15204
|
* - if true, performs logic to cache and navigate
|
|
@@ -15229,18 +15206,14 @@
|
|
|
15229
15206
|
* @param hash {string} url hash
|
|
15230
15207
|
* @param parentMeasurement {InProgressPerformanceEvent} parent measurement
|
|
15231
15208
|
*/
|
|
15232
|
-
async handleRedirectPromise(hash = "", parentMeasurement) {
|
|
15209
|
+
async handleRedirectPromise(hash = "", request, pkceVerifier, parentMeasurement) {
|
|
15233
15210
|
const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.handleRedirectPromise);
|
|
15234
15211
|
try {
|
|
15235
|
-
if (!this.browserStorage.isInteractionInProgress(true)) {
|
|
15236
|
-
this.logger.info("handleRedirectPromise called but there is no interaction in progress, returning null.");
|
|
15237
|
-
return null;
|
|
15238
|
-
}
|
|
15239
15212
|
const [serverParams, responseString] = this.getRedirectResponse(hash || "");
|
|
15240
15213
|
if (!serverParams) {
|
|
15241
15214
|
// Not a recognized server response hash or hash not associated with a redirect request
|
|
15242
15215
|
this.logger.info("handleRedirectPromise did not detect a response as a result of a redirect. Cleaning temporary cache.");
|
|
15243
|
-
this.browserStorage.
|
|
15216
|
+
this.browserStorage.resetRequestCache();
|
|
15244
15217
|
// Do not instrument "no_server_response" if user clicked back button
|
|
15245
15218
|
if (getNavigationType() !== "back_forward") {
|
|
15246
15219
|
parentMeasurement.event.errorCode = "no_server_response";
|
|
@@ -15262,12 +15235,12 @@
|
|
|
15262
15235
|
// Replace current hash with non-msal hash, if present
|
|
15263
15236
|
replaceHash(loginRequestUrl);
|
|
15264
15237
|
}
|
|
15265
|
-
const handleHashResult = await this.handleResponse(serverParams, serverTelemetryManager);
|
|
15238
|
+
const handleHashResult = await this.handleResponse(serverParams, request, pkceVerifier, serverTelemetryManager);
|
|
15266
15239
|
return handleHashResult;
|
|
15267
15240
|
}
|
|
15268
15241
|
else if (!this.config.auth.navigateToLoginRequestUrl) {
|
|
15269
15242
|
this.logger.verbose("NavigateToLoginRequestUrl set to false, handling response");
|
|
15270
|
-
return await this.handleResponse(serverParams, serverTelemetryManager);
|
|
15243
|
+
return await this.handleResponse(serverParams, request, pkceVerifier, serverTelemetryManager);
|
|
15271
15244
|
}
|
|
15272
15245
|
else if (!isInIframe() ||
|
|
15273
15246
|
this.config.system.allowRedirectInIframe) {
|
|
@@ -15303,7 +15276,7 @@
|
|
|
15303
15276
|
}
|
|
15304
15277
|
// If navigateInternal implementation returns false, handle the hash now
|
|
15305
15278
|
if (!processHashOnRedirect) {
|
|
15306
|
-
return await this.handleResponse(serverParams, serverTelemetryManager);
|
|
15279
|
+
return await this.handleResponse(serverParams, request, pkceVerifier, serverTelemetryManager);
|
|
15307
15280
|
}
|
|
15308
15281
|
}
|
|
15309
15282
|
return null;
|
|
@@ -15313,7 +15286,6 @@
|
|
|
15313
15286
|
e.setCorrelationId(this.correlationId);
|
|
15314
15287
|
serverTelemetryManager.cacheFailedRequest(e);
|
|
15315
15288
|
}
|
|
15316
|
-
this.browserStorage.cleanRequestByInteractionType(exports.InteractionType.Redirect);
|
|
15317
15289
|
throw e;
|
|
15318
15290
|
}
|
|
15319
15291
|
}
|
|
@@ -15366,39 +15338,67 @@
|
|
|
15366
15338
|
* @param hash
|
|
15367
15339
|
* @param state
|
|
15368
15340
|
*/
|
|
15369
|
-
async handleResponse(serverParams, serverTelemetryManager) {
|
|
15341
|
+
async handleResponse(serverParams, request, codeVerifier, serverTelemetryManager) {
|
|
15370
15342
|
const state = serverParams.state;
|
|
15371
15343
|
if (!state) {
|
|
15372
15344
|
throw createBrowserAuthError(noStateInHash);
|
|
15373
15345
|
}
|
|
15374
|
-
|
|
15375
|
-
|
|
15376
|
-
|
|
15377
|
-
|
|
15378
|
-
|
|
15379
|
-
|
|
15380
|
-
}
|
|
15381
|
-
const nativeInteractionClient = new NativeInteractionClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, ApiId.acquireTokenPopup, this.performanceClient, this.nativeMessageHandler, serverParams.accountId, this.nativeStorage, cachedRequest.correlationId);
|
|
15382
|
-
const { userRequestState } = ProtocolUtils.parseRequestState(this.browserCrypto, state);
|
|
15383
|
-
return nativeInteractionClient
|
|
15384
|
-
.acquireToken({
|
|
15385
|
-
...cachedRequest,
|
|
15386
|
-
state: userRequestState,
|
|
15387
|
-
prompt: undefined, // Server should handle the prompt, ideally native broker can do this part silently
|
|
15388
|
-
})
|
|
15389
|
-
.finally(() => {
|
|
15390
|
-
this.browserStorage.cleanRequestByState(state);
|
|
15346
|
+
if (serverParams.ear_jwe) {
|
|
15347
|
+
const discoveredAuthority = await invokeAsync(this.getDiscoveredAuthority.bind(this), PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority, this.logger, this.performanceClient, request.correlationId)({
|
|
15348
|
+
requestAuthority: request.authority,
|
|
15349
|
+
requestAzureCloudOptions: request.azureCloudOptions,
|
|
15350
|
+
requestExtraQueryParameters: request.extraQueryParameters,
|
|
15351
|
+
account: request.account,
|
|
15391
15352
|
});
|
|
15353
|
+
return invokeAsync(handleResponseEAR, PerformanceEvents.HandleResponseEar, this.logger, this.performanceClient, request.correlationId)(request, serverParams, ApiId.acquireTokenRedirect, this.config, discoveredAuthority, this.browserStorage, this.nativeStorage, this.eventHandler, this.logger, this.performanceClient, this.nativeMessageHandler);
|
|
15354
|
+
}
|
|
15355
|
+
const authClient = await invokeAsync(this.createAuthCodeClient.bind(this), PerformanceEvents.StandardInteractionClientCreateAuthCodeClient, this.logger, this.performanceClient, this.correlationId)({ serverTelemetryManager, requestAuthority: request.authority });
|
|
15356
|
+
return invokeAsync(handleResponseCode, PerformanceEvents.HandleResponseCode, this.logger, this.performanceClient, request.correlationId)(request, serverParams, codeVerifier, ApiId.acquireTokenRedirect, this.config, authClient, this.browserStorage, this.nativeStorage, this.eventHandler, this.logger, this.performanceClient, this.nativeMessageHandler);
|
|
15357
|
+
}
|
|
15358
|
+
/**
|
|
15359
|
+
* Redirects window to given URL.
|
|
15360
|
+
* @param urlNavigate
|
|
15361
|
+
* @param onRedirectNavigateRequest - onRedirectNavigate callback provided on the request
|
|
15362
|
+
*/
|
|
15363
|
+
async initiateAuthRequest(requestUrl, onRedirectNavigateRequest) {
|
|
15364
|
+
this.logger.verbose("RedirectHandler.initiateAuthRequest called");
|
|
15365
|
+
// Navigate if valid URL
|
|
15366
|
+
if (requestUrl) {
|
|
15367
|
+
this.logger.infoPii(`RedirectHandler.initiateAuthRequest: Navigate to: ${requestUrl}`);
|
|
15368
|
+
const navigationOptions = {
|
|
15369
|
+
apiId: ApiId.acquireTokenRedirect,
|
|
15370
|
+
timeout: this.config.system.redirectNavigationTimeout,
|
|
15371
|
+
noHistory: false,
|
|
15372
|
+
};
|
|
15373
|
+
const onRedirectNavigate = onRedirectNavigateRequest ||
|
|
15374
|
+
this.config.auth.onRedirectNavigate;
|
|
15375
|
+
// If onRedirectNavigate is implemented, invoke it and provide requestUrl
|
|
15376
|
+
if (typeof onRedirectNavigate === "function") {
|
|
15377
|
+
this.logger.verbose("RedirectHandler.initiateAuthRequest: Invoking onRedirectNavigate callback");
|
|
15378
|
+
const navigate = onRedirectNavigate(requestUrl);
|
|
15379
|
+
// Returning false from onRedirectNavigate will stop navigation
|
|
15380
|
+
if (navigate !== false) {
|
|
15381
|
+
this.logger.verbose("RedirectHandler.initiateAuthRequest: onRedirectNavigate did not return false, navigating");
|
|
15382
|
+
await this.navigationClient.navigateExternal(requestUrl, navigationOptions);
|
|
15383
|
+
return;
|
|
15384
|
+
}
|
|
15385
|
+
else {
|
|
15386
|
+
this.logger.verbose("RedirectHandler.initiateAuthRequest: onRedirectNavigate returned false, stopping navigation");
|
|
15387
|
+
return;
|
|
15388
|
+
}
|
|
15389
|
+
}
|
|
15390
|
+
else {
|
|
15391
|
+
// Navigate window to request URL
|
|
15392
|
+
this.logger.verbose("RedirectHandler.initiateAuthRequest: Navigating window to navigate url");
|
|
15393
|
+
await this.navigationClient.navigateExternal(requestUrl, navigationOptions);
|
|
15394
|
+
return;
|
|
15395
|
+
}
|
|
15392
15396
|
}
|
|
15393
|
-
|
|
15394
|
-
|
|
15395
|
-
|
|
15396
|
-
throw createBrowserAuthError(
|
|
15397
|
+
else {
|
|
15398
|
+
// Throw error if request URL is empty.
|
|
15399
|
+
this.logger.info("RedirectHandler.initiateAuthRequest: Navigate url is empty");
|
|
15400
|
+
throw createBrowserAuthError(emptyNavigateUri);
|
|
15397
15401
|
}
|
|
15398
|
-
const authClient = await invokeAsync(this.createAuthCodeClient.bind(this), PerformanceEvents.StandardInteractionClientCreateAuthCodeClient, this.logger, this.performanceClient, this.correlationId)({ serverTelemetryManager, requestAuthority: currentAuthority });
|
|
15399
|
-
ThrottlingUtils.removeThrottle(this.browserStorage, this.config.auth.clientId, cachedRequest);
|
|
15400
|
-
const interactionHandler = new RedirectHandler(authClient, this.browserStorage, cachedRequest, this.logger, this.performanceClient);
|
|
15401
|
-
return interactionHandler.handleCodeResponse(serverParams, state);
|
|
15402
15402
|
}
|
|
15403
15403
|
/**
|
|
15404
15404
|
* Use to log out the current user, and redirect the user to the postLogoutRedirectUri.
|
|
@@ -15497,7 +15497,7 @@
|
|
|
15497
15497
|
* @param urlNavigate
|
|
15498
15498
|
* @param userRequestScopes
|
|
15499
15499
|
*/
|
|
15500
|
-
async function
|
|
15500
|
+
async function initiateCodeRequest(requestUrl, performanceClient, logger, correlationId, navigateFrameWait) {
|
|
15501
15501
|
performanceClient.addQueueMeasurement(PerformanceEvents.SilentHandlerInitiateAuthRequest, correlationId);
|
|
15502
15502
|
if (!requestUrl) {
|
|
15503
15503
|
// Throw error if request URL is empty.
|
|
@@ -15509,6 +15509,15 @@
|
|
|
15509
15509
|
}
|
|
15510
15510
|
return invoke(loadFrameSync, PerformanceEvents.SilentHandlerLoadFrameSync, logger, performanceClient, correlationId)(requestUrl);
|
|
15511
15511
|
}
|
|
15512
|
+
async function initiateEarRequest(config, authority, request, logger, performanceClient) {
|
|
15513
|
+
const frame = createHiddenIframe();
|
|
15514
|
+
if (!frame.contentDocument) {
|
|
15515
|
+
throw "No document associated with iframe!";
|
|
15516
|
+
}
|
|
15517
|
+
const form = await getEARForm(frame.contentDocument, config, authority, request, logger, performanceClient);
|
|
15518
|
+
form.submit();
|
|
15519
|
+
return frame;
|
|
15520
|
+
}
|
|
15512
15521
|
/**
|
|
15513
15522
|
* Monitors an iframe content window until it loads a url with a known hash, or hits a specified timeout.
|
|
15514
15523
|
* @param iframe
|
|
@@ -15659,19 +15668,34 @@
|
|
|
15659
15668
|
}
|
|
15660
15669
|
// Create silent request
|
|
15661
15670
|
const silentRequest = await invokeAsync(this.initializeAuthorizationRequest.bind(this), PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest, this.logger, this.performanceClient, request.correlationId)(inputRequest, exports.InteractionType.Silent);
|
|
15671
|
+
silentRequest.platformBroker =
|
|
15672
|
+
NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeMessageHandler, silentRequest.authenticationScheme);
|
|
15662
15673
|
preconnect(silentRequest.authority);
|
|
15663
|
-
|
|
15674
|
+
if (this.config.auth.protocolMode === ProtocolMode.EAR) {
|
|
15675
|
+
return this.executeEarFlow(silentRequest);
|
|
15676
|
+
}
|
|
15677
|
+
else {
|
|
15678
|
+
return this.executeCodeFlow(silentRequest);
|
|
15679
|
+
}
|
|
15680
|
+
}
|
|
15681
|
+
/**
|
|
15682
|
+
* Executes auth code + PKCE flow
|
|
15683
|
+
* @param request
|
|
15684
|
+
* @returns
|
|
15685
|
+
*/
|
|
15686
|
+
async executeCodeFlow(request) {
|
|
15664
15687
|
let authClient;
|
|
15688
|
+
const serverTelemetryManager = this.initializeServerTelemetryManager(this.apiId);
|
|
15665
15689
|
try {
|
|
15666
15690
|
// Initialize the client
|
|
15667
15691
|
authClient = await invokeAsync(this.createAuthCodeClient.bind(this), PerformanceEvents.StandardInteractionClientCreateAuthCodeClient, this.logger, this.performanceClient, request.correlationId)({
|
|
15668
15692
|
serverTelemetryManager,
|
|
15669
|
-
requestAuthority:
|
|
15670
|
-
requestAzureCloudOptions:
|
|
15671
|
-
requestExtraQueryParameters:
|
|
15672
|
-
account:
|
|
15693
|
+
requestAuthority: request.authority,
|
|
15694
|
+
requestAzureCloudOptions: request.azureCloudOptions,
|
|
15695
|
+
requestExtraQueryParameters: request.extraQueryParameters,
|
|
15696
|
+
account: request.account,
|
|
15673
15697
|
});
|
|
15674
|
-
return await invokeAsync(this.silentTokenHelper.bind(this), PerformanceEvents.SilentIframeClientTokenHelper, this.logger, this.performanceClient, request.correlationId)(authClient,
|
|
15698
|
+
return await invokeAsync(this.silentTokenHelper.bind(this), PerformanceEvents.SilentIframeClientTokenHelper, this.logger, this.performanceClient, request.correlationId)(authClient, request);
|
|
15675
15699
|
}
|
|
15676
15700
|
catch (e) {
|
|
15677
15701
|
if (e instanceof AuthError) {
|
|
@@ -15686,10 +15710,33 @@
|
|
|
15686
15710
|
this.performanceClient.addFields({
|
|
15687
15711
|
retryError: e.errorCode,
|
|
15688
15712
|
}, this.correlationId);
|
|
15689
|
-
|
|
15690
|
-
return await invokeAsync(this.silentTokenHelper.bind(this), PerformanceEvents.SilentIframeClientTokenHelper, this.logger, this.performanceClient, this.correlationId)(authClient, retrySilentRequest);
|
|
15713
|
+
return await invokeAsync(this.silentTokenHelper.bind(this), PerformanceEvents.SilentIframeClientTokenHelper, this.logger, this.performanceClient, this.correlationId)(authClient, request);
|
|
15691
15714
|
}
|
|
15692
15715
|
}
|
|
15716
|
+
/**
|
|
15717
|
+
* Executes EAR flow
|
|
15718
|
+
* @param request
|
|
15719
|
+
*/
|
|
15720
|
+
async executeEarFlow(request) {
|
|
15721
|
+
const correlationId = request.correlationId;
|
|
15722
|
+
const discoveredAuthority = await invokeAsync(this.getDiscoveredAuthority.bind(this), PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority, this.logger, this.performanceClient, correlationId)({
|
|
15723
|
+
requestAuthority: request.authority,
|
|
15724
|
+
requestAzureCloudOptions: request.azureCloudOptions,
|
|
15725
|
+
requestExtraQueryParameters: request.extraQueryParameters,
|
|
15726
|
+
account: request.account,
|
|
15727
|
+
});
|
|
15728
|
+
const earJwk = await invokeAsync(generateEarKey, PerformanceEvents.GenerateEarKey, this.logger, this.performanceClient, correlationId)();
|
|
15729
|
+
const silentRequest = {
|
|
15730
|
+
...request,
|
|
15731
|
+
earJwk: earJwk,
|
|
15732
|
+
};
|
|
15733
|
+
const msalFrame = await invokeAsync(initiateEarRequest, PerformanceEvents.SilentHandlerInitiateAuthRequest, this.logger, this.performanceClient, correlationId)(this.config, discoveredAuthority, silentRequest, this.logger, this.performanceClient);
|
|
15734
|
+
const responseType = this.config.auth.OIDCOptions.serverResponseType;
|
|
15735
|
+
// Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
|
|
15736
|
+
const responseString = await invokeAsync(monitorIframeForHash, PerformanceEvents.SilentHandlerMonitorIframeForHash, this.logger, this.performanceClient, correlationId)(msalFrame, this.config.system.iframeHashTimeout, this.config.system.pollIntervalMilliseconds, this.performanceClient, this.logger, correlationId, responseType);
|
|
15737
|
+
const serverParams = invoke(deserializeResponse, PerformanceEvents.DeserializeResponse, this.logger, this.performanceClient, correlationId)(responseString, responseType, this.logger);
|
|
15738
|
+
return invokeAsync(handleResponseEAR, PerformanceEvents.HandleResponseEar, this.logger, this.performanceClient, correlationId)(silentRequest, serverParams, this.apiId, this.config, discoveredAuthority, this.browserStorage, this.nativeStorage, this.eventHandler, this.logger, this.performanceClient, this.nativeMessageHandler);
|
|
15739
|
+
}
|
|
15693
15740
|
/**
|
|
15694
15741
|
* Currently Unsupported
|
|
15695
15742
|
*/
|
|
@@ -15706,44 +15753,20 @@
|
|
|
15706
15753
|
async silentTokenHelper(authClient, request) {
|
|
15707
15754
|
const correlationId = request.correlationId;
|
|
15708
15755
|
this.performanceClient.addQueueMeasurement(PerformanceEvents.SilentIframeClientTokenHelper, correlationId);
|
|
15709
|
-
const pkceCodes = await invokeAsync(generatePkceCodes, PerformanceEvents.GeneratePkceCodes, this.logger, this.performanceClient,
|
|
15756
|
+
const pkceCodes = await invokeAsync(generatePkceCodes, PerformanceEvents.GeneratePkceCodes, this.logger, this.performanceClient, correlationId)(this.performanceClient, this.logger, correlationId);
|
|
15710
15757
|
const silentRequest = {
|
|
15711
15758
|
...request,
|
|
15712
15759
|
codeChallenge: pkceCodes.challenge,
|
|
15713
15760
|
};
|
|
15714
15761
|
// Create authorize request url
|
|
15715
|
-
const navigateUrl = await invokeAsync(getAuthCodeRequestUrl, PerformanceEvents.GetAuthCodeUrl, this.logger, this.performanceClient, correlationId)(this.config, authClient.authority,
|
|
15716
|
-
...silentRequest,
|
|
15717
|
-
platformBroker: NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeMessageHandler, silentRequest.authenticationScheme),
|
|
15718
|
-
}, this.logger, this.performanceClient);
|
|
15762
|
+
const navigateUrl = await invokeAsync(getAuthCodeRequestUrl, PerformanceEvents.GetAuthCodeUrl, this.logger, this.performanceClient, correlationId)(this.config, authClient.authority, silentRequest, this.logger, this.performanceClient);
|
|
15719
15763
|
// Get the frame handle for the silent request
|
|
15720
|
-
const msalFrame = await invokeAsync(
|
|
15764
|
+
const msalFrame = await invokeAsync(initiateCodeRequest, PerformanceEvents.SilentHandlerInitiateAuthRequest, this.logger, this.performanceClient, correlationId)(navigateUrl, this.performanceClient, this.logger, correlationId, this.config.system.navigateFrameWait);
|
|
15721
15765
|
const responseType = this.config.auth.OIDCOptions.serverResponseType;
|
|
15722
15766
|
// Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
|
|
15723
15767
|
const responseString = await invokeAsync(monitorIframeForHash, PerformanceEvents.SilentHandlerMonitorIframeForHash, this.logger, this.performanceClient, correlationId)(msalFrame, this.config.system.iframeHashTimeout, this.config.system.pollIntervalMilliseconds, this.performanceClient, this.logger, correlationId, responseType);
|
|
15724
|
-
const serverParams = invoke(deserializeResponse, PerformanceEvents.DeserializeResponse, this.logger, this.performanceClient,
|
|
15725
|
-
|
|
15726
|
-
this.logger.verbose("Account id found in hash, calling WAM for token");
|
|
15727
|
-
if (!this.nativeMessageHandler) {
|
|
15728
|
-
throw createBrowserAuthError(nativeConnectionNotEstablished);
|
|
15729
|
-
}
|
|
15730
|
-
const nativeInteractionClient = new NativeInteractionClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, this.apiId, this.performanceClient, this.nativeMessageHandler, serverParams.accountId, this.browserStorage, correlationId);
|
|
15731
|
-
const { userRequestState } = ProtocolUtils.parseRequestState(this.browserCrypto, silentRequest.state);
|
|
15732
|
-
return invokeAsync(nativeInteractionClient.acquireToken.bind(nativeInteractionClient), PerformanceEvents.NativeInteractionClientAcquireToken, this.logger, this.performanceClient, correlationId)({
|
|
15733
|
-
...silentRequest,
|
|
15734
|
-
state: userRequestState,
|
|
15735
|
-
prompt: silentRequest.prompt || PromptValue.NONE,
|
|
15736
|
-
});
|
|
15737
|
-
}
|
|
15738
|
-
const authCodeRequest = {
|
|
15739
|
-
...silentRequest,
|
|
15740
|
-
code: serverParams.code || "",
|
|
15741
|
-
codeVerifier: pkceCodes.verifier,
|
|
15742
|
-
};
|
|
15743
|
-
// Create silent handler
|
|
15744
|
-
const interactionHandler = new InteractionHandler(authClient, this.browserStorage, authCodeRequest, this.logger, this.performanceClient);
|
|
15745
|
-
// Handle response from hash string
|
|
15746
|
-
return invokeAsync(interactionHandler.handleCodeResponse.bind(interactionHandler), PerformanceEvents.HandleCodeResponse, this.logger, this.performanceClient, correlationId)(serverParams, silentRequest);
|
|
15768
|
+
const serverParams = invoke(deserializeResponse, PerformanceEvents.DeserializeResponse, this.logger, this.performanceClient, correlationId)(responseString, responseType, this.logger);
|
|
15769
|
+
return invokeAsync(handleResponseCode, PerformanceEvents.HandleResponseCode, this.logger, this.performanceClient, correlationId)(request, serverParams, pkceCodes.verifier, this.apiId, this.config, authClient, this.browserStorage, this.nativeStorage, this.eventHandler, this.logger, this.performanceClient, this.nativeMessageHandler);
|
|
15747
15770
|
}
|
|
15748
15771
|
}
|
|
15749
15772
|
|
|
@@ -16272,31 +16295,38 @@
|
|
|
16272
16295
|
* @returns
|
|
16273
16296
|
*/
|
|
16274
16297
|
async handleRedirectPromiseInternal(hash) {
|
|
16298
|
+
if (!this.browserStorage.isInteractionInProgress(true)) {
|
|
16299
|
+
this.logger.info("handleRedirectPromise called but there is no interaction in progress, returning null.");
|
|
16300
|
+
return null;
|
|
16301
|
+
}
|
|
16275
16302
|
const loggedInAccounts = this.getAllAccounts();
|
|
16276
|
-
const
|
|
16277
|
-
const useNative =
|
|
16303
|
+
const platformBrokerRequest = this.browserStorage.getCachedNativeRequest();
|
|
16304
|
+
const useNative = platformBrokerRequest &&
|
|
16278
16305
|
NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeExtensionProvider) &&
|
|
16279
16306
|
this.nativeExtensionProvider &&
|
|
16280
16307
|
!hash;
|
|
16281
|
-
|
|
16282
|
-
? request?.correlationId
|
|
16283
|
-
: this.browserStorage.getTemporaryCache(TemporaryCacheKeys.CORRELATION_ID, true) || "";
|
|
16284
|
-
const rootMeasurement = this.performanceClient.startMeasurement(PerformanceEvents.AcquireTokenRedirect, correlationId);
|
|
16308
|
+
let rootMeasurement = this.performanceClient.startMeasurement(PerformanceEvents.AcquireTokenRedirect, platformBrokerRequest?.correlationId || "");
|
|
16285
16309
|
this.eventHandler.emitEvent(EventType.HANDLE_REDIRECT_START, exports.InteractionType.Redirect);
|
|
16286
16310
|
let redirectResponse;
|
|
16287
16311
|
if (useNative && this.nativeExtensionProvider) {
|
|
16288
16312
|
this.logger.trace("handleRedirectPromise - acquiring token from native platform");
|
|
16289
|
-
const nativeClient = new NativeInteractionClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, ApiId.handleRedirectPromise, this.performanceClient, this.nativeExtensionProvider,
|
|
16313
|
+
const nativeClient = new NativeInteractionClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, ApiId.handleRedirectPromise, this.performanceClient, this.nativeExtensionProvider, platformBrokerRequest.accountId, this.nativeInternalStorage, platformBrokerRequest.correlationId);
|
|
16290
16314
|
redirectResponse = invokeAsync(nativeClient.handleRedirectPromise.bind(nativeClient), PerformanceEvents.HandleNativeRedirectPromiseMeasurement, this.logger, this.performanceClient, rootMeasurement.event.correlationId)(this.performanceClient, rootMeasurement.event.correlationId);
|
|
16291
16315
|
}
|
|
16292
16316
|
else {
|
|
16317
|
+
const [standardRequest, codeVerifier] = this.browserStorage.getCachedRequest();
|
|
16318
|
+
const correlationId = standardRequest.correlationId;
|
|
16319
|
+
// Reset rootMeasurement now that we have correlationId
|
|
16320
|
+
rootMeasurement.discard();
|
|
16321
|
+
rootMeasurement = this.performanceClient.startMeasurement(PerformanceEvents.AcquireTokenRedirect, correlationId);
|
|
16293
16322
|
this.logger.trace("handleRedirectPromise - acquiring token from web flow");
|
|
16294
16323
|
const redirectClient = this.createRedirectClient(correlationId);
|
|
16295
|
-
redirectResponse = invokeAsync(redirectClient.handleRedirectPromise.bind(redirectClient), PerformanceEvents.HandleRedirectPromiseMeasurement, this.logger, this.performanceClient, rootMeasurement.event.correlationId)(hash, rootMeasurement);
|
|
16324
|
+
redirectResponse = invokeAsync(redirectClient.handleRedirectPromise.bind(redirectClient), PerformanceEvents.HandleRedirectPromiseMeasurement, this.logger, this.performanceClient, rootMeasurement.event.correlationId)(hash, standardRequest, codeVerifier, rootMeasurement);
|
|
16296
16325
|
}
|
|
16297
16326
|
return redirectResponse
|
|
16298
16327
|
.then((result) => {
|
|
16299
16328
|
if (result) {
|
|
16329
|
+
this.browserStorage.resetRequestCache();
|
|
16300
16330
|
// Emit login event if number of accounts change
|
|
16301
16331
|
const isLoggingIn = loggedInAccounts.length < this.getAllAccounts().length;
|
|
16302
16332
|
if (isLoggingIn) {
|
|
@@ -16328,6 +16358,7 @@
|
|
|
16328
16358
|
return result;
|
|
16329
16359
|
})
|
|
16330
16360
|
.catch((e) => {
|
|
16361
|
+
this.browserStorage.resetRequestCache();
|
|
16331
16362
|
const eventError = e;
|
|
16332
16363
|
// Emit login event if there is an account
|
|
16333
16364
|
if (loggedInAccounts.length > 0) {
|
|
@@ -16421,7 +16452,6 @@
|
|
|
16421
16452
|
const redirectClient = this.createRedirectClient(correlationId);
|
|
16422
16453
|
return redirectClient.acquireToken(request);
|
|
16423
16454
|
}
|
|
16424
|
-
this.browserStorage.setInteractionInProgress(false);
|
|
16425
16455
|
throw e;
|
|
16426
16456
|
});
|
|
16427
16457
|
}
|
|
@@ -16432,6 +16462,7 @@
|
|
|
16432
16462
|
return await result;
|
|
16433
16463
|
}
|
|
16434
16464
|
catch (e) {
|
|
16465
|
+
this.browserStorage.resetRequestCache();
|
|
16435
16466
|
atrMeasurement.end({ success: false }, e);
|
|
16436
16467
|
if (isLoggedIn) {
|
|
16437
16468
|
this.eventHandler.emitEvent(EventType.ACQUIRE_TOKEN_FAILURE, exports.InteractionType.Redirect, null, e);
|
|
@@ -16483,7 +16514,6 @@
|
|
|
16483
16514
|
correlationId,
|
|
16484
16515
|
}, ApiId.acquireTokenPopup)
|
|
16485
16516
|
.then((response) => {
|
|
16486
|
-
this.browserStorage.setInteractionInProgress(false);
|
|
16487
16517
|
atPopupMeasurement.end({
|
|
16488
16518
|
success: true,
|
|
16489
16519
|
isNativeBroker: true,
|
|
@@ -16503,7 +16533,6 @@
|
|
|
16503
16533
|
const popupClient = this.createPopupClient(correlationId);
|
|
16504
16534
|
return popupClient.acquireToken(request, pkce);
|
|
16505
16535
|
}
|
|
16506
|
-
this.browserStorage.setInteractionInProgress(false);
|
|
16507
16536
|
throw e;
|
|
16508
16537
|
});
|
|
16509
16538
|
}
|
|
@@ -16544,8 +16573,12 @@
|
|
|
16544
16573
|
// Since this function is syncronous we need to reject
|
|
16545
16574
|
return Promise.reject(e);
|
|
16546
16575
|
})
|
|
16547
|
-
.finally(() =>
|
|
16548
|
-
this.
|
|
16576
|
+
.finally(async () => {
|
|
16577
|
+
this.browserStorage.setInteractionInProgress(false);
|
|
16578
|
+
if (this.config.system.asyncPopups) {
|
|
16579
|
+
await this.preGeneratePkceCodes(correlationId);
|
|
16580
|
+
}
|
|
16581
|
+
});
|
|
16549
16582
|
}
|
|
16550
16583
|
trackPageVisibilityWithMeasurement() {
|
|
16551
16584
|
const measurement = this.ssoSilentMeasurement ||
|
|
@@ -16848,7 +16881,9 @@
|
|
|
16848
16881
|
preflightCheck$1(this.initialized);
|
|
16849
16882
|
this.browserStorage.setInteractionInProgress(true);
|
|
16850
16883
|
const popupClient = this.createPopupClient(correlationId);
|
|
16851
|
-
return popupClient.logout(logoutRequest)
|
|
16884
|
+
return popupClient.logout(logoutRequest).finally(() => {
|
|
16885
|
+
this.browserStorage.setInteractionInProgress(false);
|
|
16886
|
+
});
|
|
16852
16887
|
}
|
|
16853
16888
|
catch (e) {
|
|
16854
16889
|
// Since this function is syncronous we need to reject
|
|
@@ -17264,9 +17299,7 @@
|
|
|
17264
17299
|
async acquireTokenSilentDeduped(request, account, correlationId) {
|
|
17265
17300
|
const thumbprint = getRequestThumbprint(this.config.auth.clientId, {
|
|
17266
17301
|
...request,
|
|
17267
|
-
authority: request.authority || this.config.auth.authority,
|
|
17268
|
-
correlationId: correlationId,
|
|
17269
|
-
}, account.homeAccountId);
|
|
17302
|
+
authority: request.authority || this.config.auth.authority}, account.homeAccountId);
|
|
17270
17303
|
const silentRequestKey = JSON.stringify(thumbprint);
|
|
17271
17304
|
const inProgressRequest = this.activeSilentTokenRequests.get(silentRequestKey);
|
|
17272
17305
|
if (typeof inProgressRequest === "undefined") {
|