@azure/msal-browser 3.19.1 → 3.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/dist/app/IPublicClientApplication.d.ts +53 -53
  2. package/dist/app/IPublicClientApplication.mjs +105 -105
  3. package/dist/app/PublicClientApplication.d.ts +293 -293
  4. package/dist/app/PublicClientApplication.mjs +364 -364
  5. package/dist/app/PublicClientNext.d.ts +276 -276
  6. package/dist/app/PublicClientNext.mjs +354 -354
  7. package/dist/broker/nativeBroker/NativeMessageHandler.d.ts +62 -62
  8. package/dist/broker/nativeBroker/NativeMessageHandler.mjs +254 -254
  9. package/dist/broker/nativeBroker/NativeRequest.d.ts +45 -45
  10. package/dist/broker/nativeBroker/NativeResponse.d.ts +48 -48
  11. package/dist/broker/nativeBroker/NativeStatusCodes.d.ts +7 -7
  12. package/dist/broker/nativeBroker/NativeStatusCodes.mjs +11 -11
  13. package/dist/cache/AccountManager.d.ts +48 -48
  14. package/dist/cache/AccountManager.mjs +126 -126
  15. package/dist/cache/AsyncMemoryStorage.d.ts +50 -50
  16. package/dist/cache/AsyncMemoryStorage.mjs +131 -131
  17. package/dist/cache/BrowserCacheManager.d.ts +410 -385
  18. package/dist/cache/BrowserCacheManager.d.ts.map +1 -1
  19. package/dist/cache/BrowserCacheManager.mjs +1364 -1294
  20. package/dist/cache/BrowserCacheManager.mjs.map +1 -1
  21. package/dist/cache/BrowserStorage.d.ts +11 -11
  22. package/dist/cache/BrowserStorage.mjs +32 -32
  23. package/dist/cache/DatabaseStorage.d.ts +56 -56
  24. package/dist/cache/DatabaseStorage.mjs +200 -200
  25. package/dist/cache/IAsyncStorage.d.ts +27 -27
  26. package/dist/cache/ITokenCache.d.ts +11 -11
  27. package/dist/cache/IWindowStorage.d.ts +27 -27
  28. package/dist/cache/MemoryStorage.d.ts +11 -11
  29. package/dist/cache/MemoryStorage.mjs +31 -31
  30. package/dist/cache/TokenCache.d.ts +77 -77
  31. package/dist/cache/TokenCache.mjs +195 -195
  32. package/dist/config/Configuration.d.ts +213 -208
  33. package/dist/config/Configuration.d.ts.map +1 -1
  34. package/dist/config/Configuration.mjs +128 -128
  35. package/dist/config/Configuration.mjs.map +1 -1
  36. package/dist/controllers/ControllerFactory.d.ts +5 -5
  37. package/dist/controllers/ControllerFactory.mjs +25 -25
  38. package/dist/controllers/IController.d.ts +60 -60
  39. package/dist/controllers/NestedAppAuthController.d.ts +202 -202
  40. package/dist/controllers/NestedAppAuthController.mjs +473 -473
  41. package/dist/controllers/StandardController.d.ts +405 -405
  42. package/dist/controllers/StandardController.d.ts.map +1 -1
  43. package/dist/controllers/StandardController.mjs +1334 -1316
  44. package/dist/controllers/StandardController.mjs.map +1 -1
  45. package/dist/controllers/UnknownOperatingContextController.d.ts +86 -86
  46. package/dist/controllers/UnknownOperatingContextController.mjs +256 -256
  47. package/dist/crypto/BrowserCrypto.d.ts +52 -52
  48. package/dist/crypto/BrowserCrypto.mjs +151 -151
  49. package/dist/crypto/CryptoOps.d.ts +74 -74
  50. package/dist/crypto/CryptoOps.mjs +176 -176
  51. package/dist/crypto/PkceGenerator.d.ts +8 -8
  52. package/dist/crypto/PkceGenerator.mjs +54 -54
  53. package/dist/crypto/SignedHttpRequest.d.ts +30 -30
  54. package/dist/crypto/SignedHttpRequest.mjs +39 -39
  55. package/dist/encode/Base64Decode.d.ts +9 -9
  56. package/dist/encode/Base64Decode.mjs +36 -36
  57. package/dist/encode/Base64Encode.d.ts +19 -19
  58. package/dist/encode/Base64Encode.mjs +43 -43
  59. package/dist/error/BrowserAuthError.d.ts +256 -255
  60. package/dist/error/BrowserAuthError.d.ts.map +1 -1
  61. package/dist/error/BrowserAuthError.mjs +265 -264
  62. package/dist/error/BrowserAuthError.mjs.map +1 -1
  63. package/dist/error/BrowserAuthErrorCodes.d.ts +47 -46
  64. package/dist/error/BrowserAuthErrorCodes.d.ts.map +1 -1
  65. package/dist/error/BrowserAuthErrorCodes.mjs +53 -52
  66. package/dist/error/BrowserAuthErrorCodes.mjs.map +1 -1
  67. package/dist/error/BrowserConfigurationAuthError.d.ts +33 -33
  68. package/dist/error/BrowserConfigurationAuthError.mjs +40 -40
  69. package/dist/error/BrowserConfigurationAuthError.mjs.map +1 -1
  70. package/dist/error/BrowserConfigurationAuthErrorCodes.d.ts +3 -3
  71. package/dist/error/BrowserConfigurationAuthErrorCodes.mjs +7 -7
  72. package/dist/error/NativeAuthError.d.ts +29 -29
  73. package/dist/error/NativeAuthError.mjs +60 -60
  74. package/dist/error/NativeAuthErrorCodes.d.ts +2 -2
  75. package/dist/error/NativeAuthErrorCodes.mjs +6 -6
  76. package/dist/error/NestedAppAuthError.d.ts +14 -14
  77. package/dist/error/NestedAppAuthError.mjs +23 -23
  78. package/dist/event/EventHandler.d.ts +41 -41
  79. package/dist/event/EventHandler.mjs +125 -125
  80. package/dist/event/EventMessage.d.ts +25 -25
  81. package/dist/event/EventMessage.mjs +68 -68
  82. package/dist/event/EventType.d.ts +29 -29
  83. package/dist/event/EventType.mjs +32 -32
  84. package/dist/index.d.ts +40 -40
  85. package/dist/index.mjs +1 -1
  86. package/dist/interaction_client/BaseInteractionClient.d.ts +50 -50
  87. package/dist/interaction_client/BaseInteractionClient.mjs +106 -106
  88. package/dist/interaction_client/HybridSpaAuthorizationCodeClient.d.ts +4 -4
  89. package/dist/interaction_client/HybridSpaAuthorizationCodeClient.mjs +10 -10
  90. package/dist/interaction_client/NativeInteractionClient.d.ts +151 -143
  91. package/dist/interaction_client/NativeInteractionClient.d.ts.map +1 -1
  92. package/dist/interaction_client/NativeInteractionClient.mjs +624 -584
  93. package/dist/interaction_client/NativeInteractionClient.mjs.map +1 -1
  94. package/dist/interaction_client/PopupClient.d.ts +118 -105
  95. package/dist/interaction_client/PopupClient.d.ts.map +1 -1
  96. package/dist/interaction_client/PopupClient.mjs +460 -434
  97. package/dist/interaction_client/PopupClient.mjs.map +1 -1
  98. package/dist/interaction_client/RedirectClient.d.ts +50 -50
  99. package/dist/interaction_client/RedirectClient.d.ts.map +1 -1
  100. package/dist/interaction_client/RedirectClient.mjs +349 -317
  101. package/dist/interaction_client/RedirectClient.mjs.map +1 -1
  102. package/dist/interaction_client/SilentAuthCodeClient.d.ts +23 -23
  103. package/dist/interaction_client/SilentAuthCodeClient.mjs +57 -57
  104. package/dist/interaction_client/SilentCacheClient.d.ts +16 -16
  105. package/dist/interaction_client/SilentCacheClient.mjs +42 -42
  106. package/dist/interaction_client/SilentIframeClient.d.ts +32 -32
  107. package/dist/interaction_client/SilentIframeClient.d.ts.map +1 -1
  108. package/dist/interaction_client/SilentIframeClient.mjs +111 -101
  109. package/dist/interaction_client/SilentIframeClient.mjs.map +1 -1
  110. package/dist/interaction_client/SilentRefreshClient.d.ts +20 -20
  111. package/dist/interaction_client/SilentRefreshClient.mjs +47 -47
  112. package/dist/interaction_client/StandardInteractionClient.d.ts +48 -48
  113. package/dist/interaction_client/StandardInteractionClient.mjs +199 -199
  114. package/dist/interaction_handler/InteractionHandler.d.ts +33 -33
  115. package/dist/interaction_handler/InteractionHandler.mjs +93 -93
  116. package/dist/interaction_handler/RedirectHandler.d.ts +32 -32
  117. package/dist/interaction_handler/RedirectHandler.d.ts.map +1 -1
  118. package/dist/interaction_handler/RedirectHandler.mjs +135 -134
  119. package/dist/interaction_handler/RedirectHandler.mjs.map +1 -1
  120. package/dist/interaction_handler/SilentHandler.d.ts +13 -13
  121. package/dist/interaction_handler/SilentHandler.mjs +134 -134
  122. package/dist/naa/AccountInfo.d.ts +11 -11
  123. package/dist/naa/AuthBridge.d.ts +8 -8
  124. package/dist/naa/AuthResult.d.ts +6 -6
  125. package/dist/naa/BridgeAccountContext.d.ts +12 -12
  126. package/dist/naa/BridgeCapabilities.d.ts +3 -3
  127. package/dist/naa/BridgeError.d.ts +9 -9
  128. package/dist/naa/BridgeError.mjs +7 -7
  129. package/dist/naa/BridgeProxy.d.ts +67 -67
  130. package/dist/naa/BridgeProxy.d.ts.map +1 -1
  131. package/dist/naa/BridgeProxy.mjs +153 -148
  132. package/dist/naa/BridgeProxy.mjs.map +1 -1
  133. package/dist/naa/BridgeRequest.d.ts +7 -7
  134. package/dist/naa/BridgeRequestEnvelope.d.ts +12 -12
  135. package/dist/naa/BridgeResponseEnvelope.d.ts +13 -13
  136. package/dist/naa/BridgeStatusCode.d.ts +11 -11
  137. package/dist/naa/BridgeStatusCode.mjs +14 -14
  138. package/dist/naa/IBridgeProxy.d.ts +10 -10
  139. package/dist/naa/InitContext.d.ts +8 -8
  140. package/dist/naa/TokenRequest.d.ts +18 -18
  141. package/dist/naa/TokenResponse.d.ts +13 -13
  142. package/dist/naa/mapping/NestedAppAuthAdapter.d.ts +35 -35
  143. package/dist/naa/mapping/NestedAppAuthAdapter.mjs +179 -179
  144. package/dist/navigation/INavigationClient.d.ts +16 -16
  145. package/dist/navigation/NavigationClient.d.ts +22 -22
  146. package/dist/navigation/NavigationClient.mjs +40 -40
  147. package/dist/navigation/NavigationOptions.d.ts +12 -12
  148. package/dist/network/FetchClient.d.ts +26 -26
  149. package/dist/network/FetchClient.mjs +99 -99
  150. package/dist/operatingcontext/BaseOperatingContext.d.ts +41 -41
  151. package/dist/operatingcontext/BaseOperatingContext.mjs +94 -94
  152. package/dist/operatingcontext/NestedAppOperatingContext.d.ts +34 -34
  153. package/dist/operatingcontext/NestedAppOperatingContext.mjs +71 -71
  154. package/dist/operatingcontext/StandardOperatingContext.d.ts +25 -25
  155. package/dist/operatingcontext/StandardOperatingContext.mjs +43 -43
  156. package/dist/operatingcontext/UnknownOperatingContext.d.ts +25 -25
  157. package/dist/operatingcontext/UnknownOperatingContext.mjs +42 -42
  158. package/dist/packageMetadata.d.ts +2 -2
  159. package/dist/packageMetadata.mjs +4 -4
  160. package/dist/request/AuthorizationCodeRequest.d.ts +8 -8
  161. package/dist/request/AuthorizationUrlRequest.d.ts +8 -8
  162. package/dist/request/ClearCacheRequest.d.ts +10 -10
  163. package/dist/request/EndSessionPopupRequest.d.ts +18 -18
  164. package/dist/request/EndSessionRequest.d.ts +15 -15
  165. package/dist/request/InitializeApplicationRequest.d.ts +8 -8
  166. package/dist/request/PopupRequest.d.ts +34 -34
  167. package/dist/request/PopupWindowAttributes.d.ts +15 -15
  168. package/dist/request/RedirectRequest.d.ts +40 -35
  169. package/dist/request/RedirectRequest.d.ts.map +1 -1
  170. package/dist/request/RequestHelpers.d.ts +13 -13
  171. package/dist/request/RequestHelpers.mjs +53 -53
  172. package/dist/request/SilentRequest.d.ts +33 -33
  173. package/dist/request/SsoSilentRequest.d.ts +29 -29
  174. package/dist/response/AuthenticationResult.d.ts +4 -4
  175. package/dist/response/ResponseHandler.d.ts +7 -7
  176. package/dist/response/ResponseHandler.mjs +36 -36
  177. package/dist/telemetry/BrowserPerformanceClient.d.ts +38 -34
  178. package/dist/telemetry/BrowserPerformanceClient.d.ts.map +1 -1
  179. package/dist/telemetry/BrowserPerformanceClient.mjs +163 -163
  180. package/dist/telemetry/BrowserPerformanceClient.mjs.map +1 -1
  181. package/dist/telemetry/BrowserPerformanceMeasurement.d.ts +21 -21
  182. package/dist/telemetry/BrowserPerformanceMeasurement.mjs +92 -92
  183. package/dist/utils/BrowserConstants.d.ts +182 -180
  184. package/dist/utils/BrowserConstants.d.ts.map +1 -1
  185. package/dist/utils/BrowserConstants.mjs +214 -212
  186. package/dist/utils/BrowserConstants.mjs.map +1 -1
  187. package/dist/utils/BrowserProtocolUtils.d.ts +11 -11
  188. package/dist/utils/BrowserProtocolUtils.mjs +21 -21
  189. package/dist/utils/BrowserUtils.d.ts +75 -75
  190. package/dist/utils/BrowserUtils.mjs +157 -157
  191. package/lib/msal-browser.cjs +19028 -18759
  192. package/lib/msal-browser.cjs.map +1 -1
  193. package/lib/msal-browser.js +19028 -18759
  194. package/lib/msal-browser.js.map +1 -1
  195. package/lib/msal-browser.min.js +65 -65
  196. package/package.json +2 -2
  197. package/src/cache/BrowserCacheManager.ts +95 -0
  198. package/src/config/Configuration.ts +9 -1
  199. package/src/controllers/StandardController.ts +30 -12
  200. package/src/error/BrowserAuthError.ts +2 -0
  201. package/src/error/BrowserAuthErrorCodes.ts +1 -0
  202. package/src/interaction_client/NativeInteractionClient.ts +105 -54
  203. package/src/interaction_client/PopupClient.ts +202 -117
  204. package/src/interaction_client/RedirectClient.ts +62 -2
  205. package/src/interaction_client/SilentIframeClient.ts +41 -3
  206. package/src/interaction_handler/RedirectHandler.ts +1 -0
  207. package/src/naa/BridgeProxy.ts +7 -2
  208. package/src/packageMetadata.ts +1 -1
  209. package/src/request/RedirectRequest.ts +5 -0
  210. package/src/telemetry/BrowserPerformanceClient.ts +1 -1
  211. package/src/utils/BrowserConstants.ts +2 -0
@@ -20,6 +20,7 @@ import {
20
20
  ServerResponseType,
21
21
  invokeAsync,
22
22
  invoke,
23
+ ServerError,
23
24
  } from "@azure/msal-common";
24
25
  import { StandardInteractionClient } from "./StandardInteractionClient";
25
26
  import { EventType } from "../event/EventType";
@@ -47,6 +48,7 @@ import { PopupWindowAttributes } from "../request/PopupWindowAttributes";
47
48
  import { EventError } from "../event/EventMessage";
48
49
  import { AuthenticationResult } from "../response/AuthenticationResult";
49
50
  import * as ResponseHandler from "../response/ResponseHandler";
51
+ import { AuthorizationUrlRequest } from "../request/AuthorizationUrlRequest";
50
52
 
51
53
  export type PopupParams = {
52
54
  popup?: Window | null;
@@ -182,7 +184,7 @@ export class PopupClient extends StandardInteractionClient {
182
184
  }
183
185
 
184
186
  /**
185
- * Helper which obtains an access_token for your API via opening a popup window in the user's browser
187
+ * Helper which initializes authorization clients and requests
186
188
  * @param validRequest
187
189
  * @param popupName
188
190
  * @param popup
@@ -211,19 +213,20 @@ export class PopupClient extends StandardInteractionClient {
211
213
 
212
214
  BrowserUtils.preconnect(validRequest.authority);
213
215
 
216
+ let authClient: AuthorizationCodeClient | undefined;
217
+
214
218
  try {
215
219
  // Create auth code request and generate PKCE params
216
- const authCodeRequest: CommonAuthorizationCodeRequest =
217
- await invokeAsync(
218
- this.initializeAuthorizationCodeRequest.bind(this),
219
- PerformanceEvents.StandardInteractionClientInitializeAuthorizationCodeRequest,
220
- this.logger,
221
- this.performanceClient,
222
- this.correlationId
223
- )(validRequest);
220
+ const authCodeRequest = await invokeAsync(
221
+ this.initializeAuthorizationCodeRequest.bind(this),
222
+ PerformanceEvents.StandardInteractionClientInitializeAuthorizationCodeRequest,
223
+ this.logger,
224
+ this.performanceClient,
225
+ this.correlationId
226
+ )(validRequest);
224
227
 
225
228
  // Initialize the client
226
- const authClient: AuthorizationCodeClient = await invokeAsync(
229
+ authClient = await invokeAsync(
227
230
  this.createAuthCodeClient.bind(this),
228
231
  PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,
229
232
  this.logger,
@@ -236,136 +239,218 @@ export class PopupClient extends StandardInteractionClient {
236
239
  validRequest.account
237
240
  );
238
241
 
239
- const isNativeBroker = NativeMessageHandler.isNativeAvailable(
240
- this.config,
242
+ return await invokeAsync(
243
+ this.acquireTokenPopupAsyncHelper.bind(this),
244
+ PerformanceEvents.PopupClientTokenHelper,
241
245
  this.logger,
242
- this.nativeMessageHandler,
243
- request.authenticationScheme
244
- );
245
- // Start measurement for server calls with native brokering enabled
246
- let fetchNativeAccountIdMeasurement;
247
- if (isNativeBroker) {
248
- fetchNativeAccountIdMeasurement =
249
- this.performanceClient.startMeasurement(
250
- PerformanceEvents.FetchAccountIdWithNativeBroker,
251
- request.correlationId
252
- );
253
- }
254
-
255
- // Create acquire token url.
256
- const navigateUrl = await authClient.getAuthCodeUrl({
257
- ...validRequest,
258
- nativeBroker: isNativeBroker,
259
- });
260
-
261
- // Create popup interaction handler.
262
- const interactionHandler = new InteractionHandler(
246
+ this.performanceClient,
247
+ this.correlationId
248
+ )(
263
249
  authClient,
264
- this.browserStorage,
265
250
  authCodeRequest,
266
- this.logger,
267
- this.performanceClient
268
- );
269
-
270
- // Show the UI once the url has been created. Get the window handle for the popup.
271
- const popupParameters: PopupParams = {
272
- popup,
251
+ validRequest,
252
+ request,
273
253
  popupName,
274
254
  popupWindowAttributes,
275
- };
276
- const popupWindow: Window = this.initiateAuthRequest(
277
- navigateUrl,
278
- popupParameters
255
+ popup
279
256
  );
280
- this.eventHandler.emitEvent(
281
- EventType.POPUP_OPENED,
282
- InteractionType.Popup,
283
- { popupWindow },
284
- null
257
+ } catch (e) {
258
+ if (popup) {
259
+ // Close the synchronous popup if an error is thrown before the window unload event is registered
260
+ popup.close();
261
+ }
262
+
263
+ if (e instanceof AuthError) {
264
+ (e as AuthError).setCorrelationId(this.correlationId);
265
+ serverTelemetryManager.cacheFailedRequest(e);
266
+ }
267
+
268
+ if (
269
+ !authClient ||
270
+ !(e instanceof ServerError) ||
271
+ e.errorCode !== BrowserConstants.INVALID_GRANT_ERROR
272
+ ) {
273
+ throw e;
274
+ }
275
+
276
+ this.performanceClient.addFields(
277
+ {
278
+ retryError: e.errorCode,
279
+ },
280
+ this.correlationId
285
281
  );
286
282
 
287
- // Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
288
- const responseString = await this.monitorPopupForHash(popupWindow);
283
+ const retryAuthCodeRequest = await invokeAsync(
284
+ this.initializeAuthorizationCodeRequest.bind(this),
285
+ PerformanceEvents.StandardInteractionClientInitializeAuthorizationCodeRequest,
286
+ this.logger,
287
+ this.performanceClient,
288
+ this.correlationId
289
+ )(validRequest);
289
290
 
290
- const serverParams = invoke(
291
- ResponseHandler.deserializeResponse,
292
- PerformanceEvents.DeserializeResponse,
291
+ return await invokeAsync(
292
+ this.acquireTokenPopupAsyncHelper.bind(this),
293
+ PerformanceEvents.PopupClientTokenHelper,
293
294
  this.logger,
294
295
  this.performanceClient,
295
296
  this.correlationId
296
297
  )(
297
- responseString,
298
- this.config.auth.OIDCOptions.serverResponseType,
299
- this.logger
300
- );
301
- // Remove throttle if it exists
302
- ThrottlingUtils.removeThrottle(
303
- this.browserStorage,
304
- this.config.auth.clientId,
305
- authCodeRequest
298
+ authClient,
299
+ retryAuthCodeRequest,
300
+ validRequest,
301
+ request,
302
+ popupName,
303
+ popupWindowAttributes,
304
+ popup
306
305
  );
306
+ }
307
+ }
307
308
 
308
- if (serverParams.accountId) {
309
- this.logger.verbose(
310
- "Account id found in hash, calling WAM for token"
311
- );
312
- // end measurement for server call with native brokering enabled
313
- if (fetchNativeAccountIdMeasurement) {
314
- fetchNativeAccountIdMeasurement.end({
315
- success: true,
316
- isNativeBroker: true,
317
- });
318
- }
309
+ /**
310
+ * Helper which obtains an access_token for your API via opening a popup window in the user's browser
311
+ * @param authClient
312
+ * @param authCodeRequest
313
+ * @param validRequest
314
+ * @param request
315
+ * @param popupName
316
+ * @param popupWindowAttributes
317
+ * @param popup
318
+ * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.
319
+ */
320
+ protected async acquireTokenPopupAsyncHelper(
321
+ authClient: AuthorizationCodeClient,
322
+ authCodeRequest: CommonAuthorizationCodeRequest,
323
+ validRequest: AuthorizationUrlRequest,
324
+ request: PopupRequest,
325
+ popupName: string,
326
+ popupWindowAttributes: PopupWindowAttributes,
327
+ popup?: Window | null
328
+ ): Promise<AuthenticationResult> {
329
+ const correlationId = validRequest.correlationId;
330
+ this.performanceClient.addQueueMeasurement(
331
+ PerformanceEvents.PopupClientTokenHelper,
332
+ correlationId
333
+ );
319
334
 
320
- if (!this.nativeMessageHandler) {
321
- throw createBrowserAuthError(
322
- BrowserAuthErrorCodes.nativeConnectionNotEstablished
323
- );
324
- }
325
- const nativeInteractionClient = new NativeInteractionClient(
326
- this.config,
327
- this.browserStorage,
328
- this.browserCrypto,
329
- this.logger,
330
- this.eventHandler,
331
- this.navigationClient,
332
- ApiId.acquireTokenPopup,
333
- this.performanceClient,
334
- this.nativeMessageHandler,
335
- serverParams.accountId,
336
- this.nativeStorage,
337
- validRequest.correlationId
338
- );
339
- const { userRequestState } = ProtocolUtils.parseRequestState(
340
- this.browserCrypto,
341
- validRequest.state
335
+ const isNativeBroker = NativeMessageHandler.isNativeAvailable(
336
+ this.config,
337
+ this.logger,
338
+ this.nativeMessageHandler,
339
+ request.authenticationScheme
340
+ );
341
+
342
+ // Start measurement for server calls with native brokering enabled
343
+ let fetchNativeAccountIdMeasurement;
344
+ if (isNativeBroker) {
345
+ fetchNativeAccountIdMeasurement =
346
+ this.performanceClient.startMeasurement(
347
+ PerformanceEvents.FetchAccountIdWithNativeBroker,
348
+ request.correlationId
342
349
  );
343
- return await nativeInteractionClient.acquireToken({
344
- ...validRequest,
345
- state: userRequestState,
346
- prompt: undefined, // Server should handle the prompt, ideally native broker can do this part silently
347
- });
348
- }
350
+ }
349
351
 
350
- // Handle response from hash string.
351
- const result = await interactionHandler.handleCodeResponse(
352
- serverParams,
353
- validRequest
354
- );
352
+ // Create acquire token url.
353
+ const navigateUrl = await authClient.getAuthCodeUrl({
354
+ ...validRequest,
355
+ nativeBroker: isNativeBroker,
356
+ });
355
357
 
356
- return result;
357
- } catch (e) {
358
- if (popup) {
359
- // Close the synchronous popup if an error is thrown before the window unload event is registered
360
- popup.close();
358
+ // Create popup interaction handler.
359
+ const interactionHandler = new InteractionHandler(
360
+ authClient,
361
+ this.browserStorage,
362
+ authCodeRequest,
363
+ this.logger,
364
+ this.performanceClient
365
+ );
366
+
367
+ // Show the UI once the url has been created. Get the window handle for the popup.
368
+ const popupParameters: PopupParams = {
369
+ popup,
370
+ popupName,
371
+ popupWindowAttributes,
372
+ };
373
+ const popupWindow: Window = this.initiateAuthRequest(
374
+ navigateUrl,
375
+ popupParameters
376
+ );
377
+ this.eventHandler.emitEvent(
378
+ EventType.POPUP_OPENED,
379
+ InteractionType.Popup,
380
+ { popupWindow },
381
+ null
382
+ );
383
+
384
+ // Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
385
+ const responseString = await this.monitorPopupForHash(popupWindow);
386
+
387
+ const serverParams = invoke(
388
+ ResponseHandler.deserializeResponse,
389
+ PerformanceEvents.DeserializeResponse,
390
+ this.logger,
391
+ this.performanceClient,
392
+ this.correlationId
393
+ )(
394
+ responseString,
395
+ this.config.auth.OIDCOptions.serverResponseType,
396
+ this.logger
397
+ );
398
+ // Remove throttle if it exists
399
+ ThrottlingUtils.removeThrottle(
400
+ this.browserStorage,
401
+ this.config.auth.clientId,
402
+ authCodeRequest
403
+ );
404
+
405
+ if (serverParams.accountId) {
406
+ this.logger.verbose(
407
+ "Account id found in hash, calling WAM for token"
408
+ );
409
+ // end measurement for server call with native brokering enabled
410
+ if (fetchNativeAccountIdMeasurement) {
411
+ fetchNativeAccountIdMeasurement.end({
412
+ success: true,
413
+ isNativeBroker: true,
414
+ });
361
415
  }
362
416
 
363
- if (e instanceof AuthError) {
364
- (e as AuthError).setCorrelationId(this.correlationId);
365
- serverTelemetryManager.cacheFailedRequest(e);
417
+ if (!this.nativeMessageHandler) {
418
+ throw createBrowserAuthError(
419
+ BrowserAuthErrorCodes.nativeConnectionNotEstablished
420
+ );
366
421
  }
367
- throw e;
422
+ const nativeInteractionClient = new NativeInteractionClient(
423
+ this.config,
424
+ this.browserStorage,
425
+ this.browserCrypto,
426
+ this.logger,
427
+ this.eventHandler,
428
+ this.navigationClient,
429
+ ApiId.acquireTokenPopup,
430
+ this.performanceClient,
431
+ this.nativeMessageHandler,
432
+ serverParams.accountId,
433
+ this.nativeStorage,
434
+ validRequest.correlationId
435
+ );
436
+ const { userRequestState } = ProtocolUtils.parseRequestState(
437
+ this.browserCrypto,
438
+ validRequest.state
439
+ );
440
+ return nativeInteractionClient.acquireToken({
441
+ ...validRequest,
442
+ state: userRequestState,
443
+ prompt: undefined, // Server should handle the prompt, ideally native broker can do this part silently
444
+ });
368
445
  }
446
+
447
+ // Handle response from hash string.
448
+ const result = await interactionHandler.handleCodeResponse(
449
+ serverParams,
450
+ validRequest
451
+ );
452
+
453
+ return result;
369
454
  }
370
455
 
371
456
  /**
@@ -22,10 +22,12 @@ import {
22
22
  ServerResponseType,
23
23
  UrlUtils,
24
24
  InProgressPerformanceEvent,
25
+ ServerError,
25
26
  } from "@azure/msal-common";
26
27
  import { StandardInteractionClient } from "./StandardInteractionClient";
27
28
  import {
28
29
  ApiId,
30
+ BrowserConstants,
29
31
  InteractionType,
30
32
  TemporaryCacheKeys,
31
33
  } from "../utils/BrowserConstants";
@@ -83,6 +85,14 @@ export class RedirectClient extends StandardInteractionClient {
83
85
  * @param request
84
86
  */
85
87
  async acquireToken(request: RedirectRequest): Promise<void> {
88
+ if (request.onRedirectNavigate) {
89
+ this.logger.warning(
90
+ "Unable to cache redirect request, onRedirectNavigate request option has been deprecated. Please set onRedirectNavigate on PublicClientApplication config instead."
91
+ );
92
+ } else {
93
+ this.browserStorage.cacheRedirectRequest(request);
94
+ }
95
+
86
96
  const validRequest = await invokeAsync(
87
97
  this.initializeAuthorizationRequest.bind(this),
88
98
  PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest,
@@ -174,7 +184,9 @@ export class RedirectClient extends StandardInteractionClient {
174
184
  navigationClient: this.navigationClient,
175
185
  redirectTimeout: this.config.system.redirectNavigationTimeout,
176
186
  redirectStartPage: redirectStartPage,
177
- onRedirectNavigate: request.onRedirectNavigate,
187
+ onRedirectNavigate:
188
+ request.onRedirectNavigate ||
189
+ this.config.auth.onRedirectNavigate,
178
190
  });
179
191
  } catch (e) {
180
192
  if (e instanceof AuthError) {
@@ -201,6 +213,7 @@ export class RedirectClient extends StandardInteractionClient {
201
213
  const serverTelemetryManager = this.initializeServerTelemetryManager(
202
214
  ApiId.handleRedirectPromise
203
215
  );
216
+
204
217
  try {
205
218
  if (!this.browserStorage.isInteractionInProgress(true)) {
206
219
  this.logger.info(
@@ -331,10 +344,57 @@ export class RedirectClient extends StandardInteractionClient {
331
344
  (e as AuthError).setCorrelationId(this.correlationId);
332
345
  serverTelemetryManager.cacheFailedRequest(e);
333
346
  }
347
+
348
+ if (
349
+ e instanceof ServerError &&
350
+ e.errorCode === BrowserConstants.INVALID_GRANT_ERROR
351
+ ) {
352
+ this.performanceClient.addFields(
353
+ {
354
+ retryError: e.errorCode,
355
+ },
356
+ this.correlationId
357
+ );
358
+
359
+ const requestRetried = this.browserStorage.getRequestRetried();
360
+
361
+ if (requestRetried) {
362
+ this.logger.error(
363
+ "Retried request already detected. Throwing error."
364
+ );
365
+ this.browserStorage.removeRequestRetried();
366
+ throw e;
367
+ }
368
+
369
+ const redirectRequest =
370
+ this.browserStorage.getCachedRedirectRequest();
371
+ if (!redirectRequest) {
372
+ this.logger.error(
373
+ "Unable to retry. Please retry with redirect request"
374
+ );
375
+ this.browserStorage.setRequestRetried();
376
+ throw createBrowserAuthError(
377
+ BrowserAuthErrorCodes.failedToRetry
378
+ );
379
+ }
380
+
381
+ this.browserStorage.setRequestRetried();
382
+
383
+ await this.acquireToken(redirectRequest);
384
+ return null;
385
+ }
386
+
387
+ this.browserStorage.removeTemporaryItem(
388
+ this.browserStorage.generateCacheKey(
389
+ TemporaryCacheKeys.REDIRECT_REQUEST
390
+ )
391
+ );
392
+ this.browserStorage.removeRequestRetried();
393
+ throw e;
394
+ } finally {
334
395
  this.browserStorage.cleanRequestByInteractionType(
335
396
  InteractionType.Redirect
336
397
  );
337
- throw e;
338
398
  }
339
399
  }
340
400
 
@@ -15,6 +15,7 @@ import {
15
15
  PerformanceEvents,
16
16
  invokeAsync,
17
17
  invoke,
18
+ ServerError,
18
19
  } from "@azure/msal-common";
19
20
  import { StandardInteractionClient } from "./StandardInteractionClient";
20
21
  import { AuthorizationUrlRequest } from "../request/AuthorizationUrlRequest";
@@ -26,7 +27,11 @@ import {
26
27
  createBrowserAuthError,
27
28
  BrowserAuthErrorCodes,
28
29
  } from "../error/BrowserAuthError";
29
- import { InteractionType, ApiId } from "../utils/BrowserConstants";
30
+ import {
31
+ InteractionType,
32
+ ApiId,
33
+ BrowserConstants,
34
+ } from "../utils/BrowserConstants";
30
35
  import {
31
36
  initiateAuthRequest,
32
37
  monitorIframeForHash,
@@ -123,9 +128,11 @@ export class SilentIframeClient extends StandardInteractionClient {
123
128
  this.apiId
124
129
  );
125
130
 
131
+ let authClient: AuthorizationCodeClient | undefined;
132
+
126
133
  try {
127
134
  // Initialize the client
128
- const authClient: AuthorizationCodeClient = await invokeAsync(
135
+ authClient = await invokeAsync(
129
136
  this.createAuthCodeClient.bind(this),
130
137
  PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,
131
138
  this.logger,
@@ -150,7 +157,38 @@ export class SilentIframeClient extends StandardInteractionClient {
150
157
  (e as AuthError).setCorrelationId(this.correlationId);
151
158
  serverTelemetryManager.cacheFailedRequest(e);
152
159
  }
153
- throw e;
160
+
161
+ if (
162
+ !authClient ||
163
+ !(e instanceof ServerError) ||
164
+ e.errorCode !== BrowserConstants.INVALID_GRANT_ERROR
165
+ ) {
166
+ throw e;
167
+ }
168
+
169
+ this.performanceClient.addFields(
170
+ {
171
+ retryError: e.errorCode,
172
+ },
173
+ this.correlationId
174
+ );
175
+
176
+ const retrySilentRequest: AuthorizationUrlRequest =
177
+ await invokeAsync(
178
+ this.initializeAuthorizationRequest.bind(this),
179
+ PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest,
180
+ this.logger,
181
+ this.performanceClient,
182
+ request.correlationId
183
+ )(inputRequest, InteractionType.Silent);
184
+
185
+ return await invokeAsync(
186
+ this.silentTokenHelper.bind(this),
187
+ PerformanceEvents.SilentIframeClientTokenHelper,
188
+ this.logger,
189
+ this.performanceClient,
190
+ this.correlationId
191
+ )(authClient, retrySilentRequest);
154
192
  }
155
193
  }
156
194
 
@@ -222,6 +222,7 @@ export class RedirectHandler {
222
222
  )) as AuthenticationResult;
223
223
 
224
224
  this.browserStorage.cleanRequestByState(state);
225
+ this.browserStorage.removeRequestRetried();
225
226
  return tokenResponse;
226
227
  }
227
228
 
@@ -16,6 +16,7 @@ import { IBridgeProxy } from "./IBridgeProxy";
16
16
  import { InitContext } from "./InitContext";
17
17
  import { TokenRequest } from "./TokenRequest";
18
18
  import * as BrowserCrypto from "../crypto/BrowserCrypto";
19
+ import { supportsBrowserPerformanceNow } from "../telemetry/BrowserPerformanceClient";
19
20
 
20
21
  declare global {
21
22
  interface Window {
@@ -81,7 +82,9 @@ export class BridgeProxy implements IBridgeProxy {
81
82
  messageType: "NestedAppAuthRequest",
82
83
  method: "GetInitContext",
83
84
  requestId: BrowserCrypto.createNewGuid(),
84
- sendTime: Date.now(),
85
+ sendTime: supportsBrowserPerformanceNow()
86
+ ? window.performance.now()
87
+ : Date.now(),
85
88
  };
86
89
  const request: BridgeRequest = {
87
90
  requestId: message.requestId,
@@ -157,7 +160,9 @@ export class BridgeProxy implements IBridgeProxy {
157
160
  messageType: "NestedAppAuthRequest",
158
161
  method: method,
159
162
  requestId: BrowserCrypto.createNewGuid(),
160
- sendTime: Date.now(),
163
+ sendTime: supportsBrowserPerformanceNow()
164
+ ? window.performance.now()
165
+ : Date.now(),
161
166
  ...requestParams,
162
167
  };
163
168
 
@@ -1,3 +1,3 @@
1
1
  /* eslint-disable header/header */
2
2
  export const name = "@azure/msal-browser";
3
- export const version = "3.19.1";
3
+ export const version = "3.21.0";
@@ -46,6 +46,11 @@ export type RedirectRequest = Partial<
46
46
  > & {
47
47
  scopes: Array<string>;
48
48
  redirectStartPage?: string;
49
+ /**
50
+ * @deprecated
51
+ * onRedirectNavigate is deprecated and will be removed in the next major version.
52
+ * Set onRedirectNavigate in Configuration instead.
53
+ */
49
54
  onRedirectNavigate?: (url: string) => boolean | void;
50
55
  tokenBodyParameters?: StringDict;
51
56
  };
@@ -42,7 +42,7 @@ function getPerfMeasurementModule() {
42
42
  /**
43
43
  * Returns boolean, indicating whether browser supports window.performance.now() function.
44
44
  */
45
- function supportsBrowserPerformanceNow(): boolean {
45
+ export function supportsBrowserPerformanceNow(): boolean {
46
46
  return (
47
47
  typeof window !== "undefined" &&
48
48
  typeof window.performance !== "undefined" &&
@@ -93,6 +93,8 @@ export const TemporaryCacheKeys = {
93
93
  CORRELATION_ID: "request.correlationId",
94
94
  NATIVE_REQUEST: "request.native",
95
95
  REDIRECT_CONTEXT: "request.redirect.context",
96
+ REDIRECT_REQUEST: "request.redirect",
97
+ REQUEST_RETRY: "request.retry",
96
98
  } as const;
97
99
  export type TemporaryCacheKeys =
98
100
  (typeof TemporaryCacheKeys)[keyof typeof TemporaryCacheKeys];