@azure/msal-browser 4.11.1 → 4.13.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 (222) hide show
  1. package/dist/app/IPublicClientApplication.mjs +1 -1
  2. package/dist/app/PublicClientApplication.d.ts +1 -0
  3. package/dist/app/PublicClientApplication.d.ts.map +1 -1
  4. package/dist/app/PublicClientApplication.mjs +3 -2
  5. package/dist/app/PublicClientApplication.mjs.map +1 -1
  6. package/dist/app/PublicClientNext.mjs +1 -1
  7. package/dist/broker/nativeBroker/IPlatformAuthHandler.d.ts +12 -0
  8. package/dist/broker/nativeBroker/IPlatformAuthHandler.d.ts.map +1 -0
  9. package/dist/broker/nativeBroker/NativeStatusCodes.mjs +1 -1
  10. package/dist/broker/nativeBroker/PlatformAuthDOMHandler.d.ts +30 -0
  11. package/dist/broker/nativeBroker/PlatformAuthDOMHandler.d.ts.map +1 -0
  12. package/dist/broker/nativeBroker/PlatformAuthDOMHandler.mjs +143 -0
  13. package/dist/broker/nativeBroker/PlatformAuthDOMHandler.mjs.map +1 -0
  14. package/dist/broker/nativeBroker/{NativeMessageHandler.d.ts → PlatformAuthExtensionHandler.d.ts} +16 -16
  15. package/dist/broker/nativeBroker/PlatformAuthExtensionHandler.d.ts.map +1 -0
  16. package/dist/broker/nativeBroker/{NativeMessageHandler.mjs → PlatformAuthExtensionHandler.mjs} +66 -58
  17. package/dist/broker/nativeBroker/PlatformAuthExtensionHandler.mjs.map +1 -0
  18. package/dist/broker/nativeBroker/PlatformAuthProvider.d.ts +26 -0
  19. package/dist/broker/nativeBroker/PlatformAuthProvider.d.ts.map +1 -0
  20. package/dist/broker/nativeBroker/PlatformAuthProvider.mjs +108 -0
  21. package/dist/broker/nativeBroker/PlatformAuthProvider.mjs.map +1 -0
  22. package/dist/broker/nativeBroker/{NativeRequest.d.ts → PlatformAuthRequest.d.ts} +34 -3
  23. package/dist/broker/nativeBroker/PlatformAuthRequest.d.ts.map +1 -0
  24. package/dist/broker/nativeBroker/{NativeResponse.d.ts → PlatformAuthResponse.d.ts} +24 -2
  25. package/dist/broker/nativeBroker/PlatformAuthResponse.d.ts.map +1 -0
  26. package/dist/cache/AccountManager.mjs +1 -1
  27. package/dist/cache/AsyncMemoryStorage.mjs +1 -1
  28. package/dist/cache/BrowserCacheManager.d.ts +6 -2
  29. package/dist/cache/BrowserCacheManager.d.ts.map +1 -1
  30. package/dist/cache/BrowserCacheManager.mjs +29 -3
  31. package/dist/cache/BrowserCacheManager.mjs.map +1 -1
  32. package/dist/cache/CacheHelpers.mjs +1 -1
  33. package/dist/cache/CookieStorage.mjs +1 -1
  34. package/dist/cache/DatabaseStorage.mjs +1 -1
  35. package/dist/cache/LocalStorage.mjs +1 -1
  36. package/dist/cache/MemoryStorage.mjs +1 -1
  37. package/dist/cache/SessionStorage.mjs +1 -1
  38. package/dist/cache/TokenCache.mjs +1 -1
  39. package/dist/config/Configuration.mjs +1 -1
  40. package/dist/controllers/ControllerFactory.mjs +1 -1
  41. package/dist/controllers/IController.d.ts +1 -1
  42. package/dist/controllers/IController.d.ts.map +1 -1
  43. package/dist/controllers/NestedAppAuthController.d.ts +1 -1
  44. package/dist/controllers/NestedAppAuthController.d.ts.map +1 -1
  45. package/dist/controllers/NestedAppAuthController.mjs +4 -2
  46. package/dist/controllers/NestedAppAuthController.mjs.map +1 -1
  47. package/dist/controllers/StandardController.d.ts +4 -3
  48. package/dist/controllers/StandardController.d.ts.map +1 -1
  49. package/dist/controllers/StandardController.mjs +56 -30
  50. package/dist/controllers/StandardController.mjs.map +1 -1
  51. package/dist/controllers/UnknownOperatingContextController.mjs +1 -1
  52. package/dist/crypto/BrowserCrypto.mjs +1 -1
  53. package/dist/crypto/CryptoOps.mjs +1 -1
  54. package/dist/crypto/PkceGenerator.mjs +1 -1
  55. package/dist/crypto/SignedHttpRequest.mjs +1 -1
  56. package/dist/encode/Base64Decode.mjs +1 -1
  57. package/dist/encode/Base64Encode.mjs +1 -1
  58. package/dist/error/BrowserAuthError.mjs +1 -1
  59. package/dist/error/BrowserAuthErrorCodes.mjs +1 -1
  60. package/dist/error/BrowserConfigurationAuthError.mjs +1 -1
  61. package/dist/error/BrowserConfigurationAuthErrorCodes.mjs +1 -1
  62. package/dist/error/NativeAuthError.mjs +1 -1
  63. package/dist/error/NativeAuthErrorCodes.mjs +1 -1
  64. package/dist/error/NestedAppAuthError.mjs +1 -1
  65. package/dist/event/EventHandler.mjs +1 -1
  66. package/dist/event/EventMessage.d.ts +10 -1
  67. package/dist/event/EventMessage.d.ts.map +1 -1
  68. package/dist/event/EventMessage.mjs +1 -1
  69. package/dist/event/EventMessage.mjs.map +1 -1
  70. package/dist/event/EventType.d.ts +1 -0
  71. package/dist/event/EventType.d.ts.map +1 -1
  72. package/dist/event/EventType.mjs +2 -1
  73. package/dist/event/EventType.mjs.map +1 -1
  74. package/dist/index.d.ts +2 -1
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.mjs +2 -1
  77. package/dist/index.mjs.map +1 -1
  78. package/dist/interaction_client/BaseInteractionClient.d.ts +3 -3
  79. package/dist/interaction_client/BaseInteractionClient.d.ts.map +1 -1
  80. package/dist/interaction_client/BaseInteractionClient.mjs +3 -3
  81. package/dist/interaction_client/HybridSpaAuthorizationCodeClient.mjs +1 -1
  82. package/dist/interaction_client/{NativeInteractionClient.d.ts → PlatformAuthInteractionClient.d.ts} +21 -23
  83. package/dist/interaction_client/PlatformAuthInteractionClient.d.ts.map +1 -0
  84. package/dist/interaction_client/{NativeInteractionClient.mjs → PlatformAuthInteractionClient.mjs} +80 -111
  85. package/dist/interaction_client/PlatformAuthInteractionClient.mjs.map +1 -0
  86. package/dist/interaction_client/PopupClient.d.ts +2 -2
  87. package/dist/interaction_client/PopupClient.d.ts.map +1 -1
  88. package/dist/interaction_client/PopupClient.mjs +7 -7
  89. package/dist/interaction_client/PopupClient.mjs.map +1 -1
  90. package/dist/interaction_client/RedirectClient.d.ts +2 -2
  91. package/dist/interaction_client/RedirectClient.d.ts.map +1 -1
  92. package/dist/interaction_client/RedirectClient.mjs +7 -8
  93. package/dist/interaction_client/RedirectClient.mjs.map +1 -1
  94. package/dist/interaction_client/SilentAuthCodeClient.d.ts +2 -2
  95. package/dist/interaction_client/SilentAuthCodeClient.d.ts.map +1 -1
  96. package/dist/interaction_client/SilentAuthCodeClient.mjs +3 -3
  97. package/dist/interaction_client/SilentCacheClient.mjs +1 -1
  98. package/dist/interaction_client/SilentIframeClient.d.ts +2 -2
  99. package/dist/interaction_client/SilentIframeClient.d.ts.map +1 -1
  100. package/dist/interaction_client/SilentIframeClient.mjs +7 -8
  101. package/dist/interaction_client/SilentIframeClient.mjs.map +1 -1
  102. package/dist/interaction_client/SilentRefreshClient.mjs +1 -1
  103. package/dist/interaction_client/StandardInteractionClient.mjs +1 -1
  104. package/dist/interaction_handler/InteractionHandler.mjs +1 -1
  105. package/dist/interaction_handler/SilentHandler.mjs +1 -1
  106. package/dist/naa/BridgeError.mjs +1 -1
  107. package/dist/naa/BridgeProxy.mjs +1 -1
  108. package/dist/naa/BridgeStatusCode.mjs +1 -1
  109. package/dist/naa/mapping/NestedAppAuthAdapter.mjs +1 -1
  110. package/dist/navigation/NavigationClient.mjs +1 -1
  111. package/dist/network/FetchClient.mjs +1 -1
  112. package/dist/operatingcontext/BaseOperatingContext.mjs +1 -1
  113. package/dist/operatingcontext/NestedAppOperatingContext.mjs +1 -1
  114. package/dist/operatingcontext/StandardOperatingContext.mjs +1 -1
  115. package/dist/operatingcontext/UnknownOperatingContext.mjs +1 -1
  116. package/dist/packageMetadata.d.ts +1 -1
  117. package/dist/packageMetadata.mjs +2 -2
  118. package/dist/protocol/Authorize.d.ts +4 -4
  119. package/dist/protocol/Authorize.d.ts.map +1 -1
  120. package/dist/protocol/Authorize.mjs +10 -9
  121. package/dist/protocol/Authorize.mjs.map +1 -1
  122. package/dist/request/RequestHelpers.mjs +1 -1
  123. package/dist/response/ResponseHandler.mjs +1 -1
  124. package/dist/telemetry/BrowserPerformanceClient.mjs +1 -1
  125. package/dist/telemetry/BrowserPerformanceMeasurement.mjs +1 -1
  126. package/dist/utils/BrowserConstants.d.ts +8 -1
  127. package/dist/utils/BrowserConstants.d.ts.map +1 -1
  128. package/dist/utils/BrowserConstants.mjs +11 -4
  129. package/dist/utils/BrowserConstants.mjs.map +1 -1
  130. package/dist/utils/BrowserProtocolUtils.mjs +1 -1
  131. package/dist/utils/BrowserUtils.mjs +1 -1
  132. package/dist/utils/MsalFrameStatsUtils.d.ts +3 -0
  133. package/dist/utils/MsalFrameStatsUtils.d.ts.map +1 -0
  134. package/dist/utils/MsalFrameStatsUtils.mjs +23 -0
  135. package/dist/utils/MsalFrameStatsUtils.mjs.map +1 -0
  136. package/lib/msal-browser.cjs +1600 -1323
  137. package/lib/msal-browser.cjs.map +1 -1
  138. package/lib/msal-browser.js +1600 -1323
  139. package/lib/msal-browser.js.map +1 -1
  140. package/lib/msal-browser.min.js +66 -66
  141. package/lib/types/app/PublicClientApplication.d.ts +1 -0
  142. package/lib/types/app/PublicClientApplication.d.ts.map +1 -1
  143. package/lib/types/broker/nativeBroker/IPlatformAuthHandler.d.ts +12 -0
  144. package/lib/types/broker/nativeBroker/IPlatformAuthHandler.d.ts.map +1 -0
  145. package/lib/types/broker/nativeBroker/PlatformAuthDOMHandler.d.ts +30 -0
  146. package/lib/types/broker/nativeBroker/PlatformAuthDOMHandler.d.ts.map +1 -0
  147. package/lib/types/broker/nativeBroker/{NativeMessageHandler.d.ts → PlatformAuthExtensionHandler.d.ts} +16 -16
  148. package/lib/types/broker/nativeBroker/PlatformAuthExtensionHandler.d.ts.map +1 -0
  149. package/lib/types/broker/nativeBroker/PlatformAuthProvider.d.ts +26 -0
  150. package/lib/types/broker/nativeBroker/PlatformAuthProvider.d.ts.map +1 -0
  151. package/lib/types/broker/nativeBroker/{NativeRequest.d.ts → PlatformAuthRequest.d.ts} +34 -3
  152. package/lib/types/broker/nativeBroker/PlatformAuthRequest.d.ts.map +1 -0
  153. package/lib/types/broker/nativeBroker/{NativeResponse.d.ts → PlatformAuthResponse.d.ts} +24 -2
  154. package/lib/types/broker/nativeBroker/PlatformAuthResponse.d.ts.map +1 -0
  155. package/lib/types/cache/BrowserCacheManager.d.ts +6 -2
  156. package/lib/types/cache/BrowserCacheManager.d.ts.map +1 -1
  157. package/lib/types/controllers/IController.d.ts +1 -1
  158. package/lib/types/controllers/IController.d.ts.map +1 -1
  159. package/lib/types/controllers/NestedAppAuthController.d.ts +1 -1
  160. package/lib/types/controllers/NestedAppAuthController.d.ts.map +1 -1
  161. package/lib/types/controllers/StandardController.d.ts +4 -3
  162. package/lib/types/controllers/StandardController.d.ts.map +1 -1
  163. package/lib/types/event/EventMessage.d.ts +10 -1
  164. package/lib/types/event/EventMessage.d.ts.map +1 -1
  165. package/lib/types/event/EventType.d.ts +1 -0
  166. package/lib/types/event/EventType.d.ts.map +1 -1
  167. package/lib/types/index.d.ts +2 -1
  168. package/lib/types/index.d.ts.map +1 -1
  169. package/lib/types/interaction_client/BaseInteractionClient.d.ts +3 -3
  170. package/lib/types/interaction_client/BaseInteractionClient.d.ts.map +1 -1
  171. package/lib/types/interaction_client/{NativeInteractionClient.d.ts → PlatformAuthInteractionClient.d.ts} +21 -23
  172. package/lib/types/interaction_client/PlatformAuthInteractionClient.d.ts.map +1 -0
  173. package/lib/types/interaction_client/PopupClient.d.ts +2 -2
  174. package/lib/types/interaction_client/PopupClient.d.ts.map +1 -1
  175. package/lib/types/interaction_client/RedirectClient.d.ts +2 -2
  176. package/lib/types/interaction_client/RedirectClient.d.ts.map +1 -1
  177. package/lib/types/interaction_client/SilentAuthCodeClient.d.ts +2 -2
  178. package/lib/types/interaction_client/SilentAuthCodeClient.d.ts.map +1 -1
  179. package/lib/types/interaction_client/SilentIframeClient.d.ts +2 -2
  180. package/lib/types/interaction_client/SilentIframeClient.d.ts.map +1 -1
  181. package/lib/types/packageMetadata.d.ts +1 -1
  182. package/lib/types/protocol/Authorize.d.ts +4 -4
  183. package/lib/types/protocol/Authorize.d.ts.map +1 -1
  184. package/lib/types/utils/BrowserConstants.d.ts +8 -1
  185. package/lib/types/utils/BrowserConstants.d.ts.map +1 -1
  186. package/lib/types/utils/MsalFrameStatsUtils.d.ts +3 -0
  187. package/lib/types/utils/MsalFrameStatsUtils.d.ts.map +1 -0
  188. package/package.json +3 -2
  189. package/src/app/PublicClientApplication.ts +2 -1
  190. package/src/broker/nativeBroker/IPlatformAuthHandler.ts +17 -0
  191. package/src/broker/nativeBroker/PlatformAuthDOMHandler.ts +248 -0
  192. package/src/broker/nativeBroker/{NativeMessageHandler.ts → PlatformAuthExtensionHandler.ts} +90 -79
  193. package/src/broker/nativeBroker/PlatformAuthProvider.ts +164 -0
  194. package/src/broker/nativeBroker/{NativeRequest.ts → PlatformAuthRequest.ts} +41 -2
  195. package/src/broker/nativeBroker/{NativeResponse.ts → PlatformAuthResponse.ts} +25 -1
  196. package/src/cache/BrowserCacheManager.ts +40 -4
  197. package/src/controllers/IController.ts +4 -1
  198. package/src/controllers/NestedAppAuthController.ts +5 -1
  199. package/src/controllers/StandardController.ts +87 -46
  200. package/src/event/EventMessage.ts +11 -0
  201. package/src/event/EventType.ts +1 -0
  202. package/src/index.ts +3 -0
  203. package/src/interaction_client/BaseInteractionClient.ts +4 -4
  204. package/src/interaction_client/{NativeInteractionClient.ts → PlatformAuthInteractionClient.ts} +136 -167
  205. package/src/interaction_client/PopupClient.ts +8 -7
  206. package/src/interaction_client/RedirectClient.ts +12 -12
  207. package/src/interaction_client/SilentAuthCodeClient.ts +3 -3
  208. package/src/interaction_client/SilentIframeClient.ts +12 -12
  209. package/src/packageMetadata.ts +1 -1
  210. package/src/protocol/Authorize.ts +12 -10
  211. package/src/utils/BrowserConstants.ts +9 -1
  212. package/src/utils/MsalFrameStatsUtils.ts +32 -0
  213. package/dist/broker/nativeBroker/NativeMessageHandler.d.ts.map +0 -1
  214. package/dist/broker/nativeBroker/NativeMessageHandler.mjs.map +0 -1
  215. package/dist/broker/nativeBroker/NativeRequest.d.ts.map +0 -1
  216. package/dist/broker/nativeBroker/NativeResponse.d.ts.map +0 -1
  217. package/dist/interaction_client/NativeInteractionClient.d.ts.map +0 -1
  218. package/dist/interaction_client/NativeInteractionClient.mjs.map +0 -1
  219. package/lib/types/broker/nativeBroker/NativeMessageHandler.d.ts.map +0 -1
  220. package/lib/types/broker/nativeBroker/NativeRequest.d.ts.map +0 -1
  221. package/lib/types/broker/nativeBroker/NativeResponse.d.ts.map +0 -1
  222. package/lib/types/interaction_client/NativeInteractionClient.d.ts.map +0 -1
@@ -1,4 +1,4 @@
1
- /*! @azure/msal-browser v4.11.1 2025-04-29 */
1
+ /*! @azure/msal-browser v4.13.0 2025-05-30 */
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.5.2 2025-04-29 */
9
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
10
10
  /*
11
11
  * Copyright (c) Microsoft Corporation. All rights reserved.
12
12
  * Licensed under the MIT License.
@@ -260,13 +260,6 @@
260
260
  INVALID_GRANT_ERROR: "invalid_grant",
261
261
  CLIENT_MISMATCH_ERROR: "client_mismatch",
262
262
  };
263
- /**
264
- * Response codes
265
- */
266
- const ResponseCodes = {
267
- httpSuccess: 200,
268
- httpBadRequest: 400,
269
- };
270
263
  /**
271
264
  * Region Discovery Sources
272
265
  */
@@ -309,7 +302,7 @@
309
302
  // Token renewal offset default in seconds
310
303
  const DEFAULT_TOKEN_RENEWAL_OFFSET_SEC = 300;
311
304
 
312
- /*! @azure/msal-common v15.5.2 2025-04-29 */
305
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
313
306
  /*
314
307
  * Copyright (c) Microsoft Corporation. All rights reserved.
315
308
  * Licensed under the MIT License.
@@ -326,7 +319,7 @@
326
319
  unexpectedError: unexpectedError
327
320
  });
328
321
 
329
- /*! @azure/msal-common v15.5.2 2025-04-29 */
322
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
330
323
 
331
324
  /*
332
325
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -375,7 +368,7 @@
375
368
  : AuthErrorMessages[code]);
376
369
  }
377
370
 
378
- /*! @azure/msal-common v15.5.2 2025-04-29 */
371
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
379
372
  /*
380
373
  * Copyright (c) Microsoft Corporation. All rights reserved.
381
374
  * Licensed under the MIT License.
@@ -473,7 +466,7 @@
473
466
  userTimeoutReached: userTimeoutReached
474
467
  });
475
468
 
476
- /*! @azure/msal-common v15.5.2 2025-04-29 */
469
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
477
470
 
478
471
  /*
479
472
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -725,7 +718,7 @@
725
718
  return new ClientAuthError(errorCode, additionalMessage);
726
719
  }
727
720
 
728
- /*! @azure/msal-common v15.5.2 2025-04-29 */
721
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
729
722
 
730
723
  /*
731
724
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -764,7 +757,7 @@
764
757
  },
765
758
  };
766
759
 
767
- /*! @azure/msal-common v15.5.2 2025-04-29 */
760
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
768
761
 
769
762
  /*
770
763
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -955,12 +948,12 @@
955
948
  }
956
949
  }
957
950
 
958
- /*! @azure/msal-common v15.5.2 2025-04-29 */
951
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
959
952
  /* eslint-disable header/header */
960
953
  const name$1 = "@azure/msal-common";
961
- const version$1 = "15.5.2";
954
+ const version$1 = "15.7.0";
962
955
 
963
- /*! @azure/msal-common v15.5.2 2025-04-29 */
956
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
964
957
  /*
965
958
  * Copyright (c) Microsoft Corporation. All rights reserved.
966
959
  * Licensed under the MIT License.
@@ -980,7 +973,7 @@
980
973
  AzureUsGovernment: "https://login.microsoftonline.us",
981
974
  };
982
975
 
983
- /*! @azure/msal-common v15.5.2 2025-04-29 */
976
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
984
977
 
985
978
  /*
986
979
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -1041,7 +1034,7 @@
1041
1034
  }
1042
1035
  }
1043
1036
 
1044
- /*! @azure/msal-common v15.5.2 2025-04-29 */
1037
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
1045
1038
  /*
1046
1039
  * Copyright (c) Microsoft Corporation. All rights reserved.
1047
1040
  * Licensed under the MIT License.
@@ -1096,7 +1089,7 @@
1096
1089
  return cachedAtSec > nowSeconds();
1097
1090
  }
1098
1091
 
1099
- /*! @azure/msal-common v15.5.2 2025-04-29 */
1092
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
1100
1093
 
1101
1094
  /*
1102
1095
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -1423,7 +1416,7 @@
1423
1416
  return metadata.expiresAt <= nowSeconds();
1424
1417
  }
1425
1418
 
1426
- /*! @azure/msal-common v15.5.2 2025-04-29 */
1419
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
1427
1420
  /*
1428
1421
  * Copyright (c) Microsoft Corporation. All rights reserved.
1429
1422
  * Licensed under the MIT License.
@@ -1477,7 +1470,7 @@
1477
1470
  urlParseError: urlParseError
1478
1471
  });
1479
1472
 
1480
- /*! @azure/msal-common v15.5.2 2025-04-29 */
1473
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
1481
1474
 
1482
1475
  /*
1483
1476
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -1615,7 +1608,7 @@
1615
1608
  return new ClientConfigurationError(errorCode);
1616
1609
  }
1617
1610
 
1618
- /*! @azure/msal-common v15.5.2 2025-04-29 */
1611
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
1619
1612
  /*
1620
1613
  * Copyright (c) Microsoft Corporation. All rights reserved.
1621
1614
  * Licensed under the MIT License.
@@ -1712,7 +1705,7 @@
1712
1705
  }
1713
1706
  }
1714
1707
 
1715
- /*! @azure/msal-common v15.5.2 2025-04-29 */
1708
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
1716
1709
 
1717
1710
  /*
1718
1711
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -1903,7 +1896,7 @@
1903
1896
  }
1904
1897
  }
1905
1898
 
1906
- /*! @azure/msal-common v15.5.2 2025-04-29 */
1899
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
1907
1900
 
1908
1901
  /*
1909
1902
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -1943,7 +1936,7 @@
1943
1936
  };
1944
1937
  }
1945
1938
 
1946
- /*! @azure/msal-common v15.5.2 2025-04-29 */
1939
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
1947
1940
  /*
1948
1941
  * Copyright (c) Microsoft Corporation. All rights reserved.
1949
1942
  * Licensed under the MIT License.
@@ -2022,7 +2015,7 @@
2022
2015
  return updatedAccountInfo;
2023
2016
  }
2024
2017
 
2025
- /*! @azure/msal-common v15.5.2 2025-04-29 */
2018
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
2026
2019
  /*
2027
2020
  * Copyright (c) Microsoft Corporation. All rights reserved.
2028
2021
  * Licensed under the MIT License.
@@ -2037,7 +2030,7 @@
2037
2030
  Ciam: 3,
2038
2031
  };
2039
2032
 
2040
- /*! @azure/msal-common v15.5.2 2025-04-29 */
2033
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
2041
2034
  /*
2042
2035
  * Copyright (c) Microsoft Corporation. All rights reserved.
2043
2036
  * Licensed under the MIT License.
@@ -2059,7 +2052,7 @@
2059
2052
  return null;
2060
2053
  }
2061
2054
 
2062
- /*! @azure/msal-common v15.5.2 2025-04-29 */
2055
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
2063
2056
  /*
2064
2057
  * Copyright (c) Microsoft Corporation. All rights reserved.
2065
2058
  * Licensed under the MIT License.
@@ -2083,7 +2076,7 @@
2083
2076
  EAR: "EAR",
2084
2077
  };
2085
2078
 
2086
- /*! @azure/msal-common v15.5.2 2025-04-29 */
2079
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
2087
2080
 
2088
2081
  /*
2089
2082
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -2326,7 +2319,7 @@
2326
2319
  }
2327
2320
  }
2328
2321
 
2329
- /*! @azure/msal-common v15.5.2 2025-04-29 */
2322
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
2330
2323
 
2331
2324
  /*
2332
2325
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -2391,7 +2384,7 @@
2391
2384
  return queryParameterArray.join("&");
2392
2385
  }
2393
2386
 
2394
- /*! @azure/msal-common v15.5.2 2025-04-29 */
2387
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
2395
2388
 
2396
2389
  /*
2397
2390
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -2555,7 +2548,7 @@
2555
2548
  }
2556
2549
  }
2557
2550
 
2558
- /*! @azure/msal-common v15.5.2 2025-04-29 */
2551
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
2559
2552
 
2560
2553
  /*
2561
2554
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -2695,7 +2688,7 @@
2695
2688
  return null;
2696
2689
  }
2697
2690
 
2698
- /*! @azure/msal-common v15.5.2 2025-04-29 */
2691
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
2699
2692
  /*
2700
2693
  * Copyright (c) Microsoft Corporation. All rights reserved.
2701
2694
  * Licensed under the MIT License.
@@ -2703,7 +2696,7 @@
2703
2696
  const cacheQuotaExceededErrorCode = "cache_quota_exceeded";
2704
2697
  const cacheUnknownErrorCode = "cache_error_unknown";
2705
2698
 
2706
- /*! @azure/msal-common v15.5.2 2025-04-29 */
2699
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
2707
2700
 
2708
2701
  /*
2709
2702
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -2730,7 +2723,7 @@
2730
2723
  }
2731
2724
  }
2732
2725
 
2733
- /*! @azure/msal-common v15.5.2 2025-04-29 */
2726
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
2734
2727
 
2735
2728
  /*
2736
2729
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -3915,7 +3908,7 @@
3915
3908
  }
3916
3909
  }
3917
3910
 
3918
- /*! @azure/msal-common v15.5.2 2025-04-29 */
3911
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
3919
3912
 
3920
3913
  /*
3921
3914
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -4015,7 +4008,7 @@
4015
4008
  return (config.authOptions.authority.options.protocolMode === ProtocolMode.OIDC);
4016
4009
  }
4017
4010
 
4018
- /*! @azure/msal-common v15.5.2 2025-04-29 */
4011
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
4019
4012
  /*
4020
4013
  * Copyright (c) Microsoft Corporation. All rights reserved.
4021
4014
  * Licensed under the MIT License.
@@ -4025,7 +4018,7 @@
4025
4018
  UPN: "UPN",
4026
4019
  };
4027
4020
 
4028
- /*! @azure/msal-common v15.5.2 2025-04-29 */
4021
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
4029
4022
  /*
4030
4023
  * Copyright (c) Microsoft Corporation. All rights reserved.
4031
4024
  * Licensed under the MIT License.
@@ -4075,7 +4068,7 @@
4075
4068
  const EAR_JWK = "ear_jwk";
4076
4069
  const EAR_JWE_CRYPTO = "ear_jwe_crypto";
4077
4070
 
4078
- /*! @azure/msal-common v15.5.2 2025-04-29 */
4071
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
4079
4072
 
4080
4073
  /*
4081
4074
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -4443,7 +4436,7 @@
4443
4436
  parameters.set(EAR_JWE_CRYPTO, jweCryptoB64Encoded);
4444
4437
  }
4445
4438
 
4446
- /*! @azure/msal-common v15.5.2 2025-04-29 */
4439
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
4447
4440
  /*
4448
4441
  * Copyright (c) Microsoft Corporation. All rights reserved.
4449
4442
  * Licensed under the MIT License.
@@ -4455,7 +4448,7 @@
4455
4448
  response.hasOwnProperty("jwks_uri"));
4456
4449
  }
4457
4450
 
4458
- /*! @azure/msal-common v15.5.2 2025-04-29 */
4451
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
4459
4452
  /*
4460
4453
  * Copyright (c) Microsoft Corporation. All rights reserved.
4461
4454
  * Licensed under the MIT License.
@@ -4465,7 +4458,7 @@
4465
4458
  response.hasOwnProperty("metadata"));
4466
4459
  }
4467
4460
 
4468
- /*! @azure/msal-common v15.5.2 2025-04-29 */
4461
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
4469
4462
  /*
4470
4463
  * Copyright (c) Microsoft Corporation. All rights reserved.
4471
4464
  * Licensed under the MIT License.
@@ -4475,7 +4468,7 @@
4475
4468
  response.hasOwnProperty("error_description"));
4476
4469
  }
4477
4470
 
4478
- /*! @azure/msal-common v15.5.2 2025-04-29 */
4471
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
4479
4472
  /*
4480
4473
  * Copyright (c) Microsoft Corporation. All rights reserved.
4481
4474
  * Licensed under the MIT License.
@@ -4988,7 +4981,7 @@
4988
4981
  "encryptedCacheExpiredCount",
4989
4982
  ]);
4990
4983
 
4991
- /*! @azure/msal-common v15.5.2 2025-04-29 */
4984
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
4992
4985
  /*
4993
4986
  * Copyright (c) Microsoft Corporation. All rights reserved.
4994
4987
  * Licensed under the MIT License.
@@ -5084,7 +5077,7 @@
5084
5077
  };
5085
5078
  };
5086
5079
 
5087
- /*! @azure/msal-common v15.5.2 2025-04-29 */
5080
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
5088
5081
 
5089
5082
  /*
5090
5083
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -5111,15 +5104,13 @@
5111
5104
  const options = RegionDiscovery.IMDS_OPTIONS;
5112
5105
  try {
5113
5106
  const localIMDSVersionResponse = await invokeAsync(this.getRegionFromIMDS.bind(this), PerformanceEvents.RegionDiscoveryGetRegionFromIMDS, this.logger, this.performanceClient, this.correlationId)(Constants.IMDS_VERSION, options);
5114
- if (localIMDSVersionResponse.status ===
5115
- ResponseCodes.httpSuccess) {
5107
+ if (localIMDSVersionResponse.status === HttpStatus.SUCCESS) {
5116
5108
  autodetectedRegionName = localIMDSVersionResponse.body;
5117
5109
  regionDiscoveryMetadata.region_source =
5118
5110
  RegionDiscoverySources.IMDS;
5119
5111
  }
5120
5112
  // If the response using the local IMDS version failed, try to fetch the current version of IMDS and retry.
5121
- if (localIMDSVersionResponse.status ===
5122
- ResponseCodes.httpBadRequest) {
5113
+ if (localIMDSVersionResponse.status === HttpStatus.BAD_REQUEST) {
5123
5114
  const currentIMDSVersion = await invokeAsync(this.getCurrentVersion.bind(this), PerformanceEvents.RegionDiscoveryGetCurrentVersion, this.logger, this.performanceClient, this.correlationId)(options);
5124
5115
  if (!currentIMDSVersion) {
5125
5116
  regionDiscoveryMetadata.region_source =
@@ -5127,8 +5118,7 @@
5127
5118
  return null;
5128
5119
  }
5129
5120
  const currentIMDSVersionResponse = await invokeAsync(this.getRegionFromIMDS.bind(this), PerformanceEvents.RegionDiscoveryGetRegionFromIMDS, this.logger, this.performanceClient, this.correlationId)(currentIMDSVersion, options);
5130
- if (currentIMDSVersionResponse.status ===
5131
- ResponseCodes.httpSuccess) {
5121
+ if (currentIMDSVersionResponse.status === HttpStatus.SUCCESS) {
5132
5122
  autodetectedRegionName =
5133
5123
  currentIMDSVersionResponse.body;
5134
5124
  regionDiscoveryMetadata.region_source =
@@ -5173,7 +5163,7 @@
5173
5163
  try {
5174
5164
  const response = await this.networkInterface.sendGetRequestAsync(`${Constants.IMDS_ENDPOINT}?format=json`, options);
5175
5165
  // When IMDS endpoint is called without the api version query param, bad request response comes back with latest version.
5176
- if (response.status === ResponseCodes.httpBadRequest &&
5166
+ if (response.status === HttpStatus.BAD_REQUEST &&
5177
5167
  response.body &&
5178
5168
  response.body["newest-versions"] &&
5179
5169
  response.body["newest-versions"].length > 0) {
@@ -5193,7 +5183,7 @@
5193
5183
  },
5194
5184
  };
5195
5185
 
5196
- /*! @azure/msal-common v15.5.2 2025-04-29 */
5186
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
5197
5187
 
5198
5188
  /*
5199
5189
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -6032,7 +6022,7 @@
6032
6022
  };
6033
6023
  }
6034
6024
 
6035
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6025
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6036
6026
 
6037
6027
  /*
6038
6028
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -6063,7 +6053,7 @@
6063
6053
  }
6064
6054
  }
6065
6055
 
6066
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6056
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6067
6057
 
6068
6058
  /*
6069
6059
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -6082,7 +6072,7 @@
6082
6072
  }
6083
6073
  }
6084
6074
 
6085
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6075
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6086
6076
  /*
6087
6077
  * Copyright (c) Microsoft Corporation. All rights reserved.
6088
6078
  * Licensed under the MIT License.
@@ -6103,7 +6093,7 @@
6103
6093
  };
6104
6094
  }
6105
6095
 
6106
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6096
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6107
6097
 
6108
6098
  /*
6109
6099
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -6190,7 +6180,7 @@
6190
6180
  }
6191
6181
  }
6192
6182
 
6193
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6183
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6194
6184
 
6195
6185
  /*
6196
6186
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -6221,7 +6211,7 @@
6221
6211
  return new NetworkError(error, httpStatus, responseHeaders);
6222
6212
  }
6223
6213
 
6224
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6214
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6225
6215
 
6226
6216
  /*
6227
6217
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -6369,7 +6359,7 @@
6369
6359
  }
6370
6360
  }
6371
6361
 
6372
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6362
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6373
6363
  /*
6374
6364
  * Copyright (c) Microsoft Corporation. All rights reserved.
6375
6365
  * Licensed under the MIT License.
@@ -6395,7 +6385,7 @@
6395
6385
  refreshTokenExpired: refreshTokenExpired
6396
6386
  });
6397
6387
 
6398
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6388
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6399
6389
 
6400
6390
  /*
6401
6391
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -6483,7 +6473,7 @@
6483
6473
  return new InteractionRequiredAuthError(errorCode, InteractionRequiredAuthErrorMessages[errorCode]);
6484
6474
  }
6485
6475
 
6486
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6476
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6487
6477
 
6488
6478
  /*
6489
6479
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -6555,7 +6545,7 @@
6555
6545
  }
6556
6546
  }
6557
6547
 
6558
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6548
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6559
6549
 
6560
6550
  /*
6561
6551
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -6639,7 +6629,7 @@
6639
6629
  }
6640
6630
  }
6641
6631
 
6642
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6632
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6643
6633
  /*
6644
6634
  * Copyright (c) Microsoft Corporation. All rights reserved.
6645
6635
  * Licensed under the MIT License.
@@ -6666,7 +6656,7 @@
6666
6656
  }
6667
6657
  }
6668
6658
 
6669
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6659
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6670
6660
 
6671
6661
  /*
6672
6662
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -6997,7 +6987,7 @@
6997
6987
  return baseAccount;
6998
6988
  }
6999
6989
 
7000
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6990
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
7001
6991
 
7002
6992
  /*
7003
6993
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -7064,7 +7054,7 @@
7064
7054
  }
7065
7055
  }
7066
7056
 
7067
- /*! @azure/msal-common v15.5.2 2025-04-29 */
7057
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
7068
7058
  /*
7069
7059
  * Copyright (c) Microsoft Corporation. All rights reserved.
7070
7060
  * Licensed under the MIT License.
@@ -7082,7 +7072,7 @@
7082
7072
  }
7083
7073
  }
7084
7074
 
7085
- /*! @azure/msal-common v15.5.2 2025-04-29 */
7075
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
7086
7076
 
7087
7077
  /*
7088
7078
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -7315,7 +7305,7 @@
7315
7305
  }
7316
7306
  }
7317
7307
 
7318
- /*! @azure/msal-common v15.5.2 2025-04-29 */
7308
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
7319
7309
 
7320
7310
  /*
7321
7311
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -7524,7 +7514,7 @@
7524
7514
  }
7525
7515
  }
7526
7516
 
7527
- /*! @azure/msal-common v15.5.2 2025-04-29 */
7517
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
7528
7518
 
7529
7519
  /*
7530
7520
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -7622,7 +7612,7 @@
7622
7612
  }
7623
7613
  }
7624
7614
 
7625
- /*! @azure/msal-common v15.5.2 2025-04-29 */
7615
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
7626
7616
 
7627
7617
  /*
7628
7618
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -7637,7 +7627,7 @@
7637
7627
  },
7638
7628
  };
7639
7629
 
7640
- /*! @azure/msal-common v15.5.2 2025-04-29 */
7630
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
7641
7631
 
7642
7632
  /*
7643
7633
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -7861,7 +7851,7 @@
7861
7851
  return account.idTokenClaims?.login_hint || null;
7862
7852
  }
7863
7853
 
7864
- /*! @azure/msal-common v15.5.2 2025-04-29 */
7854
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
7865
7855
 
7866
7856
  /*
7867
7857
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -7919,7 +7909,7 @@
7919
7909
  }
7920
7910
  }
7921
7911
 
7922
- /*! @azure/msal-common v15.5.2 2025-04-29 */
7912
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
7923
7913
 
7924
7914
  /*
7925
7915
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -8182,7 +8172,7 @@
8182
8172
  }
8183
8173
  }
8184
8174
 
8185
- /*! @azure/msal-common v15.5.2 2025-04-29 */
8175
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
8186
8176
  /*
8187
8177
  * Copyright (c) Microsoft Corporation. All rights reserved.
8188
8178
  * Licensed under the MIT License.
@@ -8190,7 +8180,7 @@
8190
8180
  const missingKidError = "missing_kid_error";
8191
8181
  const missingAlgError = "missing_alg_error";
8192
8182
 
8193
- /*! @azure/msal-common v15.5.2 2025-04-29 */
8183
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
8194
8184
 
8195
8185
  /*
8196
8186
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -8215,7 +8205,7 @@
8215
8205
  return new JoseHeaderError(code, JoseHeaderErrorMessages[code]);
8216
8206
  }
8217
8207
 
8218
- /*! @azure/msal-common v15.5.2 2025-04-29 */
8208
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
8219
8209
 
8220
8210
  /*
8221
8211
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -8255,7 +8245,7 @@
8255
8245
  }
8256
8246
  }
8257
8247
 
8258
- /*! @azure/msal-common v15.5.2 2025-04-29 */
8248
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
8259
8249
 
8260
8250
  /*
8261
8251
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -8334,7 +8324,7 @@
8334
8324
  }
8335
8325
  }
8336
8326
 
8337
- /*! @azure/msal-common v15.5.2 2025-04-29 */
8327
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
8338
8328
 
8339
8329
  /*
8340
8330
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -9353,10 +9343,15 @@
9353
9343
  */
9354
9344
  MSAL_SKU: "msal.js.browser",
9355
9345
  };
9356
- const NativeConstants = {
9346
+ const PlatformAuthConstants = {
9357
9347
  CHANNEL_ID: "53ee284d-920a-4b59-9d30-a60315b26836",
9358
9348
  PREFERRED_EXTENSION_ID: "ppnbnpeolgkicgegkbkbjmhlideopiji",
9359
9349
  MATS_TELEMETRY: "MATS",
9350
+ MICROSOFT_ENTRA_BROKERID: "MicrosoftEntra",
9351
+ DOM_API_NAME: "DOM API",
9352
+ PLATFORM_DOM_APIS: "get-token-and-sign-out",
9353
+ PLATFORM_DOM_PROVIDER: "PlatformAuthDOMHandler",
9354
+ PLATFORM_EXTENSION_PROVIDER: "PlatformAuthExtensionHandler",
9360
9355
  };
9361
9356
  const NativeExtensionMethod = {
9362
9357
  HandshakeRequest: "Handshake",
@@ -9394,6 +9389,7 @@
9394
9389
  const StaticCacheKeys = {
9395
9390
  ACCOUNT_KEYS: "msal.account.keys",
9396
9391
  TOKEN_KEYS: "msal.token.keys",
9392
+ VERSION: "msal.version",
9397
9393
  };
9398
9394
  /**
9399
9395
  * Cache keys stored in-memory
@@ -9522,7 +9518,8 @@
9522
9518
  ];
9523
9519
  const LOG_LEVEL_CACHE_KEY = "msal.browser.log.level";
9524
9520
  const LOG_PII_CACHE_KEY = "msal.browser.log.pii";
9525
- const BROWSER_PERF_ENABLED_KEY = "msal.browser.performance.enabled";
9521
+ const BROWSER_PERF_ENABLED_KEY = "msal.browser.performance.enabled";
9522
+ const PLATFORM_AUTH_DOM_SUPPORT = "msal.browser.platform.auth.dom";
9526
9523
 
9527
9524
  /*
9528
9525
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -10432,7 +10429,7 @@
10432
10429
 
10433
10430
  /* eslint-disable header/header */
10434
10431
  const name = "@azure/msal-browser";
10435
- const version = "4.11.1";
10432
+ const version = "4.13.0";
10436
10433
 
10437
10434
  /*
10438
10435
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -11784,6 +11781,7 @@
11784
11781
  LOGOUT_FAILURE: "msal:logoutFailure",
11785
11782
  LOGOUT_END: "msal:logoutEnd",
11786
11783
  RESTORE_FROM_BFCACHE: "msal:restoreFromBFCache",
11784
+ BROKER_CONNECTION_ESTABLISHED: "msal:brokerConnectionEstablished",
11787
11785
  };
11788
11786
 
11789
11787
  /*
@@ -11809,6 +11807,20 @@
11809
11807
  }
11810
11808
  async initialize(correlationId) {
11811
11809
  await this.browserStorage.initialize(correlationId);
11810
+ this.trackVersionChanges(correlationId);
11811
+ }
11812
+ /**
11813
+ * Tracks upgrades and downgrades for telemetry and debugging purposes
11814
+ */
11815
+ trackVersionChanges(correlationId) {
11816
+ const previousVersion = this.browserStorage.getItem(StaticCacheKeys.VERSION);
11817
+ if (previousVersion) {
11818
+ this.logger.info(`MSAL.js was last initialized by version: ${previousVersion}`);
11819
+ this.performanceClient.addFields({ previousLibraryVersion: previousVersion }, correlationId);
11820
+ }
11821
+ if (previousVersion !== version) {
11822
+ this.browserStorage.setItem(StaticCacheKeys.VERSION, version);
11823
+ }
11812
11824
  }
11813
11825
  /**
11814
11826
  * Parses passed value as JSON object, JSON.parse() will throw an error.
@@ -12529,7 +12541,17 @@
12529
12541
  getInteractionInProgress() {
12530
12542
  const key = `${Constants.CACHE_PREFIX}.${TemporaryCacheKeys.INTERACTION_STATUS_KEY}`;
12531
12543
  const value = this.getTemporaryCache(key, false);
12532
- return value ? JSON.parse(value) : null;
12544
+ try {
12545
+ return value ? JSON.parse(value) : null;
12546
+ }
12547
+ catch (e) {
12548
+ // Remove interaction and other temp keys if interaction status can't be parsed
12549
+ this.logger.error(`Cannot parse interaction status. Removing temporary cache items and clearing url hash. Retrying interaction should fix the error`);
12550
+ this.removeTemporaryItem(key);
12551
+ this.resetRequestCache();
12552
+ clearHash(window);
12553
+ return null;
12554
+ }
12533
12555
  }
12534
12556
  setInteractionInProgress(inProgress, type = INTERACTION_TYPE.SIGNIN) {
12535
12557
  // Ensure we don't overwrite interaction in progress for a different clientId
@@ -12878,14 +12900,14 @@
12878
12900
  * Licensed under the MIT License.
12879
12901
  */
12880
12902
  class BaseInteractionClient {
12881
- constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeMessageHandler, correlationId) {
12903
+ constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, platformAuthProvider, correlationId) {
12882
12904
  this.config = config;
12883
12905
  this.browserStorage = storageImpl;
12884
12906
  this.browserCrypto = browserCrypto;
12885
12907
  this.networkClient = this.config.system.networkClient;
12886
12908
  this.eventHandler = eventHandler;
12887
12909
  this.navigationClient = navigationClient;
12888
- this.nativeMessageHandler = nativeMessageHandler;
12910
+ this.platformAuthProvider = platformAuthProvider;
12889
12911
  this.correlationId = correlationId || createNewGuid();
12890
12912
  this.logger = logger.clone(BrowserConstants.MSAL_SKU, version, this.correlationId);
12891
12913
  this.performanceClient = performanceClient;
@@ -13241,6 +13263,159 @@
13241
13263
  }
13242
13264
  }
13243
13265
 
13266
+ /*
13267
+ * Copyright (c) Microsoft Corporation. All rights reserved.
13268
+ * Licensed under the MIT License.
13269
+ */
13270
+ /**
13271
+ * Extracts the BrowserStateObject from the state string.
13272
+ * @param browserCrypto
13273
+ * @param state
13274
+ */
13275
+ function extractBrowserRequestState(browserCrypto, state) {
13276
+ if (!state) {
13277
+ return null;
13278
+ }
13279
+ try {
13280
+ const requestStateObj = ProtocolUtils.parseRequestState(browserCrypto, state);
13281
+ return requestStateObj.libraryState.meta;
13282
+ }
13283
+ catch (e) {
13284
+ throw createClientAuthError(invalidState);
13285
+ }
13286
+ }
13287
+
13288
+ /*
13289
+ * Copyright (c) Microsoft Corporation. All rights reserved.
13290
+ * Licensed under the MIT License.
13291
+ */
13292
+ function deserializeResponse(responseString, responseLocation, logger) {
13293
+ // Deserialize hash fragment response parameters.
13294
+ const serverParams = getDeserializedResponse(responseString);
13295
+ if (!serverParams) {
13296
+ if (!stripLeadingHashOrQuery(responseString)) {
13297
+ // Hash or Query string is empty
13298
+ 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.`);
13299
+ throw createBrowserAuthError(hashEmptyError);
13300
+ }
13301
+ else {
13302
+ 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.`);
13303
+ logger.errorPii(`The ${responseLocation} detected is: ${responseString}`);
13304
+ throw createBrowserAuthError(hashDoesNotContainKnownProperties);
13305
+ }
13306
+ }
13307
+ return serverParams;
13308
+ }
13309
+ /**
13310
+ * Returns the interaction type that the response object belongs to
13311
+ */
13312
+ function validateInteractionType(response, browserCrypto, interactionType) {
13313
+ if (!response.state) {
13314
+ throw createBrowserAuthError(noStateInHash);
13315
+ }
13316
+ const platformStateObj = extractBrowserRequestState(browserCrypto, response.state);
13317
+ if (!platformStateObj) {
13318
+ throw createBrowserAuthError(unableToParseState);
13319
+ }
13320
+ if (platformStateObj.interactionType !== interactionType) {
13321
+ throw createBrowserAuthError(stateInteractionTypeMismatch);
13322
+ }
13323
+ }
13324
+
13325
+ /*
13326
+ * Copyright (c) Microsoft Corporation. All rights reserved.
13327
+ * Licensed under the MIT License.
13328
+ */
13329
+ /**
13330
+ * Abstract class which defines operations for a browser interaction handling class.
13331
+ */
13332
+ class InteractionHandler {
13333
+ constructor(authCodeModule, storageImpl, authCodeRequest, logger, performanceClient) {
13334
+ this.authModule = authCodeModule;
13335
+ this.browserStorage = storageImpl;
13336
+ this.authCodeRequest = authCodeRequest;
13337
+ this.logger = logger;
13338
+ this.performanceClient = performanceClient;
13339
+ }
13340
+ /**
13341
+ * Function to handle response parameters from hash.
13342
+ * @param locationHash
13343
+ */
13344
+ async handleCodeResponse(response, request) {
13345
+ this.performanceClient.addQueueMeasurement(PerformanceEvents.HandleCodeResponse, request.correlationId);
13346
+ let authCodeResponse;
13347
+ try {
13348
+ authCodeResponse = getAuthorizationCodePayload(response, request.state);
13349
+ }
13350
+ catch (e) {
13351
+ if (e instanceof ServerError &&
13352
+ e.subError === userCancelled) {
13353
+ // Translate server error caused by user closing native prompt to corresponding first class MSAL error
13354
+ throw createBrowserAuthError(userCancelled);
13355
+ }
13356
+ else {
13357
+ throw e;
13358
+ }
13359
+ }
13360
+ return invokeAsync(this.handleCodeResponseFromServer.bind(this), PerformanceEvents.HandleCodeResponseFromServer, this.logger, this.performanceClient, request.correlationId)(authCodeResponse, request);
13361
+ }
13362
+ /**
13363
+ * Process auth code response from AAD
13364
+ * @param authCodeResponse
13365
+ * @param state
13366
+ * @param authority
13367
+ * @param networkModule
13368
+ * @returns
13369
+ */
13370
+ async handleCodeResponseFromServer(authCodeResponse, request, validateNonce = true) {
13371
+ this.performanceClient.addQueueMeasurement(PerformanceEvents.HandleCodeResponseFromServer, request.correlationId);
13372
+ this.logger.trace("InteractionHandler.handleCodeResponseFromServer called");
13373
+ // Assign code to request
13374
+ this.authCodeRequest.code = authCodeResponse.code;
13375
+ // Check for new cloud instance
13376
+ if (authCodeResponse.cloud_instance_host_name) {
13377
+ await invokeAsync(this.authModule.updateAuthority.bind(this.authModule), PerformanceEvents.UpdateTokenEndpointAuthority, this.logger, this.performanceClient, request.correlationId)(authCodeResponse.cloud_instance_host_name, request.correlationId);
13378
+ }
13379
+ // Nonce validation not needed when redirect not involved (e.g. hybrid spa, renewing token via rt)
13380
+ if (validateNonce) {
13381
+ // TODO: Assigning "response nonce" to "request nonce" is confusing. Refactor the function doing validation to accept request nonce directly
13382
+ authCodeResponse.nonce = request.nonce || undefined;
13383
+ }
13384
+ authCodeResponse.state = request.state;
13385
+ // Add CCS parameters if available
13386
+ if (authCodeResponse.client_info) {
13387
+ this.authCodeRequest.clientInfo = authCodeResponse.client_info;
13388
+ }
13389
+ else {
13390
+ const ccsCred = this.createCcsCredentials(request);
13391
+ if (ccsCred) {
13392
+ this.authCodeRequest.ccsCredential = ccsCred;
13393
+ }
13394
+ }
13395
+ // Acquire token with retrieved code.
13396
+ const tokenResponse = (await invokeAsync(this.authModule.acquireToken.bind(this.authModule), PerformanceEvents.AuthClientAcquireToken, this.logger, this.performanceClient, request.correlationId)(this.authCodeRequest, authCodeResponse));
13397
+ return tokenResponse;
13398
+ }
13399
+ /**
13400
+ * Build ccs creds if available
13401
+ */
13402
+ createCcsCredentials(request) {
13403
+ if (request.account) {
13404
+ return {
13405
+ credential: request.account.homeAccountId,
13406
+ type: CcsCredentialType.HOME_ACCOUNT_ID,
13407
+ };
13408
+ }
13409
+ else if (request.loginHint) {
13410
+ return {
13411
+ credential: request.loginHint,
13412
+ type: CcsCredentialType.UPN,
13413
+ };
13414
+ }
13415
+ return null;
13416
+ }
13417
+ }
13418
+
13244
13419
  /*
13245
13420
  * Copyright (c) Microsoft Corporation. All rights reserved.
13246
13421
  * Licensed under the MIT License.
@@ -13325,930 +13500,1153 @@
13325
13500
  * Copyright (c) Microsoft Corporation. All rights reserved.
13326
13501
  * Licensed under the MIT License.
13327
13502
  */
13328
- class NativeMessageHandler {
13329
- constructor(logger, handshakeTimeoutMs, performanceClient, extensionId) {
13330
- this.logger = logger;
13331
- this.handshakeTimeoutMs = handshakeTimeoutMs;
13332
- this.extensionId = extensionId;
13333
- this.resolvers = new Map(); // Used for non-handshake messages
13334
- this.handshakeResolvers = new Map(); // Used for handshake messages
13335
- this.messageChannel = new MessageChannel();
13336
- this.windowListener = this.onWindowMessage.bind(this); // Window event callback doesn't have access to 'this' unless it's bound
13337
- this.performanceClient = performanceClient;
13338
- this.handshakeEvent = performanceClient.startMeasurement(PerformanceEvents.NativeMessageHandlerHandshake);
13339
- }
13503
+ class SilentCacheClient extends StandardInteractionClient {
13340
13504
  /**
13341
- * Sends a given message to the extension and resolves with the extension response
13342
- * @param body
13505
+ * Returns unexpired tokens from the cache, if available
13506
+ * @param silentRequest
13343
13507
  */
13344
- async sendMessage(body) {
13345
- this.logger.trace("NativeMessageHandler - sendMessage called.");
13346
- const req = {
13347
- channel: NativeConstants.CHANNEL_ID,
13348
- extensionId: this.extensionId,
13349
- responseId: createNewGuid(),
13350
- body: body,
13351
- };
13352
- this.logger.trace("NativeMessageHandler - Sending request to browser extension");
13353
- this.logger.tracePii(`NativeMessageHandler - Sending request to browser extension: ${JSON.stringify(req)}`);
13354
- this.messageChannel.port1.postMessage(req);
13355
- return new Promise((resolve, reject) => {
13356
- this.resolvers.set(req.responseId, { resolve, reject });
13508
+ async acquireToken(silentRequest) {
13509
+ this.performanceClient.addQueueMeasurement(PerformanceEvents.SilentCacheClientAcquireToken, silentRequest.correlationId);
13510
+ // Telemetry manager only used to increment cacheHits here
13511
+ const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenSilent_silentFlow);
13512
+ const clientConfig = await invokeAsync(this.getClientConfiguration.bind(this), PerformanceEvents.StandardInteractionClientGetClientConfiguration, this.logger, this.performanceClient, this.correlationId)({
13513
+ serverTelemetryManager,
13514
+ requestAuthority: silentRequest.authority,
13515
+ requestAzureCloudOptions: silentRequest.azureCloudOptions,
13516
+ account: silentRequest.account,
13357
13517
  });
13358
- }
13359
- /**
13360
- * Returns an instance of the MessageHandler that has successfully established a connection with an extension
13361
- * @param {Logger} logger
13362
- * @param {number} handshakeTimeoutMs
13363
- * @param {IPerformanceClient} performanceClient
13364
- * @param {ICrypto} crypto
13365
- */
13366
- static async createProvider(logger, handshakeTimeoutMs, performanceClient) {
13367
- logger.trace("NativeMessageHandler - createProvider called.");
13518
+ const silentAuthClient = new SilentFlowClient(clientConfig, this.performanceClient);
13519
+ this.logger.verbose("Silent auth client created");
13368
13520
  try {
13369
- const preferredProvider = new NativeMessageHandler(logger, handshakeTimeoutMs, performanceClient, NativeConstants.PREFERRED_EXTENSION_ID);
13370
- await preferredProvider.sendHandshakeRequest();
13371
- return preferredProvider;
13521
+ const response = await invokeAsync(silentAuthClient.acquireCachedToken.bind(silentAuthClient), PerformanceEvents.SilentFlowClientAcquireCachedToken, this.logger, this.performanceClient, silentRequest.correlationId)(silentRequest);
13522
+ const authResponse = response[0];
13523
+ this.performanceClient.addFields({
13524
+ fromCache: true,
13525
+ }, silentRequest.correlationId);
13526
+ return authResponse;
13372
13527
  }
13373
- catch (e) {
13374
- // If preferred extension fails for whatever reason, fallback to using any installed extension
13375
- const backupProvider = new NativeMessageHandler(logger, handshakeTimeoutMs, performanceClient);
13376
- await backupProvider.sendHandshakeRequest();
13377
- return backupProvider;
13528
+ catch (error) {
13529
+ if (error instanceof BrowserAuthError &&
13530
+ error.errorCode === cryptoKeyNotFound) {
13531
+ this.logger.verbose("Signing keypair for bound access token not found. Refreshing bound access token and generating a new crypto keypair.");
13532
+ }
13533
+ throw error;
13378
13534
  }
13379
13535
  }
13380
13536
  /**
13381
- * Send handshake request helper.
13537
+ * API to silenty clear the browser cache.
13538
+ * @param logoutRequest
13382
13539
  */
13383
- async sendHandshakeRequest() {
13384
- this.logger.trace("NativeMessageHandler - sendHandshakeRequest called.");
13385
- // Register this event listener before sending handshake
13386
- window.addEventListener("message", this.windowListener, false); // false is important, because content script message processing should work first
13387
- const req = {
13388
- channel: NativeConstants.CHANNEL_ID,
13389
- extensionId: this.extensionId,
13390
- responseId: createNewGuid(),
13391
- body: {
13392
- method: NativeExtensionMethod.HandshakeRequest,
13393
- },
13394
- };
13395
- this.handshakeEvent.add({
13396
- extensionId: this.extensionId,
13397
- extensionHandshakeTimeoutMs: this.handshakeTimeoutMs,
13398
- });
13399
- this.messageChannel.port1.onmessage = (event) => {
13400
- this.onChannelMessage(event);
13401
- };
13402
- window.postMessage(req, window.origin, [this.messageChannel.port2]);
13403
- return new Promise((resolve, reject) => {
13404
- this.handshakeResolvers.set(req.responseId, { resolve, reject });
13405
- this.timeoutId = window.setTimeout(() => {
13406
- /*
13407
- * Throw an error if neither HandshakeResponse nor original Handshake request are received in a reasonable timeframe.
13408
- * This typically suggests an event handler stopped propagation of the Handshake request but did not respond to it on the MessageChannel port
13409
- */
13410
- window.removeEventListener("message", this.windowListener, false);
13411
- this.messageChannel.port1.close();
13412
- this.messageChannel.port2.close();
13413
- this.handshakeEvent.end({
13414
- extensionHandshakeTimedOut: true,
13415
- success: false,
13416
- });
13417
- reject(createBrowserAuthError(nativeHandshakeTimeout));
13418
- this.handshakeResolvers.delete(req.responseId);
13419
- }, this.handshakeTimeoutMs); // Use a reasonable timeout in milliseconds here
13540
+ logout(logoutRequest) {
13541
+ this.logger.verbose("logoutRedirect called");
13542
+ const validLogoutRequest = this.initializeLogoutRequest(logoutRequest);
13543
+ return this.clearCacheOnLogout(validLogoutRequest?.account);
13544
+ }
13545
+ }
13546
+
13547
+ /*
13548
+ * Copyright (c) Microsoft Corporation. All rights reserved.
13549
+ * Licensed under the MIT License.
13550
+ */
13551
+ class PlatformAuthInteractionClient extends BaseInteractionClient {
13552
+ constructor(config, browserStorage, browserCrypto, logger, eventHandler, navigationClient, apiId, performanceClient, provider, accountId, nativeStorageImpl, correlationId) {
13553
+ super(config, browserStorage, browserCrypto, logger, eventHandler, navigationClient, performanceClient, provider, correlationId);
13554
+ this.apiId = apiId;
13555
+ this.accountId = accountId;
13556
+ this.platformAuthProvider = provider;
13557
+ this.nativeStorageManager = nativeStorageImpl;
13558
+ this.silentCacheClient = new SilentCacheClient(config, this.nativeStorageManager, browserCrypto, logger, eventHandler, navigationClient, performanceClient, provider, correlationId);
13559
+ const extensionName = this.platformAuthProvider.getExtensionName();
13560
+ this.skus = ServerTelemetryManager.makeExtraSkuString({
13561
+ libraryName: BrowserConstants.MSAL_SKU,
13562
+ libraryVersion: version,
13563
+ extensionName: extensionName,
13564
+ extensionVersion: this.platformAuthProvider.getExtensionVersion(),
13420
13565
  });
13421
13566
  }
13422
13567
  /**
13423
- * Invoked when a message is posted to the window. If a handshake request is received it means the extension is not installed.
13424
- * @param event
13568
+ * Adds SKUs to request extra query parameters
13569
+ * @param request {PlatformAuthRequest}
13570
+ * @private
13425
13571
  */
13426
- onWindowMessage(event) {
13427
- this.logger.trace("NativeMessageHandler - onWindowMessage called");
13428
- // We only accept messages from ourselves
13429
- if (event.source !== window) {
13430
- return;
13431
- }
13432
- const request = event.data;
13433
- if (!request.channel ||
13434
- request.channel !== NativeConstants.CHANNEL_ID) {
13435
- return;
13436
- }
13437
- if (request.extensionId && request.extensionId !== this.extensionId) {
13438
- return;
13439
- }
13440
- if (request.body.method === NativeExtensionMethod.HandshakeRequest) {
13441
- const handshakeResolver = this.handshakeResolvers.get(request.responseId);
13442
- /*
13443
- * Filter out responses with no matched resolvers sooner to keep channel ports open while waiting for
13444
- * the proper response.
13445
- */
13446
- if (!handshakeResolver) {
13447
- this.logger.trace(`NativeMessageHandler.onWindowMessage - resolver can't be found for request ${request.responseId}`);
13448
- return;
13449
- }
13450
- // If we receive this message back it means no extension intercepted the request, meaning no extension supporting handshake protocol is installed
13451
- this.logger.verbose(request.extensionId
13452
- ? `Extension with id: ${request.extensionId} not installed`
13453
- : "No extension installed");
13454
- clearTimeout(this.timeoutId);
13455
- this.messageChannel.port1.close();
13456
- this.messageChannel.port2.close();
13457
- window.removeEventListener("message", this.windowListener, false);
13458
- this.handshakeEvent.end({
13459
- success: false,
13460
- extensionInstalled: false,
13461
- });
13462
- handshakeResolver.reject(createBrowserAuthError(nativeExtensionNotInstalled));
13463
- }
13572
+ addRequestSKUs(request) {
13573
+ request.extraParameters = {
13574
+ ...request.extraParameters,
13575
+ [X_CLIENT_EXTRA_SKU]: this.skus,
13576
+ };
13464
13577
  }
13465
13578
  /**
13466
- * Invoked when a message is received from the extension on the MessageChannel port
13467
- * @param event
13579
+ * Acquire token from native platform via browser extension
13580
+ * @param request
13468
13581
  */
13469
- onChannelMessage(event) {
13470
- this.logger.trace("NativeMessageHandler - onChannelMessage called.");
13471
- const request = event.data;
13472
- const resolver = this.resolvers.get(request.responseId);
13473
- const handshakeResolver = this.handshakeResolvers.get(request.responseId);
13582
+ async acquireToken(request, cacheLookupPolicy) {
13583
+ this.performanceClient.addQueueMeasurement(PerformanceEvents.NativeInteractionClientAcquireToken, request.correlationId);
13584
+ this.logger.trace("NativeInteractionClient - acquireToken called.");
13585
+ // start the perf measurement
13586
+ const nativeATMeasurement = this.performanceClient.startMeasurement(PerformanceEvents.NativeInteractionClientAcquireToken, request.correlationId);
13587
+ const reqTimestamp = nowSeconds();
13588
+ const serverTelemetryManager = this.initializeServerTelemetryManager(this.apiId);
13474
13589
  try {
13475
- const method = request.body.method;
13476
- if (method === NativeExtensionMethod.Response) {
13477
- if (!resolver) {
13478
- return;
13479
- }
13480
- const response = request.body.response;
13481
- this.logger.trace("NativeMessageHandler - Received response from browser extension");
13482
- this.logger.tracePii(`NativeMessageHandler - Received response from browser extension: ${JSON.stringify(response)}`);
13483
- if (response.status !== "Success") {
13484
- resolver.reject(createNativeAuthError(response.code, response.description, response.ext));
13485
- }
13486
- else if (response.result) {
13487
- if (response.result["code"] &&
13488
- response.result["description"]) {
13489
- resolver.reject(createNativeAuthError(response.result["code"], response.result["description"], response.result["ext"]));
13490
- }
13491
- else {
13492
- resolver.resolve(response.result);
13493
- }
13494
- }
13495
- else {
13496
- throw createAuthError(unexpectedError, "Event does not contain result.");
13497
- }
13498
- this.resolvers.delete(request.responseId);
13590
+ // initialize native request
13591
+ const nativeRequest = await this.initializeNativeRequest(request);
13592
+ // check if the tokens can be retrieved from internal cache
13593
+ try {
13594
+ const result = await this.acquireTokensFromCache(this.accountId, nativeRequest);
13595
+ nativeATMeasurement.end({
13596
+ success: true,
13597
+ isNativeBroker: false,
13598
+ fromCache: true,
13599
+ });
13600
+ return result;
13499
13601
  }
13500
- else if (method === NativeExtensionMethod.HandshakeResponse) {
13501
- if (!handshakeResolver) {
13502
- this.logger.trace(`NativeMessageHandler.onChannelMessage - resolver can't be found for request ${request.responseId}`);
13503
- return;
13602
+ catch (e) {
13603
+ if (cacheLookupPolicy === CacheLookupPolicy.AccessToken) {
13604
+ this.logger.info("MSAL internal Cache does not contain tokens, return error as per cache policy");
13605
+ throw e;
13504
13606
  }
13505
- clearTimeout(this.timeoutId); // Clear setTimeout
13506
- window.removeEventListener("message", this.windowListener, false); // Remove 'No extension' listener
13507
- this.extensionId = request.extensionId;
13508
- this.extensionVersion = request.body.version;
13509
- this.logger.verbose(`NativeMessageHandler - Received HandshakeResponse from extension: ${this.extensionId}`);
13510
- this.handshakeEvent.end({
13511
- extensionInstalled: true,
13607
+ // continue with a native call for any and all errors
13608
+ this.logger.info("MSAL internal Cache does not contain tokens, proceed to make a native call");
13609
+ }
13610
+ const validatedResponse = await this.platformAuthProvider.sendMessage(nativeRequest);
13611
+ return await this.handleNativeResponse(validatedResponse, nativeRequest, reqTimestamp)
13612
+ .then((result) => {
13613
+ nativeATMeasurement.end({
13512
13614
  success: true,
13615
+ isNativeBroker: true,
13616
+ requestId: result.requestId,
13513
13617
  });
13514
- handshakeResolver.resolve();
13515
- this.handshakeResolvers.delete(request.responseId);
13516
- }
13517
- // Do nothing if method is not Response or HandshakeResponse
13618
+ serverTelemetryManager.clearNativeBrokerErrorCode();
13619
+ return result;
13620
+ })
13621
+ .catch((error) => {
13622
+ nativeATMeasurement.end({
13623
+ success: false,
13624
+ errorCode: error.errorCode,
13625
+ subErrorCode: error.subError,
13626
+ isNativeBroker: true,
13627
+ });
13628
+ throw error;
13629
+ });
13518
13630
  }
13519
- catch (err) {
13520
- this.logger.error("Error parsing response from WAM Extension");
13521
- this.logger.errorPii(`Error parsing response from WAM Extension: ${err}`);
13522
- this.logger.errorPii(`Unable to parse ${event}`);
13523
- if (resolver) {
13524
- resolver.reject(err);
13525
- }
13526
- else if (handshakeResolver) {
13527
- handshakeResolver.reject(err);
13631
+ catch (e) {
13632
+ if (e instanceof NativeAuthError) {
13633
+ serverTelemetryManager.setNativeBrokerErrorCode(e.errorCode);
13528
13634
  }
13635
+ throw e;
13529
13636
  }
13530
13637
  }
13531
13638
  /**
13532
- * Returns the Id for the browser extension this handler is communicating with
13533
- * @returns
13639
+ * Creates silent flow request
13640
+ * @param request
13641
+ * @param cachedAccount
13642
+ * @returns CommonSilentFlowRequest
13534
13643
  */
13535
- getExtensionId() {
13536
- return this.extensionId;
13644
+ createSilentCacheRequest(request, cachedAccount) {
13645
+ return {
13646
+ authority: request.authority,
13647
+ correlationId: this.correlationId,
13648
+ scopes: ScopeSet.fromString(request.scope).asArray(),
13649
+ account: cachedAccount,
13650
+ forceRefresh: false,
13651
+ };
13537
13652
  }
13538
13653
  /**
13539
- * Returns the version for the browser extension this handler is communicating with
13540
- * @returns
13654
+ * Fetches the tokens from the cache if un-expired
13655
+ * @param nativeAccountId
13656
+ * @param request
13657
+ * @returns authenticationResult
13541
13658
  */
13542
- getExtensionVersion() {
13543
- return this.extensionVersion;
13659
+ async acquireTokensFromCache(nativeAccountId, request) {
13660
+ if (!nativeAccountId) {
13661
+ this.logger.warning("NativeInteractionClient:acquireTokensFromCache - No nativeAccountId provided");
13662
+ throw createClientAuthError(noAccountFound);
13663
+ }
13664
+ // fetch the account from browser cache
13665
+ const account = this.browserStorage.getBaseAccountInfo({
13666
+ nativeAccountId,
13667
+ });
13668
+ if (!account) {
13669
+ throw createClientAuthError(noAccountFound);
13670
+ }
13671
+ // leverage silent flow for cached tokens retrieval
13672
+ try {
13673
+ const silentRequest = this.createSilentCacheRequest(request, account);
13674
+ const result = await this.silentCacheClient.acquireToken(silentRequest);
13675
+ const fullAccount = {
13676
+ ...account,
13677
+ idTokenClaims: result?.idTokenClaims,
13678
+ idToken: result?.idToken,
13679
+ };
13680
+ return {
13681
+ ...result,
13682
+ account: fullAccount,
13683
+ };
13684
+ }
13685
+ catch (e) {
13686
+ throw e;
13687
+ }
13544
13688
  }
13545
13689
  /**
13546
- * Returns boolean indicating whether or not the request should attempt to use native broker
13547
- * @param logger
13548
- * @param config
13549
- * @param nativeExtensionProvider
13550
- * @param authenticationScheme
13690
+ * Acquires a token from native platform then redirects to the redirectUri instead of returning the response
13691
+ * @param {RedirectRequest} request
13692
+ * @param {InProgressPerformanceEvent} rootMeasurement
13551
13693
  */
13552
- static isPlatformBrokerAvailable(config, logger, nativeExtensionProvider, authenticationScheme) {
13553
- logger.trace("isPlatformBrokerAvailable called");
13554
- if (!config.system.allowPlatformBroker) {
13555
- logger.trace("isPlatformBrokerAvailable: allowPlatformBroker is not enabled, returning false");
13556
- // Developer disabled WAM
13557
- return false;
13558
- }
13559
- if (!nativeExtensionProvider) {
13560
- logger.trace("isPlatformBrokerAvailable: Platform extension provider is not initialized, returning false");
13561
- // Extension is not available
13562
- return false;
13694
+ async acquireTokenRedirect(request, rootMeasurement) {
13695
+ this.logger.trace("NativeInteractionClient - acquireTokenRedirect called.");
13696
+ const { ...remainingParameters } = request;
13697
+ delete remainingParameters.onRedirectNavigate;
13698
+ const nativeRequest = await this.initializeNativeRequest(remainingParameters);
13699
+ try {
13700
+ await this.platformAuthProvider.sendMessage(nativeRequest);
13563
13701
  }
13564
- if (authenticationScheme) {
13565
- switch (authenticationScheme) {
13566
- case AuthenticationScheme.BEARER:
13567
- case AuthenticationScheme.POP:
13568
- logger.trace("isPlatformBrokerAvailable: authenticationScheme is supported, returning true");
13569
- return true;
13570
- default:
13571
- logger.trace("isPlatformBrokerAvailable: authenticationScheme is not supported, returning false");
13572
- return false;
13702
+ catch (e) {
13703
+ // Only throw fatal errors here to allow application to fallback to regular redirect. Otherwise proceed and the error will be thrown in handleRedirectPromise
13704
+ if (e instanceof NativeAuthError) {
13705
+ const serverTelemetryManager = this.initializeServerTelemetryManager(this.apiId);
13706
+ serverTelemetryManager.setNativeBrokerErrorCode(e.errorCode);
13707
+ if (isFatalNativeAuthError(e)) {
13708
+ throw e;
13709
+ }
13573
13710
  }
13574
13711
  }
13575
- return true;
13576
- }
13577
- }
13578
-
13579
- /*
13580
- * Copyright (c) Microsoft Corporation. All rights reserved.
13581
- * Licensed under the MIT License.
13582
- */
13583
- /**
13584
- * Extracts the BrowserStateObject from the state string.
13585
- * @param browserCrypto
13586
- * @param state
13587
- */
13588
- function extractBrowserRequestState(browserCrypto, state) {
13589
- if (!state) {
13590
- return null;
13591
- }
13592
- try {
13593
- const requestStateObj = ProtocolUtils.parseRequestState(browserCrypto, state);
13594
- return requestStateObj.libraryState.meta;
13595
- }
13596
- catch (e) {
13597
- throw createClientAuthError(invalidState);
13598
- }
13599
- }
13600
-
13601
- /*
13602
- * Copyright (c) Microsoft Corporation. All rights reserved.
13603
- * Licensed under the MIT License.
13604
- */
13605
- function deserializeResponse(responseString, responseLocation, logger) {
13606
- // Deserialize hash fragment response parameters.
13607
- const serverParams = getDeserializedResponse(responseString);
13608
- if (!serverParams) {
13609
- if (!stripLeadingHashOrQuery(responseString)) {
13610
- // Hash or Query string is empty
13611
- 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.`);
13612
- throw createBrowserAuthError(hashEmptyError);
13613
- }
13614
- else {
13615
- 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.`);
13616
- logger.errorPii(`The ${responseLocation} detected is: ${responseString}`);
13617
- throw createBrowserAuthError(hashDoesNotContainKnownProperties);
13618
- }
13619
- }
13620
- return serverParams;
13621
- }
13622
- /**
13623
- * Returns the interaction type that the response object belongs to
13624
- */
13625
- function validateInteractionType(response, browserCrypto, interactionType) {
13626
- if (!response.state) {
13627
- throw createBrowserAuthError(noStateInHash);
13628
- }
13629
- const platformStateObj = extractBrowserRequestState(browserCrypto, response.state);
13630
- if (!platformStateObj) {
13631
- throw createBrowserAuthError(unableToParseState);
13632
- }
13633
- if (platformStateObj.interactionType !== interactionType) {
13634
- throw createBrowserAuthError(stateInteractionTypeMismatch);
13635
- }
13636
- }
13637
-
13638
- /*
13639
- * Copyright (c) Microsoft Corporation. All rights reserved.
13640
- * Licensed under the MIT License.
13641
- */
13642
- /**
13643
- * Abstract class which defines operations for a browser interaction handling class.
13644
- */
13645
- class InteractionHandler {
13646
- constructor(authCodeModule, storageImpl, authCodeRequest, logger, performanceClient) {
13647
- this.authModule = authCodeModule;
13648
- this.browserStorage = storageImpl;
13649
- this.authCodeRequest = authCodeRequest;
13650
- this.logger = logger;
13651
- this.performanceClient = performanceClient;
13712
+ this.browserStorage.setTemporaryCache(TemporaryCacheKeys.NATIVE_REQUEST, JSON.stringify(nativeRequest), true);
13713
+ const navigationOptions = {
13714
+ apiId: ApiId.acquireTokenRedirect,
13715
+ timeout: this.config.system.redirectNavigationTimeout,
13716
+ noHistory: false,
13717
+ };
13718
+ const redirectUri = this.config.auth.navigateToLoginRequestUrl
13719
+ ? window.location.href
13720
+ : this.getRedirectUri(request.redirectUri);
13721
+ rootMeasurement.end({ success: true });
13722
+ await this.navigationClient.navigateExternal(redirectUri, navigationOptions); // Need to treat this as external to ensure handleRedirectPromise is run again
13652
13723
  }
13653
13724
  /**
13654
- * Function to handle response parameters from hash.
13655
- * @param locationHash
13725
+ * If the previous page called native platform for a token using redirect APIs, send the same request again and return the response
13726
+ * @param performanceClient {IPerformanceClient?}
13727
+ * @param correlationId {string?} correlation identifier
13656
13728
  */
13657
- async handleCodeResponse(response, request) {
13658
- this.performanceClient.addQueueMeasurement(PerformanceEvents.HandleCodeResponse, request.correlationId);
13659
- let authCodeResponse;
13660
- try {
13661
- authCodeResponse = getAuthorizationCodePayload(response, request.state);
13729
+ async handleRedirectPromise(performanceClient, correlationId) {
13730
+ this.logger.trace("NativeInteractionClient - handleRedirectPromise called.");
13731
+ if (!this.browserStorage.isInteractionInProgress(true)) {
13732
+ this.logger.info("handleRedirectPromise called but there is no interaction in progress, returning null.");
13733
+ return null;
13662
13734
  }
13663
- catch (e) {
13664
- if (e instanceof ServerError &&
13665
- e.subError === userCancelled) {
13666
- // Translate server error caused by user closing native prompt to corresponding first class MSAL error
13667
- throw createBrowserAuthError(userCancelled);
13668
- }
13669
- else {
13670
- throw e;
13735
+ // remove prompt from the request to prevent WAM from prompting twice
13736
+ const cachedRequest = this.browserStorage.getCachedNativeRequest();
13737
+ if (!cachedRequest) {
13738
+ this.logger.verbose("NativeInteractionClient - handleRedirectPromise called but there is no cached request, returning null.");
13739
+ if (performanceClient && correlationId) {
13740
+ performanceClient?.addFields({ errorCode: "no_cached_request" }, correlationId);
13671
13741
  }
13742
+ return null;
13672
13743
  }
13673
- return invokeAsync(this.handleCodeResponseFromServer.bind(this), PerformanceEvents.HandleCodeResponseFromServer, this.logger, this.performanceClient, request.correlationId)(authCodeResponse, request);
13674
- }
13675
- /**
13676
- * Process auth code response from AAD
13677
- * @param authCodeResponse
13678
- * @param state
13679
- * @param authority
13680
- * @param networkModule
13681
- * @returns
13682
- */
13683
- async handleCodeResponseFromServer(authCodeResponse, request, validateNonce = true) {
13684
- this.performanceClient.addQueueMeasurement(PerformanceEvents.HandleCodeResponseFromServer, request.correlationId);
13685
- this.logger.trace("InteractionHandler.handleCodeResponseFromServer called");
13686
- // Assign code to request
13687
- this.authCodeRequest.code = authCodeResponse.code;
13688
- // Check for new cloud instance
13689
- if (authCodeResponse.cloud_instance_host_name) {
13690
- await invokeAsync(this.authModule.updateAuthority.bind(this.authModule), PerformanceEvents.UpdateTokenEndpointAuthority, this.logger, this.performanceClient, request.correlationId)(authCodeResponse.cloud_instance_host_name, request.correlationId);
13691
- }
13692
- // Nonce validation not needed when redirect not involved (e.g. hybrid spa, renewing token via rt)
13693
- if (validateNonce) {
13694
- // TODO: Assigning "response nonce" to "request nonce" is confusing. Refactor the function doing validation to accept request nonce directly
13695
- authCodeResponse.nonce = request.nonce || undefined;
13744
+ const { prompt, ...request } = cachedRequest;
13745
+ if (prompt) {
13746
+ 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.");
13696
13747
  }
13697
- authCodeResponse.state = request.state;
13698
- // Add CCS parameters if available
13699
- if (authCodeResponse.client_info) {
13700
- this.authCodeRequest.clientInfo = authCodeResponse.client_info;
13748
+ this.browserStorage.removeItem(this.browserStorage.generateCacheKey(TemporaryCacheKeys.NATIVE_REQUEST));
13749
+ const reqTimestamp = nowSeconds();
13750
+ try {
13751
+ this.logger.verbose("NativeInteractionClient - handleRedirectPromise sending message to native broker.");
13752
+ const response = await this.platformAuthProvider.sendMessage(request);
13753
+ const authResult = await this.handleNativeResponse(response, request, reqTimestamp);
13754
+ const serverTelemetryManager = this.initializeServerTelemetryManager(this.apiId);
13755
+ serverTelemetryManager.clearNativeBrokerErrorCode();
13756
+ return authResult;
13701
13757
  }
13702
- else {
13703
- const ccsCred = this.createCcsCredentials(request);
13704
- if (ccsCred) {
13705
- this.authCodeRequest.ccsCredential = ccsCred;
13706
- }
13758
+ catch (e) {
13759
+ throw e;
13707
13760
  }
13708
- // Acquire token with retrieved code.
13709
- const tokenResponse = (await invokeAsync(this.authModule.acquireToken.bind(this.authModule), PerformanceEvents.AuthClientAcquireToken, this.logger, this.performanceClient, request.correlationId)(this.authCodeRequest, authCodeResponse));
13710
- return tokenResponse;
13711
13761
  }
13712
13762
  /**
13713
- * Build ccs creds if available
13763
+ * Logout from native platform via browser extension
13764
+ * @param request
13714
13765
  */
13715
- createCcsCredentials(request) {
13716
- if (request.account) {
13717
- return {
13718
- credential: request.account.homeAccountId,
13719
- type: CcsCredentialType.HOME_ACCOUNT_ID,
13720
- };
13721
- }
13722
- else if (request.loginHint) {
13723
- return {
13724
- credential: request.loginHint,
13725
- type: CcsCredentialType.UPN,
13726
- };
13727
- }
13728
- return null;
13766
+ logout() {
13767
+ this.logger.trace("NativeInteractionClient - logout called.");
13768
+ return Promise.reject("Logout not implemented yet");
13729
13769
  }
13730
- }
13731
-
13732
- /*
13733
- * Copyright (c) Microsoft Corporation. All rights reserved.
13734
- * Licensed under the MIT License.
13735
- */
13736
- class SilentCacheClient extends StandardInteractionClient {
13737
13770
  /**
13738
- * Returns unexpired tokens from the cache, if available
13739
- * @param silentRequest
13771
+ * Transform response from native platform into AuthenticationResult object which will be returned to the end user
13772
+ * @param response
13773
+ * @param request
13774
+ * @param reqTimestamp
13740
13775
  */
13741
- async acquireToken(silentRequest) {
13742
- this.performanceClient.addQueueMeasurement(PerformanceEvents.SilentCacheClientAcquireToken, silentRequest.correlationId);
13743
- // Telemetry manager only used to increment cacheHits here
13744
- const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenSilent_silentFlow);
13745
- const clientConfig = await invokeAsync(this.getClientConfiguration.bind(this), PerformanceEvents.StandardInteractionClientGetClientConfiguration, this.logger, this.performanceClient, this.correlationId)({
13746
- serverTelemetryManager,
13747
- requestAuthority: silentRequest.authority,
13748
- requestAzureCloudOptions: silentRequest.azureCloudOptions,
13749
- account: silentRequest.account,
13750
- });
13751
- const silentAuthClient = new SilentFlowClient(clientConfig, this.performanceClient);
13752
- this.logger.verbose("Silent auth client created");
13753
- try {
13754
- const response = await invokeAsync(silentAuthClient.acquireCachedToken.bind(silentAuthClient), PerformanceEvents.SilentFlowClientAcquireCachedToken, this.logger, this.performanceClient, silentRequest.correlationId)(silentRequest);
13755
- const authResponse = response[0];
13756
- this.performanceClient.addFields({
13757
- fromCache: true,
13758
- }, silentRequest.correlationId);
13759
- return authResponse;
13776
+ async handleNativeResponse(response, request, reqTimestamp) {
13777
+ this.logger.trace("NativeInteractionClient - handleNativeResponse called.");
13778
+ // generate identifiers
13779
+ const idTokenClaims = extractTokenClaims(response.id_token, base64Decode);
13780
+ const homeAccountIdentifier = this.createHomeAccountIdentifier(response, idTokenClaims);
13781
+ const cachedhomeAccountId = this.browserStorage.getAccountInfoFilteredBy({
13782
+ nativeAccountId: request.accountId,
13783
+ })?.homeAccountId;
13784
+ // add exception for double brokering, please note this is temporary and will be fortified in future
13785
+ if (request.extraParameters?.child_client_id &&
13786
+ response.account.id !== request.accountId) {
13787
+ this.logger.info("handleNativeServerResponse: Double broker flow detected, ignoring accountId mismatch");
13760
13788
  }
13761
- catch (error) {
13762
- if (error instanceof BrowserAuthError &&
13763
- error.errorCode === cryptoKeyNotFound) {
13764
- this.logger.verbose("Signing keypair for bound access token not found. Refreshing bound access token and generating a new crypto keypair.");
13765
- }
13766
- throw error;
13789
+ else if (homeAccountIdentifier !== cachedhomeAccountId &&
13790
+ response.account.id !== request.accountId) {
13791
+ // 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
13792
+ throw createNativeAuthError(userSwitch);
13767
13793
  }
13794
+ // Get the preferred_cache domain for the given authority
13795
+ const authority = await this.getDiscoveredAuthority({
13796
+ requestAuthority: request.authority,
13797
+ });
13798
+ const baseAccount = buildAccountToCache(this.browserStorage, authority, homeAccountIdentifier, base64Decode, idTokenClaims, response.client_info, undefined, // environment
13799
+ idTokenClaims.tid, undefined, // auth code payload
13800
+ response.account.id, this.logger);
13801
+ // Ensure expires_in is in number format
13802
+ response.expires_in = Number(response.expires_in);
13803
+ // generate authenticationResult
13804
+ const result = await this.generateAuthenticationResult(response, request, idTokenClaims, baseAccount, authority.canonicalAuthority, reqTimestamp);
13805
+ // cache accounts and tokens in the appropriate storage
13806
+ await this.cacheAccount(baseAccount);
13807
+ await this.cacheNativeTokens(response, request, homeAccountIdentifier, idTokenClaims, response.access_token, result.tenantId, reqTimestamp);
13808
+ return result;
13768
13809
  }
13769
13810
  /**
13770
- * API to silenty clear the browser cache.
13771
- * @param logoutRequest
13811
+ * creates an homeAccountIdentifier for the account
13812
+ * @param response
13813
+ * @param idTokenObj
13814
+ * @returns
13772
13815
  */
13773
- logout(logoutRequest) {
13774
- this.logger.verbose("logoutRedirect called");
13775
- const validLogoutRequest = this.initializeLogoutRequest(logoutRequest);
13776
- return this.clearCacheOnLogout(validLogoutRequest?.account);
13777
- }
13778
- }
13779
-
13780
- /*
13781
- * Copyright (c) Microsoft Corporation. All rights reserved.
13782
- * Licensed under the MIT License.
13783
- */
13784
- class NativeInteractionClient extends BaseInteractionClient {
13785
- constructor(config, browserStorage, browserCrypto, logger, eventHandler, navigationClient, apiId, performanceClient, provider, accountId, nativeStorageImpl, correlationId) {
13786
- super(config, browserStorage, browserCrypto, logger, eventHandler, navigationClient, performanceClient, provider, correlationId);
13787
- this.apiId = apiId;
13788
- this.accountId = accountId;
13789
- this.nativeMessageHandler = provider;
13790
- this.nativeStorageManager = nativeStorageImpl;
13791
- this.silentCacheClient = new SilentCacheClient(config, this.nativeStorageManager, browserCrypto, logger, eventHandler, navigationClient, performanceClient, provider, correlationId);
13792
- const extensionName = this.nativeMessageHandler.getExtensionId() ===
13793
- NativeConstants.PREFERRED_EXTENSION_ID
13794
- ? "chrome"
13795
- : this.nativeMessageHandler.getExtensionId()?.length
13796
- ? "unknown"
13797
- : undefined;
13798
- this.skus = ServerTelemetryManager.makeExtraSkuString({
13799
- libraryName: BrowserConstants.MSAL_SKU,
13800
- libraryVersion: version,
13801
- extensionName: extensionName,
13802
- extensionVersion: this.nativeMessageHandler.getExtensionVersion(),
13803
- });
13816
+ createHomeAccountIdentifier(response, idTokenClaims) {
13817
+ // Save account in browser storage
13818
+ const homeAccountIdentifier = AccountEntity.generateHomeAccountId(response.client_info || Constants.EMPTY_STRING, AuthorityType.Default, this.logger, this.browserCrypto, idTokenClaims);
13819
+ return homeAccountIdentifier;
13804
13820
  }
13805
13821
  /**
13806
- * Adds SKUs to request extra query parameters
13807
- * @param request {NativeTokenRequest}
13808
- * @private
13822
+ * Helper to generate scopes
13823
+ * @param response
13824
+ * @param request
13825
+ * @returns
13809
13826
  */
13810
- addRequestSKUs(request) {
13811
- request.extraParameters = {
13812
- ...request.extraParameters,
13813
- [X_CLIENT_EXTRA_SKU]: this.skus,
13814
- };
13827
+ generateScopes(requestScopes, responseScopes) {
13828
+ return responseScopes
13829
+ ? ScopeSet.fromString(responseScopes)
13830
+ : ScopeSet.fromString(requestScopes);
13815
13831
  }
13816
13832
  /**
13817
- * Acquire token from native platform via browser extension
13833
+ * If PoP token is requesred, records the PoP token if returned from the WAM, else generates one in the browser
13818
13834
  * @param request
13835
+ * @param response
13819
13836
  */
13820
- async acquireToken(request, cacheLookupPolicy) {
13821
- this.performanceClient.addQueueMeasurement(PerformanceEvents.NativeInteractionClientAcquireToken, request.correlationId);
13822
- this.logger.trace("NativeInteractionClient - acquireToken called.");
13823
- // start the perf measurement
13824
- const nativeATMeasurement = this.performanceClient.startMeasurement(PerformanceEvents.NativeInteractionClientAcquireToken, request.correlationId);
13825
- const reqTimestamp = nowSeconds();
13826
- const serverTelemetryManager = this.initializeServerTelemetryManager(this.apiId);
13827
- try {
13828
- // initialize native request
13829
- const nativeRequest = await this.initializeNativeRequest(request);
13830
- // check if the tokens can be retrieved from internal cache
13831
- try {
13832
- const result = await this.acquireTokensFromCache(this.accountId, nativeRequest);
13833
- nativeATMeasurement.end({
13834
- success: true,
13835
- isNativeBroker: false,
13836
- fromCache: true,
13837
- });
13838
- return result;
13839
- }
13840
- catch (e) {
13841
- if (cacheLookupPolicy === CacheLookupPolicy.AccessToken) {
13842
- this.logger.info("MSAL internal Cache does not contain tokens, return error as per cache policy");
13843
- throw e;
13844
- }
13845
- // continue with a native call for any and all errors
13846
- this.logger.info("MSAL internal Cache does not contain tokens, proceed to make a native call");
13837
+ async generatePopAccessToken(response, request) {
13838
+ if (request.tokenType === AuthenticationScheme.POP &&
13839
+ request.signPopToken) {
13840
+ /**
13841
+ * This code prioritizes SHR returned from the native layer. In case of error/SHR not calculated from WAM and the AT
13842
+ * is still received, SHR is calculated locally
13843
+ */
13844
+ // Check if native layer returned an SHR token
13845
+ if (response.shr) {
13846
+ this.logger.trace("handleNativeServerResponse: SHR is enabled in native layer");
13847
+ return response.shr;
13847
13848
  }
13848
- const { ...nativeTokenRequest } = nativeRequest;
13849
- // fall back to native calls
13850
- const messageBody = {
13851
- method: NativeExtensionMethod.GetToken,
13852
- request: nativeTokenRequest,
13849
+ // Generate SHR in msal js if WAM does not compute it when POP is enabled
13850
+ const popTokenGenerator = new PopTokenGenerator(this.browserCrypto);
13851
+ const shrParameters = {
13852
+ resourceRequestMethod: request.resourceRequestMethod,
13853
+ resourceRequestUri: request.resourceRequestUri,
13854
+ shrClaims: request.shrClaims,
13855
+ shrNonce: request.shrNonce,
13853
13856
  };
13854
- const response = await this.nativeMessageHandler.sendMessage(messageBody);
13855
- const validatedResponse = this.validateNativeResponse(response);
13856
- return await this.handleNativeResponse(validatedResponse, nativeRequest, reqTimestamp)
13857
- .then((result) => {
13858
- nativeATMeasurement.end({
13859
- success: true,
13860
- isNativeBroker: true,
13861
- requestId: result.requestId,
13862
- });
13863
- serverTelemetryManager.clearNativeBrokerErrorCode();
13864
- return result;
13865
- })
13866
- .catch((error) => {
13867
- nativeATMeasurement.end({
13868
- success: false,
13869
- errorCode: error.errorCode,
13870
- subErrorCode: error.subError,
13871
- isNativeBroker: true,
13872
- });
13873
- throw error;
13874
- });
13875
- }
13876
- catch (e) {
13877
- if (e instanceof NativeAuthError) {
13878
- serverTelemetryManager.setNativeBrokerErrorCode(e.errorCode);
13857
+ /**
13858
+ * KeyID must be present in the native request from when the PoP key was generated in order for
13859
+ * PopTokenGenerator to query the full key for signing
13860
+ */
13861
+ if (!request.keyId) {
13862
+ throw createClientAuthError(keyIdMissing);
13879
13863
  }
13880
- throw e;
13864
+ return popTokenGenerator.signPopToken(response.access_token, request.keyId, shrParameters);
13865
+ }
13866
+ else {
13867
+ return response.access_token;
13881
13868
  }
13882
13869
  }
13883
13870
  /**
13884
- * Creates silent flow request
13871
+ * Generates authentication result
13872
+ * @param response
13885
13873
  * @param request
13886
- * @param cachedAccount
13887
- * @returns CommonSilentFlowRequest
13874
+ * @param idTokenObj
13875
+ * @param accountEntity
13876
+ * @param authority
13877
+ * @param reqTimestamp
13878
+ * @returns
13888
13879
  */
13889
- createSilentCacheRequest(request, cachedAccount) {
13890
- return {
13891
- authority: request.authority,
13880
+ async generateAuthenticationResult(response, request, idTokenClaims, accountEntity, authority, reqTimestamp) {
13881
+ // Add Native Broker fields to Telemetry
13882
+ const mats = this.addTelemetryFromNativeResponse(response.properties.MATS);
13883
+ // If scopes not returned in server response, use request scopes
13884
+ const responseScopes = this.generateScopes(request.scope, response.scope);
13885
+ const accountProperties = response.account.properties || {};
13886
+ const uid = accountProperties["UID"] ||
13887
+ idTokenClaims.oid ||
13888
+ idTokenClaims.sub ||
13889
+ Constants.EMPTY_STRING;
13890
+ const tid = accountProperties["TenantId"] ||
13891
+ idTokenClaims.tid ||
13892
+ Constants.EMPTY_STRING;
13893
+ const accountInfo = updateAccountTenantProfileData(accountEntity.getAccountInfo(), undefined, // tenantProfile optional
13894
+ idTokenClaims, response.id_token);
13895
+ /**
13896
+ * In pairwise broker flows, this check prevents the broker's native account id
13897
+ * from being returned over the embedded app's account id.
13898
+ */
13899
+ if (accountInfo.nativeAccountId !== response.account.id) {
13900
+ accountInfo.nativeAccountId = response.account.id;
13901
+ }
13902
+ // generate PoP token as needed
13903
+ const responseAccessToken = await this.generatePopAccessToken(response, request);
13904
+ const tokenType = request.tokenType === AuthenticationScheme.POP
13905
+ ? AuthenticationScheme.POP
13906
+ : AuthenticationScheme.BEARER;
13907
+ const result = {
13908
+ authority: authority,
13909
+ uniqueId: uid,
13910
+ tenantId: tid,
13911
+ scopes: responseScopes.asArray(),
13912
+ account: accountInfo,
13913
+ idToken: response.id_token,
13914
+ idTokenClaims: idTokenClaims,
13915
+ accessToken: responseAccessToken,
13916
+ fromCache: mats ? this.isResponseFromCache(mats) : false,
13917
+ // Request timestamp and NativeResponse expires_in are in seconds, converting to Date for AuthenticationResult
13918
+ expiresOn: toDateFromSeconds(reqTimestamp + response.expires_in),
13919
+ tokenType: tokenType,
13892
13920
  correlationId: this.correlationId,
13893
- scopes: ScopeSet.fromString(request.scope).asArray(),
13894
- account: cachedAccount,
13895
- forceRefresh: false,
13921
+ state: response.state,
13922
+ fromNativeBroker: true,
13896
13923
  };
13924
+ return result;
13897
13925
  }
13898
13926
  /**
13899
- * Fetches the tokens from the cache if un-expired
13900
- * @param nativeAccountId
13901
- * @param request
13902
- * @returns authenticationResult
13927
+ * cache the account entity in browser storage
13928
+ * @param accountEntity
13903
13929
  */
13904
- async acquireTokensFromCache(nativeAccountId, request) {
13905
- if (!nativeAccountId) {
13906
- this.logger.warning("NativeInteractionClient:acquireTokensFromCache - No nativeAccountId provided");
13907
- throw createClientAuthError(noAccountFound);
13908
- }
13909
- // fetch the account from browser cache
13910
- const account = this.browserStorage.getBaseAccountInfo({
13911
- nativeAccountId,
13930
+ async cacheAccount(accountEntity) {
13931
+ // Store the account info and hence `nativeAccountId` in browser cache
13932
+ await this.browserStorage.setAccount(accountEntity, this.correlationId);
13933
+ // Remove any existing cached tokens for this account in browser storage
13934
+ this.browserStorage.removeAccountContext(accountEntity).catch((e) => {
13935
+ this.logger.error(`Error occurred while removing account context from browser storage. ${e}`);
13912
13936
  });
13913
- if (!account) {
13914
- throw createClientAuthError(noAccountFound);
13915
- }
13916
- // leverage silent flow for cached tokens retrieval
13917
- try {
13918
- const silentRequest = this.createSilentCacheRequest(request, account);
13919
- const result = await this.silentCacheClient.acquireToken(silentRequest);
13920
- const fullAccount = {
13921
- ...account,
13922
- idTokenClaims: result?.idTokenClaims,
13923
- idToken: result?.idToken,
13924
- };
13925
- return {
13926
- ...result,
13927
- account: fullAccount,
13928
- };
13929
- }
13930
- catch (e) {
13931
- throw e;
13932
- }
13933
13937
  }
13934
13938
  /**
13935
- * Acquires a token from native platform then redirects to the redirectUri instead of returning the response
13936
- * @param {RedirectRequest} request
13937
- * @param {InProgressPerformanceEvent} rootMeasurement
13939
+ * Stores the access_token and id_token in inmemory storage
13940
+ * @param response
13941
+ * @param request
13942
+ * @param homeAccountIdentifier
13943
+ * @param idTokenObj
13944
+ * @param responseAccessToken
13945
+ * @param tenantId
13946
+ * @param reqTimestamp
13938
13947
  */
13939
- async acquireTokenRedirect(request, rootMeasurement) {
13940
- this.logger.trace("NativeInteractionClient - acquireTokenRedirect called.");
13941
- const { ...remainingParameters } = request;
13942
- delete remainingParameters.onRedirectNavigate;
13943
- const nativeRequest = await this.initializeNativeRequest(remainingParameters);
13944
- const messageBody = {
13945
- method: NativeExtensionMethod.GetToken,
13946
- request: nativeRequest,
13948
+ cacheNativeTokens(response, request, homeAccountIdentifier, idTokenClaims, responseAccessToken, tenantId, reqTimestamp) {
13949
+ const cachedIdToken = createIdTokenEntity(homeAccountIdentifier, request.authority, response.id_token || "", request.clientId, idTokenClaims.tid || "");
13950
+ // cache accessToken in inmemory storage
13951
+ const expiresIn = request.tokenType === AuthenticationScheme.POP
13952
+ ? Constants.SHR_NONCE_VALIDITY
13953
+ : (typeof response.expires_in === "string"
13954
+ ? parseInt(response.expires_in, 10)
13955
+ : response.expires_in) || 0;
13956
+ const tokenExpirationSeconds = reqTimestamp + expiresIn;
13957
+ const responseScopes = this.generateScopes(response.scope, request.scope);
13958
+ const cachedAccessToken = createAccessTokenEntity(homeAccountIdentifier, request.authority, responseAccessToken, request.clientId, idTokenClaims.tid || tenantId, responseScopes.printScopes(), tokenExpirationSeconds, 0, base64Decode, undefined, request.tokenType, undefined, request.keyId);
13959
+ const nativeCacheRecord = {
13960
+ idToken: cachedIdToken,
13961
+ accessToken: cachedAccessToken,
13947
13962
  };
13948
- try {
13949
- const response = await this.nativeMessageHandler.sendMessage(messageBody);
13950
- this.validateNativeResponse(response);
13963
+ return this.nativeStorageManager.saveCacheRecord(nativeCacheRecord, this.correlationId, request.storeInCache);
13964
+ }
13965
+ getExpiresInValue(tokenType, expiresIn) {
13966
+ return tokenType === AuthenticationScheme.POP
13967
+ ? Constants.SHR_NONCE_VALIDITY
13968
+ : (typeof expiresIn === "string"
13969
+ ? parseInt(expiresIn, 10)
13970
+ : expiresIn) || 0;
13971
+ }
13972
+ addTelemetryFromNativeResponse(matsResponse) {
13973
+ const mats = this.getMATSFromResponse(matsResponse);
13974
+ if (!mats) {
13975
+ return null;
13951
13976
  }
13952
- catch (e) {
13953
- // Only throw fatal errors here to allow application to fallback to regular redirect. Otherwise proceed and the error will be thrown in handleRedirectPromise
13954
- if (e instanceof NativeAuthError) {
13955
- const serverTelemetryManager = this.initializeServerTelemetryManager(this.apiId);
13956
- serverTelemetryManager.setNativeBrokerErrorCode(e.errorCode);
13957
- if (isFatalNativeAuthError(e)) {
13958
- throw e;
13959
- }
13960
- }
13961
- }
13962
- this.browserStorage.setTemporaryCache(TemporaryCacheKeys.NATIVE_REQUEST, JSON.stringify(nativeRequest), true);
13963
- const navigationOptions = {
13964
- apiId: ApiId.acquireTokenRedirect,
13965
- timeout: this.config.system.redirectNavigationTimeout,
13966
- noHistory: false,
13967
- };
13968
- const redirectUri = this.config.auth.navigateToLoginRequestUrl
13969
- ? window.location.href
13970
- : this.getRedirectUri(request.redirectUri);
13971
- rootMeasurement.end({ success: true });
13972
- await this.navigationClient.navigateExternal(redirectUri, navigationOptions); // Need to treat this as external to ensure handleRedirectPromise is run again
13973
- }
13974
- /**
13975
- * If the previous page called native platform for a token using redirect APIs, send the same request again and return the response
13976
- * @param performanceClient {IPerformanceClient?}
13977
- * @param correlationId {string?} correlation identifier
13978
- */
13979
- async handleRedirectPromise(performanceClient, correlationId) {
13980
- this.logger.trace("NativeInteractionClient - handleRedirectPromise called.");
13981
- if (!this.browserStorage.isInteractionInProgress(true)) {
13982
- this.logger.info("handleRedirectPromise called but there is no interaction in progress, returning null.");
13983
- return null;
13984
- }
13985
- // remove prompt from the request to prevent WAM from prompting twice
13986
- const cachedRequest = this.browserStorage.getCachedNativeRequest();
13987
- if (!cachedRequest) {
13988
- this.logger.verbose("NativeInteractionClient - handleRedirectPromise called but there is no cached request, returning null.");
13989
- if (performanceClient && correlationId) {
13990
- performanceClient?.addFields({ errorCode: "no_cached_request" }, correlationId);
13991
- }
13992
- return null;
13993
- }
13994
- const { prompt, ...request } = cachedRequest;
13995
- if (prompt) {
13996
- 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.");
13997
- }
13998
- this.browserStorage.removeItem(this.browserStorage.generateCacheKey(TemporaryCacheKeys.NATIVE_REQUEST));
13999
- const messageBody = {
14000
- method: NativeExtensionMethod.GetToken,
14001
- request: request,
14002
- };
14003
- const reqTimestamp = nowSeconds();
14004
- try {
14005
- this.logger.verbose("NativeInteractionClient - handleRedirectPromise sending message to native broker.");
14006
- const response = await this.nativeMessageHandler.sendMessage(messageBody);
14007
- this.validateNativeResponse(response);
14008
- const result = this.handleNativeResponse(response, request, reqTimestamp);
14009
- const res = await result;
14010
- const serverTelemetryManager = this.initializeServerTelemetryManager(this.apiId);
14011
- serverTelemetryManager.clearNativeBrokerErrorCode();
14012
- return res;
14013
- }
14014
- catch (e) {
14015
- throw e;
14016
- }
14017
- }
14018
- /**
14019
- * Logout from native platform via browser extension
14020
- * @param request
14021
- */
14022
- logout() {
14023
- this.logger.trace("NativeInteractionClient - logout called.");
14024
- return Promise.reject("Logout not implemented yet");
14025
- }
14026
- /**
14027
- * Transform response from native platform into AuthenticationResult object which will be returned to the end user
14028
- * @param response
14029
- * @param request
14030
- * @param reqTimestamp
14031
- */
14032
- async handleNativeResponse(response, request, reqTimestamp) {
14033
- this.logger.trace("NativeInteractionClient - handleNativeResponse called.");
14034
- // generate identifiers
14035
- const idTokenClaims = extractTokenClaims(response.id_token, base64Decode);
14036
- const homeAccountIdentifier = this.createHomeAccountIdentifier(response, idTokenClaims);
14037
- const cachedhomeAccountId = this.browserStorage.getAccountInfoFilteredBy({
14038
- nativeAccountId: request.accountId,
14039
- })?.homeAccountId;
14040
- // add exception for double brokering, please note this is temporary and will be fortified in future
14041
- if (request.extraParameters?.child_client_id &&
14042
- response.account.id !== request.accountId) {
14043
- this.logger.info("handleNativeServerResponse: Double broker flow detected, ignoring accountId mismatch");
14044
- }
14045
- else if (homeAccountIdentifier !== cachedhomeAccountId &&
14046
- response.account.id !== request.accountId) {
14047
- // 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
14048
- throw createNativeAuthError(userSwitch);
14049
- }
14050
- // Get the preferred_cache domain for the given authority
14051
- const authority = await this.getDiscoveredAuthority({
14052
- requestAuthority: request.authority,
14053
- });
14054
- const baseAccount = buildAccountToCache(this.browserStorage, authority, homeAccountIdentifier, base64Decode, idTokenClaims, response.client_info, undefined, // environment
14055
- idTokenClaims.tid, undefined, // auth code payload
14056
- response.account.id, this.logger);
14057
- // Ensure expires_in is in number format
14058
- response.expires_in = Number(response.expires_in);
14059
- // generate authenticationResult
14060
- const result = await this.generateAuthenticationResult(response, request, idTokenClaims, baseAccount, authority.canonicalAuthority, reqTimestamp);
14061
- // cache accounts and tokens in the appropriate storage
14062
- await this.cacheAccount(baseAccount);
14063
- await this.cacheNativeTokens(response, request, homeAccountIdentifier, idTokenClaims, response.access_token, result.tenantId, reqTimestamp);
14064
- return result;
13977
+ this.performanceClient.addFields({
13978
+ extensionId: this.platformAuthProvider.getExtensionId(),
13979
+ extensionVersion: this.platformAuthProvider.getExtensionVersion(),
13980
+ matsBrokerVersion: mats.broker_version,
13981
+ matsAccountJoinOnStart: mats.account_join_on_start,
13982
+ matsAccountJoinOnEnd: mats.account_join_on_end,
13983
+ matsDeviceJoin: mats.device_join,
13984
+ matsPromptBehavior: mats.prompt_behavior,
13985
+ matsApiErrorCode: mats.api_error_code,
13986
+ matsUiVisible: mats.ui_visible,
13987
+ matsSilentCode: mats.silent_code,
13988
+ matsSilentBiSubCode: mats.silent_bi_sub_code,
13989
+ matsSilentMessage: mats.silent_message,
13990
+ matsSilentStatus: mats.silent_status,
13991
+ matsHttpStatus: mats.http_status,
13992
+ matsHttpEventCount: mats.http_event_count,
13993
+ }, this.correlationId);
13994
+ return mats;
14065
13995
  }
14066
13996
  /**
14067
- * creates an homeAccountIdentifier for the account
13997
+ * Gets MATS telemetry from native response
14068
13998
  * @param response
14069
- * @param idTokenObj
14070
13999
  * @returns
14071
14000
  */
14072
- createHomeAccountIdentifier(response, idTokenClaims) {
14073
- // Save account in browser storage
14074
- const homeAccountIdentifier = AccountEntity.generateHomeAccountId(response.client_info || Constants.EMPTY_STRING, AuthorityType.Default, this.logger, this.browserCrypto, idTokenClaims);
14075
- return homeAccountIdentifier;
14001
+ getMATSFromResponse(matsResponse) {
14002
+ if (matsResponse) {
14003
+ try {
14004
+ return JSON.parse(matsResponse);
14005
+ }
14006
+ catch (e) {
14007
+ this.logger.error("NativeInteractionClient - Error parsing MATS telemetry, returning null instead");
14008
+ }
14009
+ }
14010
+ return null;
14076
14011
  }
14077
14012
  /**
14078
- * Helper to generate scopes
14013
+ * Returns whether or not response came from native cache
14079
14014
  * @param response
14080
- * @param request
14081
14015
  * @returns
14082
14016
  */
14083
- generateScopes(response, request) {
14084
- return response.scope
14085
- ? ScopeSet.fromString(response.scope)
14086
- : ScopeSet.fromString(request.scope);
14017
+ isResponseFromCache(mats) {
14018
+ if (typeof mats.is_cached === "undefined") {
14019
+ this.logger.verbose("NativeInteractionClient - MATS telemetry does not contain field indicating if response was served from cache. Returning false.");
14020
+ return false;
14021
+ }
14022
+ return !!mats.is_cached;
14087
14023
  }
14088
14024
  /**
14089
- * If PoP token is requesred, records the PoP token if returned from the WAM, else generates one in the browser
14025
+ * Translates developer provided request object into NativeRequest object
14090
14026
  * @param request
14091
- * @param response
14092
14027
  */
14093
- async generatePopAccessToken(response, request) {
14094
- if (request.tokenType === AuthenticationScheme.POP &&
14095
- request.signPopToken) {
14096
- /**
14097
- * This code prioritizes SHR returned from the native layer. In case of error/SHR not calculated from WAM and the AT
14098
- * is still received, SHR is calculated locally
14099
- */
14100
- // Check if native layer returned an SHR token
14101
- if (response.shr) {
14102
- this.logger.trace("handleNativeServerResponse: SHR is enabled in native layer");
14103
- return response.shr;
14104
- }
14105
- // Generate SHR in msal js if WAM does not compute it when POP is enabled
14106
- const popTokenGenerator = new PopTokenGenerator(this.browserCrypto);
14028
+ async initializeNativeRequest(request) {
14029
+ this.logger.trace("NativeInteractionClient - initializeNativeRequest called");
14030
+ const canonicalAuthority = await this.getCanonicalAuthority(request);
14031
+ // 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.
14032
+ const { scopes, ...remainingProperties } = request;
14033
+ const scopeSet = new ScopeSet(scopes || []);
14034
+ scopeSet.appendScopes(OIDC_DEFAULT_SCOPES);
14035
+ const validatedRequest = {
14036
+ ...remainingProperties,
14037
+ accountId: this.accountId,
14038
+ clientId: this.config.auth.clientId,
14039
+ authority: canonicalAuthority.urlString,
14040
+ scope: scopeSet.printScopes(),
14041
+ redirectUri: this.getRedirectUri(request.redirectUri),
14042
+ prompt: this.getPrompt(request.prompt),
14043
+ correlationId: this.correlationId,
14044
+ tokenType: request.authenticationScheme,
14045
+ windowTitleSubstring: document.title,
14046
+ extraParameters: {
14047
+ ...request.extraQueryParameters,
14048
+ ...request.tokenQueryParameters,
14049
+ },
14050
+ extendedExpiryToken: false,
14051
+ keyId: request.popKid,
14052
+ };
14053
+ // Check for PoP token requests: signPopToken should only be set to true if popKid is not set
14054
+ if (validatedRequest.signPopToken && !!request.popKid) {
14055
+ throw createBrowserAuthError(invalidPopTokenRequest);
14056
+ }
14057
+ this.handleExtraBrokerParams(validatedRequest);
14058
+ validatedRequest.extraParameters =
14059
+ validatedRequest.extraParameters || {};
14060
+ validatedRequest.extraParameters.telemetry =
14061
+ PlatformAuthConstants.MATS_TELEMETRY;
14062
+ if (request.authenticationScheme === AuthenticationScheme.POP) {
14063
+ // add POP request type
14107
14064
  const shrParameters = {
14108
- resourceRequestMethod: request.resourceRequestMethod,
14109
14065
  resourceRequestUri: request.resourceRequestUri,
14066
+ resourceRequestMethod: request.resourceRequestMethod,
14110
14067
  shrClaims: request.shrClaims,
14111
14068
  shrNonce: request.shrNonce,
14112
14069
  };
14113
- /**
14114
- * KeyID must be present in the native request from when the PoP key was generated in order for
14115
- * PopTokenGenerator to query the full key for signing
14116
- */
14117
- if (!request.keyId) {
14118
- throw createClientAuthError(keyIdMissing);
14070
+ const popTokenGenerator = new PopTokenGenerator(this.browserCrypto);
14071
+ // generate reqCnf if not provided in the request
14072
+ let reqCnfData;
14073
+ if (!validatedRequest.keyId) {
14074
+ const generatedReqCnfData = await invokeAsync(popTokenGenerator.generateCnf.bind(popTokenGenerator), PerformanceEvents.PopTokenGenerateCnf, this.logger, this.performanceClient, request.correlationId)(shrParameters, this.logger);
14075
+ reqCnfData = generatedReqCnfData.reqCnfString;
14076
+ validatedRequest.keyId = generatedReqCnfData.kid;
14077
+ validatedRequest.signPopToken = true;
14119
14078
  }
14120
- return popTokenGenerator.signPopToken(response.access_token, request.keyId, shrParameters);
14079
+ else {
14080
+ reqCnfData = this.browserCrypto.base64UrlEncode(JSON.stringify({ kid: validatedRequest.keyId }));
14081
+ validatedRequest.signPopToken = false;
14082
+ }
14083
+ // SPAs require whole string to be passed to broker
14084
+ validatedRequest.reqCnf = reqCnfData;
14121
14085
  }
14122
- else {
14123
- return response.access_token;
14086
+ this.addRequestSKUs(validatedRequest);
14087
+ return validatedRequest;
14088
+ }
14089
+ async getCanonicalAuthority(request) {
14090
+ const requestAuthority = request.authority || this.config.auth.authority;
14091
+ if (request.account) {
14092
+ // validate authority
14093
+ await this.getDiscoveredAuthority({
14094
+ requestAuthority,
14095
+ requestAzureCloudOptions: request.azureCloudOptions,
14096
+ account: request.account,
14097
+ });
14098
+ }
14099
+ const canonicalAuthority = new UrlString(requestAuthority);
14100
+ canonicalAuthority.validateAsUri();
14101
+ return canonicalAuthority;
14102
+ }
14103
+ getPrompt(prompt) {
14104
+ // If request is silent, prompt is always none
14105
+ switch (this.apiId) {
14106
+ case ApiId.ssoSilent:
14107
+ case ApiId.acquireTokenSilent_silentFlow:
14108
+ this.logger.trace("initializeNativeRequest: silent request sets prompt to none");
14109
+ return PromptValue.NONE;
14110
+ }
14111
+ // Prompt not provided, request may proceed and native broker decides if it needs to prompt
14112
+ if (!prompt) {
14113
+ this.logger.trace("initializeNativeRequest: prompt was not provided");
14114
+ return undefined;
14115
+ }
14116
+ // If request is interactive, check if prompt provided is allowed to go directly to native broker
14117
+ switch (prompt) {
14118
+ case PromptValue.NONE:
14119
+ case PromptValue.CONSENT:
14120
+ case PromptValue.LOGIN:
14121
+ this.logger.trace("initializeNativeRequest: prompt is compatible with native flow");
14122
+ return prompt;
14123
+ default:
14124
+ this.logger.trace(`initializeNativeRequest: prompt = ${prompt} is not compatible with native flow`);
14125
+ throw createBrowserAuthError(nativePromptNotSupported);
14124
14126
  }
14125
14127
  }
14126
14128
  /**
14127
- * Generates authentication result
14128
- * @param response
14129
- * @param request
14130
- * @param idTokenObj
14131
- * @param accountEntity
14132
- * @param authority
14133
- * @param reqTimestamp
14134
- * @returns
14129
+ * Handles extra broker request parameters
14130
+ * @param request {PlatformAuthRequest}
14131
+ * @private
14135
14132
  */
14136
- async generateAuthenticationResult(response, request, idTokenClaims, accountEntity, authority, reqTimestamp) {
14137
- // Add Native Broker fields to Telemetry
14138
- const mats = this.addTelemetryFromNativeResponse(response);
14139
- // If scopes not returned in server response, use request scopes
14140
- const responseScopes = response.scope
14141
- ? ScopeSet.fromString(response.scope)
14142
- : ScopeSet.fromString(request.scope);
14143
- const accountProperties = response.account.properties || {};
14144
- const uid = accountProperties["UID"] ||
14145
- idTokenClaims.oid ||
14146
- idTokenClaims.sub ||
14147
- Constants.EMPTY_STRING;
14148
- const tid = accountProperties["TenantId"] ||
14149
- idTokenClaims.tid ||
14150
- Constants.EMPTY_STRING;
14151
- const accountInfo = updateAccountTenantProfileData(accountEntity.getAccountInfo(), undefined, // tenantProfile optional
14152
- idTokenClaims, response.id_token);
14153
- /**
14154
- * In pairwise broker flows, this check prevents the broker's native account id
14155
- * from being returned over the embedded app's account id.
14156
- */
14157
- if (accountInfo.nativeAccountId !== response.account.id) {
14158
- accountInfo.nativeAccountId = response.account.id;
14133
+ handleExtraBrokerParams(request) {
14134
+ const hasExtraBrokerParams = request.extraParameters &&
14135
+ request.extraParameters.hasOwnProperty(BROKER_CLIENT_ID) &&
14136
+ request.extraParameters.hasOwnProperty(BROKER_REDIRECT_URI) &&
14137
+ request.extraParameters.hasOwnProperty(CLIENT_ID);
14138
+ if (!request.embeddedClientId && !hasExtraBrokerParams) {
14139
+ return;
14159
14140
  }
14160
- // generate PoP token as needed
14161
- const responseAccessToken = await this.generatePopAccessToken(response, request);
14162
- const tokenType = request.tokenType === AuthenticationScheme.POP
14163
- ? AuthenticationScheme.POP
14164
- : AuthenticationScheme.BEARER;
14165
- const result = {
14166
- authority: authority,
14167
- uniqueId: uid,
14168
- tenantId: tid,
14169
- scopes: responseScopes.asArray(),
14170
- account: accountInfo,
14171
- idToken: response.id_token,
14172
- idTokenClaims: idTokenClaims,
14173
- accessToken: responseAccessToken,
14174
- fromCache: mats ? this.isResponseFromCache(mats) : false,
14175
- // Request timestamp and NativeResponse expires_in are in seconds, converting to Date for AuthenticationResult
14176
- expiresOn: toDateFromSeconds(reqTimestamp + response.expires_in),
14177
- tokenType: tokenType,
14178
- correlationId: this.correlationId,
14179
- state: response.state,
14180
- fromNativeBroker: true,
14141
+ let child_client_id = "";
14142
+ const child_redirect_uri = request.redirectUri;
14143
+ if (request.embeddedClientId) {
14144
+ request.redirectUri = this.config.auth.redirectUri;
14145
+ child_client_id = request.embeddedClientId;
14146
+ }
14147
+ else if (request.extraParameters) {
14148
+ request.redirectUri =
14149
+ request.extraParameters[BROKER_REDIRECT_URI];
14150
+ child_client_id =
14151
+ request.extraParameters[CLIENT_ID];
14152
+ }
14153
+ request.extraParameters = {
14154
+ child_client_id,
14155
+ child_redirect_uri,
14181
14156
  };
14182
- return result;
14157
+ this.performanceClient?.addFields({
14158
+ embeddedClientId: child_client_id,
14159
+ embeddedRedirectUri: child_redirect_uri,
14160
+ }, request.correlationId);
14161
+ }
14162
+ }
14163
+
14164
+ /*
14165
+ * Copyright (c) Microsoft Corporation. All rights reserved.
14166
+ * Licensed under the MIT License.
14167
+ */
14168
+ /**
14169
+ * Returns map of parameters that are applicable to all calls to /authorize whether using PKCE or EAR
14170
+ * @param config
14171
+ * @param authority
14172
+ * @param request
14173
+ * @param logger
14174
+ * @param performanceClient
14175
+ * @returns
14176
+ */
14177
+ async function getStandardParameters(config, authority, request, logger, performanceClient) {
14178
+ const parameters = getStandardAuthorizeRequestParameters({ ...config.auth, authority: authority }, request, logger, performanceClient);
14179
+ addLibraryInfo(parameters, {
14180
+ sku: BrowserConstants.MSAL_SKU,
14181
+ version: version,
14182
+ os: "",
14183
+ cpu: "",
14184
+ });
14185
+ if (config.auth.protocolMode !== ProtocolMode.OIDC) {
14186
+ addApplicationTelemetry(parameters, config.telemetry.application);
14187
+ }
14188
+ if (request.platformBroker) {
14189
+ // signal ests that this is a WAM call
14190
+ addNativeBroker(parameters);
14191
+ // pass the req_cnf for POP
14192
+ if (request.authenticationScheme === AuthenticationScheme.POP) {
14193
+ const cryptoOps = new CryptoOps(logger, performanceClient);
14194
+ const popTokenGenerator = new PopTokenGenerator(cryptoOps);
14195
+ // req_cnf is always sent as a string for SPAs
14196
+ let reqCnfData;
14197
+ if (!request.popKid) {
14198
+ const generatedReqCnfData = await invokeAsync(popTokenGenerator.generateCnf.bind(popTokenGenerator), PerformanceEvents.PopTokenGenerateCnf, logger, performanceClient, request.correlationId)(request, logger);
14199
+ reqCnfData = generatedReqCnfData.reqCnfString;
14200
+ }
14201
+ else {
14202
+ reqCnfData = cryptoOps.encodeKid(request.popKid);
14203
+ }
14204
+ addPopToken(parameters, reqCnfData);
14205
+ }
14206
+ }
14207
+ instrumentBrokerParams(parameters, request.correlationId, performanceClient);
14208
+ return parameters;
14209
+ }
14210
+ /**
14211
+ * Gets the full /authorize URL with request parameters when using Auth Code + PKCE
14212
+ * @param config
14213
+ * @param authority
14214
+ * @param request
14215
+ * @param logger
14216
+ * @param performanceClient
14217
+ * @returns
14218
+ */
14219
+ async function getAuthCodeRequestUrl(config, authority, request, logger, performanceClient) {
14220
+ if (!request.codeChallenge) {
14221
+ throw createClientConfigurationError(pkceParamsMissing);
14222
+ }
14223
+ const parameters = await invokeAsync(getStandardParameters, PerformanceEvents.GetStandardParams, logger, performanceClient, request.correlationId)(config, authority, request, logger, performanceClient);
14224
+ addResponseType(parameters, OAuthResponseType.CODE);
14225
+ addCodeChallengeParams(parameters, request.codeChallenge, Constants.S256_CODE_CHALLENGE_METHOD);
14226
+ addExtraQueryParameters(parameters, request.extraQueryParameters || {});
14227
+ return getAuthorizeUrl(authority, parameters, config.auth.encodeExtraQueryParams, request.extraQueryParameters);
14228
+ }
14229
+ /**
14230
+ * Gets the form that will be posted to /authorize with request parameters when using EAR
14231
+ */
14232
+ async function getEARForm(frame, config, authority, request, logger, performanceClient) {
14233
+ if (!request.earJwk) {
14234
+ throw createBrowserAuthError(earJwkEmpty);
14235
+ }
14236
+ const parameters = await getStandardParameters(config, authority, request, logger, performanceClient);
14237
+ addResponseType(parameters, OAuthResponseType.IDTOKEN_TOKEN_REFRESHTOKEN);
14238
+ addEARParameters(parameters, request.earJwk);
14239
+ const queryParams = new Map();
14240
+ addExtraQueryParameters(queryParams, request.extraQueryParameters || {});
14241
+ const url = getAuthorizeUrl(authority, queryParams, config.auth.encodeExtraQueryParams, request.extraQueryParameters);
14242
+ return createForm(frame, url, parameters);
14243
+ }
14244
+ /**
14245
+ * Creates form element in the provided document with auth parameters in the post body
14246
+ * @param frame
14247
+ * @param authorizeUrl
14248
+ * @param parameters
14249
+ * @returns
14250
+ */
14251
+ function createForm(frame, authorizeUrl, parameters) {
14252
+ const form = frame.createElement("form");
14253
+ form.method = "post";
14254
+ form.action = authorizeUrl;
14255
+ parameters.forEach((value, key) => {
14256
+ const param = frame.createElement("input");
14257
+ param.hidden = true;
14258
+ param.name = key;
14259
+ param.value = value;
14260
+ form.appendChild(param);
14261
+ });
14262
+ frame.body.appendChild(form);
14263
+ return form;
14264
+ }
14265
+ /**
14266
+ * Response handler when server returns accountId on the /authorize request
14267
+ * @param request
14268
+ * @param accountId
14269
+ * @param apiId
14270
+ * @param config
14271
+ * @param browserStorage
14272
+ * @param nativeStorage
14273
+ * @param eventHandler
14274
+ * @param logger
14275
+ * @param performanceClient
14276
+ * @param nativeMessageHandler
14277
+ * @returns
14278
+ */
14279
+ async function handleResponsePlatformBroker(request, accountId, apiId, config, browserStorage, nativeStorage, eventHandler, logger, performanceClient, platformAuthProvider) {
14280
+ logger.verbose("Account id found, calling WAM for token");
14281
+ if (!platformAuthProvider) {
14282
+ throw createBrowserAuthError(nativeConnectionNotEstablished);
14283
+ }
14284
+ const browserCrypto = new CryptoOps(logger, performanceClient);
14285
+ const nativeInteractionClient = new PlatformAuthInteractionClient(config, browserStorage, browserCrypto, logger, eventHandler, config.system.navigationClient, apiId, performanceClient, platformAuthProvider, accountId, nativeStorage, request.correlationId);
14286
+ const { userRequestState } = ProtocolUtils.parseRequestState(browserCrypto, request.state);
14287
+ return invokeAsync(nativeInteractionClient.acquireToken.bind(nativeInteractionClient), PerformanceEvents.NativeInteractionClientAcquireToken, logger, performanceClient, request.correlationId)({
14288
+ ...request,
14289
+ state: userRequestState,
14290
+ prompt: undefined, // Server should handle the prompt, ideally native broker can do this part silently
14291
+ });
14292
+ }
14293
+ /**
14294
+ * Response handler when server returns code on the /authorize request
14295
+ * @param request
14296
+ * @param response
14297
+ * @param codeVerifier
14298
+ * @param authClient
14299
+ * @param browserStorage
14300
+ * @param logger
14301
+ * @param performanceClient
14302
+ * @returns
14303
+ */
14304
+ async function handleResponseCode(request, response, codeVerifier, apiId, config, authClient, browserStorage, nativeStorage, eventHandler, logger, performanceClient, platformAuthProvider) {
14305
+ // Remove throttle if it exists
14306
+ ThrottlingUtils.removeThrottle(browserStorage, config.auth.clientId, request);
14307
+ if (response.accountId) {
14308
+ return invokeAsync(handleResponsePlatformBroker, PerformanceEvents.HandleResponsePlatformBroker, logger, performanceClient, request.correlationId)(request, response.accountId, apiId, config, browserStorage, nativeStorage, eventHandler, logger, performanceClient, platformAuthProvider);
14309
+ }
14310
+ const authCodeRequest = {
14311
+ ...request,
14312
+ code: response.code || "",
14313
+ codeVerifier: codeVerifier,
14314
+ };
14315
+ // Create popup interaction handler.
14316
+ const interactionHandler = new InteractionHandler(authClient, browserStorage, authCodeRequest, logger, performanceClient);
14317
+ // Handle response from hash string.
14318
+ const result = await invokeAsync(interactionHandler.handleCodeResponse.bind(interactionHandler), PerformanceEvents.HandleCodeResponse, logger, performanceClient, request.correlationId)(response, request);
14319
+ return result;
14320
+ }
14321
+ /**
14322
+ * Response handler when server returns ear_jwe on the /authorize request
14323
+ * @param request
14324
+ * @param response
14325
+ * @param apiId
14326
+ * @param config
14327
+ * @param authority
14328
+ * @param browserStorage
14329
+ * @param nativeStorage
14330
+ * @param eventHandler
14331
+ * @param logger
14332
+ * @param performanceClient
14333
+ * @param nativeMessageHandler
14334
+ * @returns
14335
+ */
14336
+ async function handleResponseEAR(request, response, apiId, config, authority, browserStorage, nativeStorage, eventHandler, logger, performanceClient, platformAuthProvider) {
14337
+ // Remove throttle if it exists
14338
+ ThrottlingUtils.removeThrottle(browserStorage, config.auth.clientId, request);
14339
+ // Validate state & check response for errors
14340
+ validateAuthorizationResponse(response, request.state);
14341
+ if (!response.ear_jwe) {
14342
+ throw createBrowserAuthError(earJweEmpty);
14343
+ }
14344
+ if (!request.earJwk) {
14345
+ throw createBrowserAuthError(earJwkEmpty);
14346
+ }
14347
+ const decryptedData = JSON.parse(await invokeAsync(decryptEarResponse, PerformanceEvents.DecryptEarResponse, logger, performanceClient, request.correlationId)(request.earJwk, response.ear_jwe));
14348
+ if (decryptedData.accountId) {
14349
+ return invokeAsync(handleResponsePlatformBroker, PerformanceEvents.HandleResponsePlatformBroker, logger, performanceClient, request.correlationId)(request, decryptedData.accountId, apiId, config, browserStorage, nativeStorage, eventHandler, logger, performanceClient, platformAuthProvider);
14350
+ }
14351
+ const responseHandler = new ResponseHandler(config.auth.clientId, browserStorage, new CryptoOps(logger, performanceClient), logger, null, null, performanceClient);
14352
+ // Validate response. This function throws a server error if an error is returned by the server.
14353
+ responseHandler.validateTokenResponse(decryptedData);
14354
+ // Temporary until response handler is refactored to be more flow agnostic.
14355
+ const additionalData = {
14356
+ code: "",
14357
+ state: request.state,
14358
+ nonce: request.nonce,
14359
+ client_info: decryptedData.client_info,
14360
+ cloud_graph_host_name: decryptedData.cloud_graph_host_name,
14361
+ cloud_instance_host_name: decryptedData.cloud_instance_host_name,
14362
+ cloud_instance_name: decryptedData.cloud_instance_name,
14363
+ msgraph_host: decryptedData.msgraph_host,
14364
+ };
14365
+ return (await invokeAsync(responseHandler.handleServerTokenResponse.bind(responseHandler), PerformanceEvents.HandleServerTokenResponse, logger, performanceClient, request.correlationId)(decryptedData, authority, nowSeconds(), request, additionalData, undefined, undefined, undefined, undefined));
14366
+ }
14367
+
14368
+ /*
14369
+ * Copyright (c) Microsoft Corporation. All rights reserved.
14370
+ * Licensed under the MIT License.
14371
+ */
14372
+ // Constant byte array length
14373
+ const RANDOM_BYTE_ARR_LENGTH = 32;
14374
+ /**
14375
+ * This file defines APIs to generate PKCE codes and code verifiers.
14376
+ */
14377
+ /**
14378
+ * Generates PKCE Codes. See the RFC for more information: https://tools.ietf.org/html/rfc7636
14379
+ */
14380
+ async function generatePkceCodes(performanceClient, logger, correlationId) {
14381
+ performanceClient.addQueueMeasurement(PerformanceEvents.GeneratePkceCodes, correlationId);
14382
+ const codeVerifier = invoke(generateCodeVerifier, PerformanceEvents.GenerateCodeVerifier, logger, performanceClient, correlationId)(performanceClient, logger, correlationId);
14383
+ const codeChallenge = await invokeAsync(generateCodeChallengeFromVerifier, PerformanceEvents.GenerateCodeChallengeFromVerifier, logger, performanceClient, correlationId)(codeVerifier, performanceClient, logger, correlationId);
14384
+ return {
14385
+ verifier: codeVerifier,
14386
+ challenge: codeChallenge,
14387
+ };
14388
+ }
14389
+ /**
14390
+ * Generates a random 32 byte buffer and returns the base64
14391
+ * encoded string to be used as a PKCE Code Verifier
14392
+ */
14393
+ function generateCodeVerifier(performanceClient, logger, correlationId) {
14394
+ try {
14395
+ // Generate random values as utf-8
14396
+ const buffer = new Uint8Array(RANDOM_BYTE_ARR_LENGTH);
14397
+ invoke(getRandomValues, PerformanceEvents.GetRandomValues, logger, performanceClient, correlationId)(buffer);
14398
+ // encode verifier as base64
14399
+ const pkceCodeVerifierB64 = urlEncodeArr(buffer);
14400
+ return pkceCodeVerifierB64;
14401
+ }
14402
+ catch (e) {
14403
+ throw createBrowserAuthError(pkceNotCreated);
14404
+ }
14405
+ }
14406
+ /**
14407
+ * Creates a base64 encoded PKCE Code Challenge string from the
14408
+ * hash created from the PKCE Code Verifier supplied
14409
+ */
14410
+ async function generateCodeChallengeFromVerifier(pkceCodeVerifier, performanceClient, logger, correlationId) {
14411
+ performanceClient.addQueueMeasurement(PerformanceEvents.GenerateCodeChallengeFromVerifier, correlationId);
14412
+ try {
14413
+ // hashed verifier
14414
+ const pkceHashedCodeVerifier = await invokeAsync(sha256Digest, PerformanceEvents.Sha256Digest, logger, performanceClient, correlationId)(pkceCodeVerifier, performanceClient, correlationId);
14415
+ // encode hash as base64
14416
+ return urlEncodeArr(new Uint8Array(pkceHashedCodeVerifier));
14417
+ }
14418
+ catch (e) {
14419
+ throw createBrowserAuthError(pkceNotCreated);
14420
+ }
14421
+ }
14422
+
14423
+ /*
14424
+ * Copyright (c) Microsoft Corporation. All rights reserved.
14425
+ * Licensed under the MIT License.
14426
+ */
14427
+ class PlatformAuthExtensionHandler {
14428
+ constructor(logger, handshakeTimeoutMs, performanceClient, extensionId) {
14429
+ this.logger = logger;
14430
+ this.handshakeTimeoutMs = handshakeTimeoutMs;
14431
+ this.extensionId = extensionId;
14432
+ this.resolvers = new Map(); // Used for non-handshake messages
14433
+ this.handshakeResolvers = new Map(); // Used for handshake messages
14434
+ this.messageChannel = new MessageChannel();
14435
+ this.windowListener = this.onWindowMessage.bind(this); // Window event callback doesn't have access to 'this' unless it's bound
14436
+ this.performanceClient = performanceClient;
14437
+ this.handshakeEvent = performanceClient.startMeasurement(PerformanceEvents.NativeMessageHandlerHandshake);
14438
+ this.platformAuthType =
14439
+ PlatformAuthConstants.PLATFORM_EXTENSION_PROVIDER;
14183
14440
  }
14184
14441
  /**
14185
- * cache the account entity in browser storage
14186
- * @param accountEntity
14442
+ * Sends a given message to the extension and resolves with the extension response
14443
+ * @param request
14187
14444
  */
14188
- async cacheAccount(accountEntity) {
14189
- // Store the account info and hence `nativeAccountId` in browser cache
14190
- await this.browserStorage.setAccount(accountEntity, this.correlationId);
14191
- // Remove any existing cached tokens for this account in browser storage
14192
- this.browserStorage.removeAccountContext(accountEntity).catch((e) => {
14193
- this.logger.error(`Error occurred while removing account context from browser storage. ${e}`);
14445
+ async sendMessage(request) {
14446
+ this.logger.trace(this.platformAuthType + " - sendMessage called.");
14447
+ // fall back to native calls
14448
+ const messageBody = {
14449
+ method: NativeExtensionMethod.GetToken,
14450
+ request: request,
14451
+ };
14452
+ const req = {
14453
+ channel: PlatformAuthConstants.CHANNEL_ID,
14454
+ extensionId: this.extensionId,
14455
+ responseId: createNewGuid(),
14456
+ body: messageBody,
14457
+ };
14458
+ this.logger.trace(this.platformAuthType + " - Sending request to browser extension");
14459
+ this.logger.tracePii(this.platformAuthType +
14460
+ ` - Sending request to browser extension: ${JSON.stringify(req)}`);
14461
+ this.messageChannel.port1.postMessage(req);
14462
+ const response = await new Promise((resolve, reject) => {
14463
+ this.resolvers.set(req.responseId, { resolve, reject });
14194
14464
  });
14465
+ const validatedResponse = this.validatePlatformBrokerResponse(response);
14466
+ return validatedResponse;
14195
14467
  }
14196
14468
  /**
14197
- * Stores the access_token and id_token in inmemory storage
14198
- * @param response
14199
- * @param request
14200
- * @param homeAccountIdentifier
14201
- * @param idTokenObj
14202
- * @param responseAccessToken
14203
- * @param tenantId
14204
- * @param reqTimestamp
14469
+ * Returns an instance of the MessageHandler that has successfully established a connection with an extension
14470
+ * @param {Logger} logger
14471
+ * @param {number} handshakeTimeoutMs
14472
+ * @param {IPerformanceClient} performanceClient
14473
+ * @param {ICrypto} crypto
14205
14474
  */
14206
- cacheNativeTokens(response, request, homeAccountIdentifier, idTokenClaims, responseAccessToken, tenantId, reqTimestamp) {
14207
- const cachedIdToken = createIdTokenEntity(homeAccountIdentifier, request.authority, response.id_token || "", request.clientId, idTokenClaims.tid || "");
14208
- // cache accessToken in inmemory storage
14209
- const expiresIn = request.tokenType === AuthenticationScheme.POP
14210
- ? Constants.SHR_NONCE_VALIDITY
14211
- : (typeof response.expires_in === "string"
14212
- ? parseInt(response.expires_in, 10)
14213
- : response.expires_in) || 0;
14214
- const tokenExpirationSeconds = reqTimestamp + expiresIn;
14215
- const responseScopes = this.generateScopes(response, request);
14216
- const cachedAccessToken = createAccessTokenEntity(homeAccountIdentifier, request.authority, responseAccessToken, request.clientId, idTokenClaims.tid || tenantId, responseScopes.printScopes(), tokenExpirationSeconds, 0, base64Decode, undefined, request.tokenType, undefined, request.keyId);
14217
- const nativeCacheRecord = {
14218
- idToken: cachedIdToken,
14219
- accessToken: cachedAccessToken,
14475
+ static async createProvider(logger, handshakeTimeoutMs, performanceClient) {
14476
+ logger.trace("PlatformAuthExtensionHandler - createProvider called.");
14477
+ try {
14478
+ const preferredProvider = new PlatformAuthExtensionHandler(logger, handshakeTimeoutMs, performanceClient, PlatformAuthConstants.PREFERRED_EXTENSION_ID);
14479
+ await preferredProvider.sendHandshakeRequest();
14480
+ return preferredProvider;
14481
+ }
14482
+ catch (e) {
14483
+ // If preferred extension fails for whatever reason, fallback to using any installed extension
14484
+ const backupProvider = new PlatformAuthExtensionHandler(logger, handshakeTimeoutMs, performanceClient);
14485
+ await backupProvider.sendHandshakeRequest();
14486
+ return backupProvider;
14487
+ }
14488
+ }
14489
+ /**
14490
+ * Send handshake request helper.
14491
+ */
14492
+ async sendHandshakeRequest() {
14493
+ this.logger.trace(this.platformAuthType + " - sendHandshakeRequest called.");
14494
+ // Register this event listener before sending handshake
14495
+ window.addEventListener("message", this.windowListener, false); // false is important, because content script message processing should work first
14496
+ const req = {
14497
+ channel: PlatformAuthConstants.CHANNEL_ID,
14498
+ extensionId: this.extensionId,
14499
+ responseId: createNewGuid(),
14500
+ body: {
14501
+ method: NativeExtensionMethod.HandshakeRequest,
14502
+ },
14220
14503
  };
14221
- return this.nativeStorageManager.saveCacheRecord(nativeCacheRecord, this.correlationId, request.storeInCache);
14504
+ this.handshakeEvent.add({
14505
+ extensionId: this.extensionId,
14506
+ extensionHandshakeTimeoutMs: this.handshakeTimeoutMs,
14507
+ });
14508
+ this.messageChannel.port1.onmessage = (event) => {
14509
+ this.onChannelMessage(event);
14510
+ };
14511
+ window.postMessage(req, window.origin, [this.messageChannel.port2]);
14512
+ return new Promise((resolve, reject) => {
14513
+ this.handshakeResolvers.set(req.responseId, { resolve, reject });
14514
+ this.timeoutId = window.setTimeout(() => {
14515
+ /*
14516
+ * Throw an error if neither HandshakeResponse nor original Handshake request are received in a reasonable timeframe.
14517
+ * This typically suggests an event handler stopped propagation of the Handshake request but did not respond to it on the MessageChannel port
14518
+ */
14519
+ window.removeEventListener("message", this.windowListener, false);
14520
+ this.messageChannel.port1.close();
14521
+ this.messageChannel.port2.close();
14522
+ this.handshakeEvent.end({
14523
+ extensionHandshakeTimedOut: true,
14524
+ success: false,
14525
+ });
14526
+ reject(createBrowserAuthError(nativeHandshakeTimeout));
14527
+ this.handshakeResolvers.delete(req.responseId);
14528
+ }, this.handshakeTimeoutMs); // Use a reasonable timeout in milliseconds here
14529
+ });
14222
14530
  }
14223
- addTelemetryFromNativeResponse(response) {
14224
- const mats = this.getMATSFromResponse(response);
14225
- if (!mats) {
14226
- return null;
14531
+ /**
14532
+ * Invoked when a message is posted to the window. If a handshake request is received it means the extension is not installed.
14533
+ * @param event
14534
+ */
14535
+ onWindowMessage(event) {
14536
+ this.logger.trace(this.platformAuthType + " - onWindowMessage called");
14537
+ // We only accept messages from ourselves
14538
+ if (event.source !== window) {
14539
+ return;
14540
+ }
14541
+ const request = event.data;
14542
+ if (!request.channel ||
14543
+ request.channel !== PlatformAuthConstants.CHANNEL_ID) {
14544
+ return;
14545
+ }
14546
+ if (request.extensionId && request.extensionId !== this.extensionId) {
14547
+ return;
14548
+ }
14549
+ if (request.body.method === NativeExtensionMethod.HandshakeRequest) {
14550
+ const handshakeResolver = this.handshakeResolvers.get(request.responseId);
14551
+ /*
14552
+ * Filter out responses with no matched resolvers sooner to keep channel ports open while waiting for
14553
+ * the proper response.
14554
+ */
14555
+ if (!handshakeResolver) {
14556
+ this.logger.trace(this.platformAuthType +
14557
+ `.onWindowMessage - resolver can't be found for request ${request.responseId}`);
14558
+ return;
14559
+ }
14560
+ // If we receive this message back it means no extension intercepted the request, meaning no extension supporting handshake protocol is installed
14561
+ this.logger.verbose(request.extensionId
14562
+ ? `Extension with id: ${request.extensionId} not installed`
14563
+ : "No extension installed");
14564
+ clearTimeout(this.timeoutId);
14565
+ this.messageChannel.port1.close();
14566
+ this.messageChannel.port2.close();
14567
+ window.removeEventListener("message", this.windowListener, false);
14568
+ this.handshakeEvent.end({
14569
+ success: false,
14570
+ extensionInstalled: false,
14571
+ });
14572
+ handshakeResolver.reject(createBrowserAuthError(nativeExtensionNotInstalled));
14573
+ }
14574
+ }
14575
+ /**
14576
+ * Invoked when a message is received from the extension on the MessageChannel port
14577
+ * @param event
14578
+ */
14579
+ onChannelMessage(event) {
14580
+ this.logger.trace(this.platformAuthType + " - onChannelMessage called.");
14581
+ const request = event.data;
14582
+ const resolver = this.resolvers.get(request.responseId);
14583
+ const handshakeResolver = this.handshakeResolvers.get(request.responseId);
14584
+ try {
14585
+ const method = request.body.method;
14586
+ if (method === NativeExtensionMethod.Response) {
14587
+ if (!resolver) {
14588
+ return;
14589
+ }
14590
+ const response = request.body.response;
14591
+ this.logger.trace(this.platformAuthType +
14592
+ " - Received response from browser extension");
14593
+ this.logger.tracePii(this.platformAuthType +
14594
+ ` - Received response from browser extension: ${JSON.stringify(response)}`);
14595
+ if (response.status !== "Success") {
14596
+ resolver.reject(createNativeAuthError(response.code, response.description, response.ext));
14597
+ }
14598
+ else if (response.result) {
14599
+ if (response.result["code"] &&
14600
+ response.result["description"]) {
14601
+ resolver.reject(createNativeAuthError(response.result["code"], response.result["description"], response.result["ext"]));
14602
+ }
14603
+ else {
14604
+ resolver.resolve(response.result);
14605
+ }
14606
+ }
14607
+ else {
14608
+ throw createAuthError(unexpectedError, "Event does not contain result.");
14609
+ }
14610
+ this.resolvers.delete(request.responseId);
14611
+ }
14612
+ else if (method === NativeExtensionMethod.HandshakeResponse) {
14613
+ if (!handshakeResolver) {
14614
+ this.logger.trace(this.platformAuthType +
14615
+ `.onChannelMessage - resolver can't be found for request ${request.responseId}`);
14616
+ return;
14617
+ }
14618
+ clearTimeout(this.timeoutId); // Clear setTimeout
14619
+ window.removeEventListener("message", this.windowListener, false); // Remove 'No extension' listener
14620
+ this.extensionId = request.extensionId;
14621
+ this.extensionVersion = request.body.version;
14622
+ this.logger.verbose(this.platformAuthType +
14623
+ ` - Received HandshakeResponse from extension: ${this.extensionId}`);
14624
+ this.handshakeEvent.end({
14625
+ extensionInstalled: true,
14626
+ success: true,
14627
+ });
14628
+ handshakeResolver.resolve();
14629
+ this.handshakeResolvers.delete(request.responseId);
14630
+ }
14631
+ // Do nothing if method is not Response or HandshakeResponse
14632
+ }
14633
+ catch (err) {
14634
+ this.logger.error("Error parsing response from WAM Extension");
14635
+ this.logger.errorPii(`Error parsing response from WAM Extension: ${err}`);
14636
+ this.logger.errorPii(`Unable to parse ${event}`);
14637
+ if (resolver) {
14638
+ resolver.reject(err);
14639
+ }
14640
+ else if (handshakeResolver) {
14641
+ handshakeResolver.reject(err);
14642
+ }
14227
14643
  }
14228
- this.performanceClient.addFields({
14229
- extensionId: this.nativeMessageHandler.getExtensionId(),
14230
- extensionVersion: this.nativeMessageHandler.getExtensionVersion(),
14231
- matsBrokerVersion: mats.broker_version,
14232
- matsAccountJoinOnStart: mats.account_join_on_start,
14233
- matsAccountJoinOnEnd: mats.account_join_on_end,
14234
- matsDeviceJoin: mats.device_join,
14235
- matsPromptBehavior: mats.prompt_behavior,
14236
- matsApiErrorCode: mats.api_error_code,
14237
- matsUiVisible: mats.ui_visible,
14238
- matsSilentCode: mats.silent_code,
14239
- matsSilentBiSubCode: mats.silent_bi_sub_code,
14240
- matsSilentMessage: mats.silent_message,
14241
- matsSilentStatus: mats.silent_status,
14242
- matsHttpStatus: mats.http_status,
14243
- matsHttpEventCount: mats.http_event_count,
14244
- }, this.correlationId);
14245
- return mats;
14246
14644
  }
14247
14645
  /**
14248
14646
  * Validates native platform response before processing
14249
14647
  * @param response
14250
14648
  */
14251
- validateNativeResponse(response) {
14649
+ validatePlatformBrokerResponse(response) {
14252
14650
  if (response.hasOwnProperty("access_token") &&
14253
14651
  response.hasOwnProperty("id_token") &&
14254
14652
  response.hasOwnProperty("client_info") &&
@@ -14262,425 +14660,258 @@
14262
14660
  }
14263
14661
  }
14264
14662
  /**
14265
- * Gets MATS telemetry from native response
14266
- * @param response
14267
- * @returns
14268
- */
14269
- getMATSFromResponse(response) {
14270
- if (response.properties.MATS) {
14271
- try {
14272
- return JSON.parse(response.properties.MATS);
14273
- }
14274
- catch (e) {
14275
- this.logger.error("NativeInteractionClient - Error parsing MATS telemetry, returning null instead");
14276
- }
14277
- }
14278
- return null;
14279
- }
14280
- /**
14281
- * Returns whether or not response came from native cache
14282
- * @param response
14663
+ * Returns the Id for the browser extension this handler is communicating with
14283
14664
  * @returns
14284
14665
  */
14285
- isResponseFromCache(mats) {
14286
- if (typeof mats.is_cached === "undefined") {
14287
- this.logger.verbose("NativeInteractionClient - MATS telemetry does not contain field indicating if response was served from cache. Returning false.");
14288
- return false;
14289
- }
14290
- return !!mats.is_cached;
14291
- }
14292
- /**
14293
- * Translates developer provided request object into NativeRequest object
14294
- * @param request
14295
- */
14296
- async initializeNativeRequest(request) {
14297
- this.logger.trace("NativeInteractionClient - initializeNativeRequest called");
14298
- const requestAuthority = request.authority || this.config.auth.authority;
14299
- if (request.account) {
14300
- // validate authority
14301
- await this.getDiscoveredAuthority({
14302
- requestAuthority,
14303
- requestAzureCloudOptions: request.azureCloudOptions,
14304
- account: request.account,
14305
- });
14306
- }
14307
- const canonicalAuthority = new UrlString(requestAuthority);
14308
- canonicalAuthority.validateAsUri();
14309
- // 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.
14310
- const { scopes, ...remainingProperties } = request;
14311
- const scopeSet = new ScopeSet(scopes || []);
14312
- scopeSet.appendScopes(OIDC_DEFAULT_SCOPES);
14313
- const getPrompt = () => {
14314
- // If request is silent, prompt is always none
14315
- switch (this.apiId) {
14316
- case ApiId.ssoSilent:
14317
- case ApiId.acquireTokenSilent_silentFlow:
14318
- this.logger.trace("initializeNativeRequest: silent request sets prompt to none");
14319
- return PromptValue.NONE;
14320
- }
14321
- // Prompt not provided, request may proceed and native broker decides if it needs to prompt
14322
- if (!request.prompt) {
14323
- this.logger.trace("initializeNativeRequest: prompt was not provided");
14324
- return undefined;
14325
- }
14326
- // If request is interactive, check if prompt provided is allowed to go directly to native broker
14327
- switch (request.prompt) {
14328
- case PromptValue.NONE:
14329
- case PromptValue.CONSENT:
14330
- case PromptValue.LOGIN:
14331
- this.logger.trace("initializeNativeRequest: prompt is compatible with native flow");
14332
- return request.prompt;
14333
- default:
14334
- this.logger.trace(`initializeNativeRequest: prompt = ${request.prompt} is not compatible with native flow`);
14335
- throw createBrowserAuthError(nativePromptNotSupported);
14336
- }
14337
- };
14338
- const validatedRequest = {
14339
- ...remainingProperties,
14340
- accountId: this.accountId,
14341
- clientId: this.config.auth.clientId,
14342
- authority: canonicalAuthority.urlString,
14343
- scope: scopeSet.printScopes(),
14344
- redirectUri: this.getRedirectUri(request.redirectUri),
14345
- prompt: getPrompt(),
14346
- correlationId: this.correlationId,
14347
- tokenType: request.authenticationScheme,
14348
- windowTitleSubstring: document.title,
14349
- extraParameters: {
14350
- ...request.extraQueryParameters,
14351
- ...request.tokenQueryParameters,
14352
- },
14353
- extendedExpiryToken: false,
14354
- keyId: request.popKid,
14355
- };
14356
- // Check for PoP token requests: signPopToken should only be set to true if popKid is not set
14357
- if (validatedRequest.signPopToken && !!request.popKid) {
14358
- throw createBrowserAuthError(invalidPopTokenRequest);
14359
- }
14360
- this.handleExtraBrokerParams(validatedRequest);
14361
- validatedRequest.extraParameters =
14362
- validatedRequest.extraParameters || {};
14363
- validatedRequest.extraParameters.telemetry =
14364
- NativeConstants.MATS_TELEMETRY;
14365
- if (request.authenticationScheme === AuthenticationScheme.POP) {
14366
- // add POP request type
14367
- const shrParameters = {
14368
- resourceRequestUri: request.resourceRequestUri,
14369
- resourceRequestMethod: request.resourceRequestMethod,
14370
- shrClaims: request.shrClaims,
14371
- shrNonce: request.shrNonce,
14372
- };
14373
- const popTokenGenerator = new PopTokenGenerator(this.browserCrypto);
14374
- // generate reqCnf if not provided in the request
14375
- let reqCnfData;
14376
- if (!validatedRequest.keyId) {
14377
- const generatedReqCnfData = await invokeAsync(popTokenGenerator.generateCnf.bind(popTokenGenerator), PerformanceEvents.PopTokenGenerateCnf, this.logger, this.performanceClient, request.correlationId)(shrParameters, this.logger);
14378
- reqCnfData = generatedReqCnfData.reqCnfString;
14379
- validatedRequest.keyId = generatedReqCnfData.kid;
14380
- validatedRequest.signPopToken = true;
14381
- }
14382
- else {
14383
- reqCnfData = this.browserCrypto.base64UrlEncode(JSON.stringify({ kid: validatedRequest.keyId }));
14384
- validatedRequest.signPopToken = false;
14385
- }
14386
- // SPAs require whole string to be passed to broker
14387
- validatedRequest.reqCnf = reqCnfData;
14388
- }
14389
- this.addRequestSKUs(validatedRequest);
14390
- return validatedRequest;
14391
- }
14392
- /**
14393
- * Handles extra broker request parameters
14394
- * @param request {NativeTokenRequest}
14395
- * @private
14396
- */
14397
- handleExtraBrokerParams(request) {
14398
- const hasExtraBrokerParams = request.extraParameters &&
14399
- request.extraParameters.hasOwnProperty(BROKER_CLIENT_ID) &&
14400
- request.extraParameters.hasOwnProperty(BROKER_REDIRECT_URI) &&
14401
- request.extraParameters.hasOwnProperty(CLIENT_ID);
14402
- if (!request.embeddedClientId && !hasExtraBrokerParams) {
14403
- return;
14404
- }
14405
- let child_client_id = "";
14406
- const child_redirect_uri = request.redirectUri;
14407
- if (request.embeddedClientId) {
14408
- request.redirectUri = this.config.auth.redirectUri;
14409
- child_client_id = request.embeddedClientId;
14410
- }
14411
- else if (request.extraParameters) {
14412
- request.redirectUri =
14413
- request.extraParameters[BROKER_REDIRECT_URI];
14414
- child_client_id =
14415
- request.extraParameters[CLIENT_ID];
14416
- }
14417
- request.extraParameters = {
14418
- child_client_id,
14419
- child_redirect_uri,
14420
- };
14421
- this.performanceClient?.addFields({
14422
- embeddedClientId: child_client_id,
14423
- embeddedRedirectUri: child_redirect_uri,
14424
- }, request.correlationId);
14425
- }
14426
- }
14427
-
14428
- /*
14429
- * Copyright (c) Microsoft Corporation. All rights reserved.
14430
- * Licensed under the MIT License.
14431
- */
14432
- /**
14433
- * Returns map of parameters that are applicable to all calls to /authorize whether using PKCE or EAR
14434
- * @param config
14435
- * @param authority
14436
- * @param request
14437
- * @param logger
14438
- * @param performanceClient
14439
- * @returns
14440
- */
14441
- async function getStandardParameters(config, authority, request, logger, performanceClient) {
14442
- const parameters = getStandardAuthorizeRequestParameters({ ...config.auth, authority: authority }, request, logger, performanceClient);
14443
- addLibraryInfo(parameters, {
14444
- sku: BrowserConstants.MSAL_SKU,
14445
- version: version,
14446
- os: "",
14447
- cpu: "",
14448
- });
14449
- if (config.auth.protocolMode !== ProtocolMode.OIDC) {
14450
- addApplicationTelemetry(parameters, config.telemetry.application);
14451
- }
14452
- if (request.platformBroker) {
14453
- // signal ests that this is a WAM call
14454
- addNativeBroker(parameters);
14455
- // pass the req_cnf for POP
14456
- if (request.authenticationScheme === AuthenticationScheme.POP) {
14457
- const cryptoOps = new CryptoOps(logger, performanceClient);
14458
- const popTokenGenerator = new PopTokenGenerator(cryptoOps);
14459
- // req_cnf is always sent as a string for SPAs
14460
- let reqCnfData;
14461
- if (!request.popKid) {
14462
- const generatedReqCnfData = await invokeAsync(popTokenGenerator.generateCnf.bind(popTokenGenerator), PerformanceEvents.PopTokenGenerateCnf, logger, performanceClient, request.correlationId)(request, logger);
14463
- reqCnfData = generatedReqCnfData.reqCnfString;
14464
- }
14465
- else {
14466
- reqCnfData = cryptoOps.encodeKid(request.popKid);
14467
- }
14468
- addPopToken(parameters, reqCnfData);
14469
- }
14666
+ getExtensionId() {
14667
+ return this.extensionId;
14470
14668
  }
14471
- instrumentBrokerParams(parameters, request.correlationId, performanceClient);
14472
- return parameters;
14473
- }
14474
- /**
14475
- * Gets the full /authorize URL with request parameters when using Auth Code + PKCE
14476
- * @param config
14477
- * @param authority
14478
- * @param request
14479
- * @param logger
14480
- * @param performanceClient
14481
- * @returns
14482
- */
14483
- async function getAuthCodeRequestUrl(config, authority, request, logger, performanceClient) {
14484
- if (!request.codeChallenge) {
14485
- throw createClientConfigurationError(pkceParamsMissing);
14669
+ /**
14670
+ * Returns the version for the browser extension this handler is communicating with
14671
+ * @returns
14672
+ */
14673
+ getExtensionVersion() {
14674
+ return this.extensionVersion;
14486
14675
  }
14487
- const parameters = await invokeAsync(getStandardParameters, PerformanceEvents.GetStandardParams, logger, performanceClient, request.correlationId)(config, authority, request, logger, performanceClient);
14488
- addResponseType(parameters, OAuthResponseType.CODE);
14489
- addCodeChallengeParams(parameters, request.codeChallenge, Constants.S256_CODE_CHALLENGE_METHOD);
14490
- addExtraQueryParameters(parameters, request.extraQueryParameters || {});
14491
- return getAuthorizeUrl(authority, parameters, config.auth.encodeExtraQueryParams, request.extraQueryParameters);
14492
- }
14493
- /**
14494
- * Gets the form that will be posted to /authorize with request parameters when using EAR
14495
- */
14496
- async function getEARForm(frame, config, authority, request, logger, performanceClient) {
14497
- if (!request.earJwk) {
14498
- throw createBrowserAuthError(earJwkEmpty);
14676
+ getExtensionName() {
14677
+ return this.getExtensionId() ===
14678
+ PlatformAuthConstants.PREFERRED_EXTENSION_ID
14679
+ ? "chrome"
14680
+ : this.getExtensionId()?.length
14681
+ ? "unknown"
14682
+ : undefined;
14499
14683
  }
14500
- const parameters = await getStandardParameters(config, authority, request, logger, performanceClient);
14501
- addResponseType(parameters, OAuthResponseType.IDTOKEN_TOKEN_REFRESHTOKEN);
14502
- addEARParameters(parameters, request.earJwk);
14503
- const queryParams = new Map();
14504
- addExtraQueryParameters(queryParams, request.extraQueryParameters || {});
14505
- const url = getAuthorizeUrl(authority, queryParams, config.auth.encodeExtraQueryParams, request.extraQueryParameters);
14506
- return createForm(frame, url, parameters);
14507
- }
14508
- /**
14509
- * Creates form element in the provided document with auth parameters in the post body
14510
- * @param frame
14511
- * @param authorizeUrl
14512
- * @param parameters
14513
- * @returns
14514
- */
14515
- function createForm(frame, authorizeUrl, parameters) {
14516
- const form = frame.createElement("form");
14517
- form.method = "post";
14518
- form.action = authorizeUrl;
14519
- parameters.forEach((value, key) => {
14520
- const param = frame.createElement("input");
14521
- param.hidden = true;
14522
- param.name = key;
14523
- param.value = value;
14524
- form.appendChild(param);
14525
- });
14526
- frame.body.appendChild(form);
14527
- return form;
14528
- }
14529
- /**
14530
- * Response handler when server returns accountId on the /authorize request
14531
- * @param request
14532
- * @param accountId
14533
- * @param apiId
14534
- * @param config
14535
- * @param browserStorage
14536
- * @param nativeStorage
14537
- * @param eventHandler
14538
- * @param logger
14539
- * @param performanceClient
14540
- * @param nativeMessageHandler
14541
- * @returns
14684
+ }
14685
+
14686
+ /*
14687
+ * Copyright (c) Microsoft Corporation. All rights reserved.
14688
+ * Licensed under the MIT License.
14542
14689
  */
14543
- async function handleResponsePlatformBroker(request, accountId, apiId, config, browserStorage, nativeStorage, eventHandler, logger, performanceClient, nativeMessageHandler) {
14544
- if (!nativeMessageHandler) {
14545
- throw createBrowserAuthError(nativeConnectionNotEstablished);
14690
+ class PlatformAuthDOMHandler {
14691
+ constructor(logger, performanceClient, correlationId) {
14692
+ this.logger = logger;
14693
+ this.performanceClient = performanceClient;
14694
+ this.correlationId = correlationId;
14695
+ this.platformAuthType = PlatformAuthConstants.PLATFORM_DOM_PROVIDER;
14546
14696
  }
14547
- const browserCrypto = new CryptoOps(logger, performanceClient);
14548
- const nativeInteractionClient = new NativeInteractionClient(config, browserStorage, browserCrypto, logger, eventHandler, config.system.navigationClient, apiId, performanceClient, nativeMessageHandler, accountId, nativeStorage, request.correlationId);
14549
- const { userRequestState } = ProtocolUtils.parseRequestState(browserCrypto, request.state);
14550
- return invokeAsync(nativeInteractionClient.acquireToken.bind(nativeInteractionClient), PerformanceEvents.NativeInteractionClientAcquireToken, logger, performanceClient, request.correlationId)({
14551
- ...request,
14552
- state: userRequestState,
14553
- prompt: undefined, // Server should handle the prompt, ideally native broker can do this part silently
14554
- });
14555
- }
14556
- /**
14557
- * Response handler when server returns code on the /authorize request
14558
- * @param request
14559
- * @param response
14560
- * @param codeVerifier
14561
- * @param authClient
14562
- * @param browserStorage
14563
- * @param logger
14564
- * @param performanceClient
14565
- * @returns
14566
- */
14567
- async function handleResponseCode(request, response, codeVerifier, apiId, config, authClient, browserStorage, nativeStorage, eventHandler, logger, performanceClient, nativeMessageHandler) {
14568
- // Remove throttle if it exists
14569
- ThrottlingUtils.removeThrottle(browserStorage, config.auth.clientId, request);
14570
- if (response.accountId) {
14571
- return invokeAsync(handleResponsePlatformBroker, PerformanceEvents.HandleResponsePlatformBroker, logger, performanceClient, request.correlationId)(request, response.accountId, apiId, config, browserStorage, nativeStorage, eventHandler, logger, performanceClient, nativeMessageHandler);
14697
+ static async createProvider(logger, performanceClient, correlationId) {
14698
+ logger.trace("PlatformAuthDOMHandler: createProvider called");
14699
+ // @ts-ignore
14700
+ if (window.navigator?.platformAuthentication) {
14701
+ const supportedContracts =
14702
+ // @ts-ignore
14703
+ await window.navigator.platformAuthentication.getSupportedContracts(PlatformAuthConstants.MICROSOFT_ENTRA_BROKERID);
14704
+ if (supportedContracts?.includes(PlatformAuthConstants.PLATFORM_DOM_APIS)) {
14705
+ logger.trace("Platform auth api available in DOM");
14706
+ return new PlatformAuthDOMHandler(logger, performanceClient, correlationId);
14707
+ }
14708
+ }
14709
+ return undefined;
14572
14710
  }
14573
- const authCodeRequest = {
14574
- ...request,
14575
- code: response.code || "",
14576
- codeVerifier: codeVerifier,
14577
- };
14578
- // Create popup interaction handler.
14579
- const interactionHandler = new InteractionHandler(authClient, browserStorage, authCodeRequest, logger, performanceClient);
14580
- // Handle response from hash string.
14581
- const result = await invokeAsync(interactionHandler.handleCodeResponse.bind(interactionHandler), PerformanceEvents.HandleCodeResponse, logger, performanceClient, request.correlationId)(response, request);
14582
- return result;
14583
- }
14584
- /**
14585
- * Response handler when server returns ear_jwe on the /authorize request
14586
- * @param request
14587
- * @param response
14588
- * @param apiId
14589
- * @param config
14590
- * @param authority
14591
- * @param browserStorage
14592
- * @param nativeStorage
14593
- * @param eventHandler
14594
- * @param logger
14595
- * @param performanceClient
14596
- * @param nativeMessageHandler
14597
- * @returns
14598
- */
14599
- async function handleResponseEAR(request, response, apiId, config, authority, browserStorage, nativeStorage, eventHandler, logger, performanceClient, nativeMessageHandler) {
14600
- // Remove throttle if it exists
14601
- ThrottlingUtils.removeThrottle(browserStorage, config.auth.clientId, request);
14602
- // Validate state & check response for errors
14603
- validateAuthorizationResponse(response, request.state);
14604
- if (!response.ear_jwe) {
14605
- throw createBrowserAuthError(earJweEmpty);
14711
+ /**
14712
+ * Returns the Id for the broker extension this handler is communicating with
14713
+ * @returns
14714
+ */
14715
+ getExtensionId() {
14716
+ return PlatformAuthConstants.MICROSOFT_ENTRA_BROKERID;
14606
14717
  }
14607
- if (!request.earJwk) {
14608
- throw createBrowserAuthError(earJwkEmpty);
14718
+ getExtensionVersion() {
14719
+ return "";
14609
14720
  }
14610
- const decryptedData = JSON.parse(await invokeAsync(decryptEarResponse, PerformanceEvents.DecryptEarResponse, logger, performanceClient, request.correlationId)(request.earJwk, response.ear_jwe));
14611
- if (decryptedData.accountId) {
14612
- return invokeAsync(handleResponsePlatformBroker, PerformanceEvents.HandleResponsePlatformBroker, logger, performanceClient, request.correlationId)(request, decryptedData.accountId, apiId, config, browserStorage, nativeStorage, eventHandler, logger, performanceClient, nativeMessageHandler);
14721
+ getExtensionName() {
14722
+ return PlatformAuthConstants.DOM_API_NAME;
14723
+ }
14724
+ /**
14725
+ * Send token request to platform broker via browser DOM API
14726
+ * @param request
14727
+ * @returns
14728
+ */
14729
+ async sendMessage(request) {
14730
+ this.logger.trace(this.platformAuthType + " - Sending request to browser DOM API");
14731
+ try {
14732
+ const platformDOMRequest = this.initializePlatformDOMRequest(request);
14733
+ const response =
14734
+ // @ts-ignore
14735
+ await window.navigator.platformAuthentication.executeGetToken(platformDOMRequest);
14736
+ return this.validatePlatformBrokerResponse(response);
14737
+ }
14738
+ catch (e) {
14739
+ this.logger.error(this.platformAuthType + " - executeGetToken DOM API error");
14740
+ throw e;
14741
+ }
14742
+ }
14743
+ initializePlatformDOMRequest(request) {
14744
+ this.logger.trace(this.platformAuthType + " - initializeNativeDOMRequest called");
14745
+ const { accountId, clientId, authority, scope, redirectUri, correlationId, state, storeInCache, embeddedClientId, extraParameters, ...remainingProperties } = request;
14746
+ const validExtraParameters = this.getDOMExtraParams(remainingProperties);
14747
+ const platformDOMRequest = {
14748
+ accountId: accountId,
14749
+ brokerId: this.getExtensionId(),
14750
+ authority: authority,
14751
+ clientId: clientId,
14752
+ correlationId: correlationId || this.correlationId,
14753
+ extraParameters: { ...extraParameters, ...validExtraParameters },
14754
+ isSecurityTokenService: false,
14755
+ redirectUri: redirectUri,
14756
+ scope: scope,
14757
+ state: state,
14758
+ storeInCache: storeInCache,
14759
+ embeddedClientId: embeddedClientId,
14760
+ };
14761
+ return platformDOMRequest;
14762
+ }
14763
+ validatePlatformBrokerResponse(response) {
14764
+ if (response.hasOwnProperty("isSuccess")) {
14765
+ if (response.hasOwnProperty("accessToken") &&
14766
+ response.hasOwnProperty("idToken") &&
14767
+ response.hasOwnProperty("clientInfo") &&
14768
+ response.hasOwnProperty("account") &&
14769
+ response.hasOwnProperty("scopes") &&
14770
+ response.hasOwnProperty("expiresIn")) {
14771
+ this.logger.trace(this.platformAuthType +
14772
+ " - platform broker returned successful and valid response");
14773
+ return this.convertToPlatformBrokerResponse(response);
14774
+ }
14775
+ else if (response.hasOwnProperty("error")) {
14776
+ const errorResponse = response;
14777
+ if (errorResponse.isSuccess === false &&
14778
+ errorResponse.error &&
14779
+ errorResponse.error.code) {
14780
+ this.logger.trace(this.platformAuthType +
14781
+ " - platform broker returned error response");
14782
+ throw createNativeAuthError(errorResponse.error.code, errorResponse.error.description, {
14783
+ error: parseInt(errorResponse.error.errorCode),
14784
+ protocol_error: errorResponse.error.protocolError,
14785
+ status: errorResponse.error.status,
14786
+ properties: errorResponse.error.properties,
14787
+ });
14788
+ }
14789
+ }
14790
+ }
14791
+ throw createAuthError(unexpectedError, "Response missing expected properties.");
14792
+ }
14793
+ convertToPlatformBrokerResponse(response) {
14794
+ this.logger.trace(this.platformAuthType + " - convertToNativeResponse called");
14795
+ const nativeResponse = {
14796
+ access_token: response.accessToken,
14797
+ id_token: response.idToken,
14798
+ client_info: response.clientInfo,
14799
+ account: response.account,
14800
+ expires_in: response.expiresIn,
14801
+ scope: response.scopes,
14802
+ state: response.state || "",
14803
+ properties: response.properties || {},
14804
+ extendedLifetimeToken: response.extendedLifetimeToken ?? false,
14805
+ shr: response.proofOfPossessionPayload,
14806
+ };
14807
+ return nativeResponse;
14808
+ }
14809
+ getDOMExtraParams(extraParameters) {
14810
+ const stringifiedParams = Object.entries(extraParameters).reduce((record, [key, value]) => {
14811
+ record[key] = String(value);
14812
+ return record;
14813
+ }, {});
14814
+ const validExtraParams = {
14815
+ ...stringifiedParams,
14816
+ };
14817
+ return validExtraParams;
14613
14818
  }
14614
- const responseHandler = new ResponseHandler(config.auth.clientId, browserStorage, new CryptoOps(logger, performanceClient), logger, null, null, performanceClient);
14615
- // Validate response. This function throws a server error if an error is returned by the server.
14616
- responseHandler.validateTokenResponse(decryptedData);
14617
- // Temporary until response handler is refactored to be more flow agnostic.
14618
- const additionalData = {
14619
- code: "",
14620
- state: request.state,
14621
- nonce: request.nonce,
14622
- client_info: decryptedData.client_info,
14623
- cloud_graph_host_name: decryptedData.cloud_graph_host_name,
14624
- cloud_instance_host_name: decryptedData.cloud_instance_host_name,
14625
- cloud_instance_name: decryptedData.cloud_instance_name,
14626
- msgraph_host: decryptedData.msgraph_host,
14627
- };
14628
- return (await invokeAsync(responseHandler.handleServerTokenResponse.bind(responseHandler), PerformanceEvents.HandleServerTokenResponse, logger, performanceClient, request.correlationId)(decryptedData, authority, nowSeconds(), request, additionalData, undefined, undefined, undefined, undefined));
14629
14819
  }
14630
14820
 
14631
14821
  /*
14632
14822
  * Copyright (c) Microsoft Corporation. All rights reserved.
14633
14823
  * Licensed under the MIT License.
14634
14824
  */
14635
- // Constant byte array length
14636
- const RANDOM_BYTE_ARR_LENGTH = 32;
14637
- /**
14638
- * This file defines APIs to generate PKCE codes and code verifiers.
14639
- */
14640
14825
  /**
14641
- * Generates PKCE Codes. See the RFC for more information: https://tools.ietf.org/html/rfc7636
14826
+ * Checks if the platform broker is available in the current environment.
14827
+ * @param loggerOptions
14828
+ * @param perfClient
14829
+ * @returns
14642
14830
  */
14643
- async function generatePkceCodes(performanceClient, logger, correlationId) {
14644
- performanceClient.addQueueMeasurement(PerformanceEvents.GeneratePkceCodes, correlationId);
14645
- const codeVerifier = invoke(generateCodeVerifier, PerformanceEvents.GenerateCodeVerifier, logger, performanceClient, correlationId)(performanceClient, logger, correlationId);
14646
- const codeChallenge = await invokeAsync(generateCodeChallengeFromVerifier, PerformanceEvents.GenerateCodeChallengeFromVerifier, logger, performanceClient, correlationId)(codeVerifier, performanceClient, logger, correlationId);
14647
- return {
14648
- verifier: codeVerifier,
14649
- challenge: codeChallenge,
14650
- };
14831
+ async function isPlatformBrokerAvailable(loggerOptions, perfClient, correlationId) {
14832
+ const logger = new Logger(loggerOptions || {}, name, version);
14833
+ logger.trace("isPlatformBrokerAvailable called");
14834
+ const performanceClient = perfClient || new StubPerformanceClient();
14835
+ if (typeof window === "undefined") {
14836
+ logger.trace("Non-browser environment detected, returning false");
14837
+ return false;
14838
+ }
14839
+ return !!(await getPlatformAuthProvider(logger, performanceClient, correlationId || createNewGuid()));
14651
14840
  }
14652
- /**
14653
- * Generates a random 32 byte buffer and returns the base64
14654
- * encoded string to be used as a PKCE Code Verifier
14655
- */
14656
- function generateCodeVerifier(performanceClient, logger, correlationId) {
14841
+ async function getPlatformAuthProvider(logger, performanceClient, correlationId, nativeBrokerHandshakeTimeout) {
14842
+ logger.trace("getPlatformAuthProvider called", correlationId);
14843
+ const enablePlatformBrokerDOMSupport = isDomEnabledForPlatformAuth();
14844
+ logger.trace("Has client allowed platform auth via DOM API: " +
14845
+ enablePlatformBrokerDOMSupport);
14846
+ let platformAuthProvider;
14657
14847
  try {
14658
- // Generate random values as utf-8
14659
- const buffer = new Uint8Array(RANDOM_BYTE_ARR_LENGTH);
14660
- invoke(getRandomValues, PerformanceEvents.GetRandomValues, logger, performanceClient, correlationId)(buffer);
14661
- // encode verifier as base64
14662
- const pkceCodeVerifierB64 = urlEncodeArr(buffer);
14663
- return pkceCodeVerifierB64;
14848
+ if (enablePlatformBrokerDOMSupport) {
14849
+ // Check if DOM platform API is supported first
14850
+ platformAuthProvider = await PlatformAuthDOMHandler.createProvider(logger, performanceClient, correlationId);
14851
+ }
14852
+ if (!platformAuthProvider) {
14853
+ logger.trace("Platform auth via DOM API not available, checking for extension");
14854
+ /*
14855
+ * If DOM APIs are not available, check if browser extension is available.
14856
+ * Platform authentication via DOM APIs is preferred over extension APIs.
14857
+ */
14858
+ platformAuthProvider =
14859
+ await PlatformAuthExtensionHandler.createProvider(logger, nativeBrokerHandshakeTimeout ||
14860
+ DEFAULT_NATIVE_BROKER_HANDSHAKE_TIMEOUT_MS, performanceClient);
14861
+ }
14664
14862
  }
14665
14863
  catch (e) {
14666
- throw createBrowserAuthError(pkceNotCreated);
14864
+ logger.trace("Platform auth not available", e);
14667
14865
  }
14866
+ return platformAuthProvider;
14668
14867
  }
14669
14868
  /**
14670
- * Creates a base64 encoded PKCE Code Challenge string from the
14671
- * hash created from the PKCE Code Verifier supplied
14869
+ * Returns true if the DOM API support for platform auth is enabled in session storage
14870
+ * @returns boolean
14871
+ * @deprecated
14672
14872
  */
14673
- async function generateCodeChallengeFromVerifier(pkceCodeVerifier, performanceClient, logger, correlationId) {
14674
- performanceClient.addQueueMeasurement(PerformanceEvents.GenerateCodeChallengeFromVerifier, correlationId);
14873
+ function isDomEnabledForPlatformAuth() {
14874
+ let sessionStorage;
14675
14875
  try {
14676
- // hashed verifier
14677
- const pkceHashedCodeVerifier = await invokeAsync(sha256Digest, PerformanceEvents.Sha256Digest, logger, performanceClient, correlationId)(pkceCodeVerifier, performanceClient, correlationId);
14678
- // encode hash as base64
14679
- return urlEncodeArr(new Uint8Array(pkceHashedCodeVerifier));
14876
+ sessionStorage = window[BrowserCacheLocation.SessionStorage];
14877
+ // Mute errors if it's a non-browser environment or cookies are blocked.
14878
+ return sessionStorage?.getItem(PLATFORM_AUTH_DOM_SUPPORT) === "true";
14680
14879
  }
14681
14880
  catch (e) {
14682
- throw createBrowserAuthError(pkceNotCreated);
14881
+ return false;
14882
+ }
14883
+ }
14884
+ /**
14885
+ * Returns boolean indicating whether or not the request should attempt to use native broker
14886
+ * @param logger
14887
+ * @param config
14888
+ * @param platformAuthProvider
14889
+ * @param authenticationScheme
14890
+ */
14891
+ function isPlatformAuthAllowed(config, logger, platformAuthProvider, authenticationScheme) {
14892
+ logger.trace("isBrokerAvailable called");
14893
+ if (!config.system.allowPlatformBroker) {
14894
+ logger.trace("isBrokerAvailable: allowPlatformBroker is not enabled, returning false");
14895
+ // Developer disabled WAM
14896
+ return false;
14897
+ }
14898
+ if (!platformAuthProvider) {
14899
+ logger.trace("isBrokerAvailable: Platform auth provider is not initialized, returning false");
14900
+ // Platform broker auth providers are not available
14901
+ return false;
14902
+ }
14903
+ if (authenticationScheme) {
14904
+ switch (authenticationScheme) {
14905
+ case AuthenticationScheme.BEARER:
14906
+ case AuthenticationScheme.POP:
14907
+ logger.trace("isBrokerAvailable: authenticationScheme is supported, returning true");
14908
+ return true;
14909
+ default:
14910
+ logger.trace("isBrokerAvailable: authenticationScheme is not supported, returning false");
14911
+ return false;
14912
+ }
14683
14913
  }
14914
+ return true;
14684
14915
  }
14685
14916
 
14686
14917
  /*
@@ -14688,8 +14919,8 @@
14688
14919
  * Licensed under the MIT License.
14689
14920
  */
14690
14921
  class PopupClient extends StandardInteractionClient {
14691
- constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeStorageImpl, nativeMessageHandler, correlationId) {
14692
- super(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeMessageHandler, correlationId);
14922
+ constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeStorageImpl, platformAuthHandler, correlationId) {
14923
+ super(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, platformAuthHandler, correlationId);
14693
14924
  // Properly sets this reference for the unload event.
14694
14925
  this.unloadWindow = this.unloadWindow.bind(this);
14695
14926
  this.nativeStorage = nativeStorageImpl;
@@ -14777,7 +15008,7 @@
14777
15008
  if (popupParams.popup) {
14778
15009
  preconnect(validRequest.authority);
14779
15010
  }
14780
- const isPlatformBroker = NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeMessageHandler, request.authenticationScheme);
15011
+ const isPlatformBroker = isPlatformAuthAllowed(this.config, this.logger, this.platformAuthProvider, request.authenticationScheme);
14781
15012
  validRequest.platformBroker = isPlatformBroker;
14782
15013
  if (this.config.auth.protocolMode === ProtocolMode.EAR) {
14783
15014
  return this.executeEarFlow(validRequest, popupParams);
@@ -14819,7 +15050,7 @@
14819
15050
  // Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
14820
15051
  const responseString = await this.monitorPopupForHash(popupWindow, popupParams.popupWindowParent);
14821
15052
  const serverParams = invoke(deserializeResponse, PerformanceEvents.DeserializeResponse, this.logger, this.performanceClient, this.correlationId)(responseString, this.config.auth.OIDCOptions.serverResponseType, this.logger);
14822
- 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);
15053
+ 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.platformAuthProvider);
14823
15054
  }
14824
15055
  catch (e) {
14825
15056
  // Close the synchronous popup if an error is thrown before the window unload event is registered
@@ -14855,7 +15086,7 @@
14855
15086
  // Monitor the popup for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
14856
15087
  const responseString = await invokeAsync(this.monitorPopupForHash.bind(this), PerformanceEvents.SilentHandlerMonitorIframeForHash, this.logger, this.performanceClient, correlationId)(popupWindow, popupParams.popupWindowParent);
14857
15088
  const serverParams = invoke(deserializeResponse, PerformanceEvents.DeserializeResponse, this.logger, this.performanceClient, this.correlationId)(responseString, this.config.auth.OIDCOptions.serverResponseType, this.logger);
14858
- 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);
15089
+ 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.platformAuthProvider);
14859
15090
  }
14860
15091
  /**
14861
15092
  *
@@ -15152,8 +15383,8 @@
15152
15383
  return navigation?.type;
15153
15384
  }
15154
15385
  class RedirectClient extends StandardInteractionClient {
15155
- constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeStorageImpl, nativeMessageHandler, correlationId) {
15156
- super(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeMessageHandler, correlationId);
15386
+ constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeStorageImpl, platformAuthHandler, correlationId) {
15387
+ super(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, platformAuthHandler, correlationId);
15157
15388
  this.nativeStorage = nativeStorageImpl;
15158
15389
  }
15159
15390
  /**
@@ -15162,8 +15393,7 @@
15162
15393
  */
15163
15394
  async acquireToken(request) {
15164
15395
  const validRequest = await invokeAsync(this.initializeAuthorizationRequest.bind(this), PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest, this.logger, this.performanceClient, this.correlationId)(request, exports.InteractionType.Redirect);
15165
- validRequest.platformBroker =
15166
- NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeMessageHandler, request.authenticationScheme);
15396
+ validRequest.platformBroker = isPlatformAuthAllowed(this.config, this.logger, this.platformAuthProvider, request.authenticationScheme);
15167
15397
  const handleBackButton = (event) => {
15168
15398
  // Clear temporary cache if the back button is clicked during the redirect flow.
15169
15399
  if (event.persisted) {
@@ -15403,10 +15633,10 @@
15403
15633
  requestExtraQueryParameters: request.extraQueryParameters,
15404
15634
  account: request.account,
15405
15635
  });
15406
- 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);
15636
+ 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.platformAuthProvider);
15407
15637
  }
15408
15638
  const authClient = await invokeAsync(this.createAuthCodeClient.bind(this), PerformanceEvents.StandardInteractionClientCreateAuthCodeClient, this.logger, this.performanceClient, this.correlationId)({ serverTelemetryManager, requestAuthority: request.authority });
15409
- 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);
15639
+ 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.platformAuthProvider);
15410
15640
  }
15411
15641
  /**
15412
15642
  * Redirects window to given URL.
@@ -15690,8 +15920,8 @@
15690
15920
  * Licensed under the MIT License.
15691
15921
  */
15692
15922
  class SilentIframeClient extends StandardInteractionClient {
15693
- constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, apiId, performanceClient, nativeStorageImpl, nativeMessageHandler, correlationId) {
15694
- super(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeMessageHandler, correlationId);
15923
+ constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, apiId, performanceClient, nativeStorageImpl, platformAuthProvider, correlationId) {
15924
+ super(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, platformAuthProvider, correlationId);
15695
15925
  this.apiId = apiId;
15696
15926
  this.nativeStorage = nativeStorageImpl;
15697
15927
  }
@@ -15721,8 +15951,7 @@
15721
15951
  }
15722
15952
  // Create silent request
15723
15953
  const silentRequest = await invokeAsync(this.initializeAuthorizationRequest.bind(this), PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest, this.logger, this.performanceClient, request.correlationId)(inputRequest, exports.InteractionType.Silent);
15724
- silentRequest.platformBroker =
15725
- NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeMessageHandler, silentRequest.authenticationScheme);
15954
+ silentRequest.platformBroker = isPlatformAuthAllowed(this.config, this.logger, this.platformAuthProvider, silentRequest.authenticationScheme);
15726
15955
  preconnect(silentRequest.authority);
15727
15956
  if (this.config.auth.protocolMode === ProtocolMode.EAR) {
15728
15957
  return this.executeEarFlow(silentRequest);
@@ -15788,7 +16017,7 @@
15788
16017
  // Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
15789
16018
  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);
15790
16019
  const serverParams = invoke(deserializeResponse, PerformanceEvents.DeserializeResponse, this.logger, this.performanceClient, correlationId)(responseString, responseType, this.logger);
15791
- 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);
16020
+ 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.platformAuthProvider);
15792
16021
  }
15793
16022
  /**
15794
16023
  * Currently Unsupported
@@ -15819,7 +16048,7 @@
15819
16048
  // Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
15820
16049
  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);
15821
16050
  const serverParams = invoke(deserializeResponse, PerformanceEvents.DeserializeResponse, this.logger, this.performanceClient, correlationId)(responseString, responseType, this.logger);
15822
- 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);
16051
+ 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.platformAuthProvider);
15823
16052
  }
15824
16053
  }
15825
16054
 
@@ -16100,8 +16329,8 @@
16100
16329
  * Licensed under the MIT License.
16101
16330
  */
16102
16331
  class SilentAuthCodeClient extends StandardInteractionClient {
16103
- constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, apiId, performanceClient, nativeMessageHandler, correlationId) {
16104
- super(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeMessageHandler, correlationId);
16332
+ constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, apiId, performanceClient, platformAuthProvider, correlationId) {
16333
+ super(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, platformAuthProvider, correlationId);
16105
16334
  this.apiId = apiId;
16106
16335
  }
16107
16336
  /**
@@ -16159,6 +16388,25 @@
16159
16388
  }
16160
16389
  }
16161
16390
 
16391
+ /*
16392
+ * Copyright (c) Microsoft Corporation. All rights reserved.
16393
+ * Licensed under the MIT License.
16394
+ */
16395
+ function collectInstanceStats(currentClientId, performanceEvent, logger) {
16396
+ const frameInstances =
16397
+ // @ts-ignore
16398
+ window.msal?.clientIds || [];
16399
+ const msalInstanceCount = frameInstances.length;
16400
+ const sameClientIdInstanceCount = frameInstances.filter((i) => i === currentClientId).length;
16401
+ if (sameClientIdInstanceCount > 1) {
16402
+ logger.warning("There is already an instance of MSAL.js in the window with the same client id.");
16403
+ }
16404
+ performanceEvent.add({
16405
+ msalInstanceCount: msalInstanceCount,
16406
+ sameClientIdInstanceCount: sameClientIdInstanceCount,
16407
+ });
16408
+ }
16409
+
16162
16410
  /*
16163
16411
  * Copyright (c) Microsoft Corporation. All rights reserved.
16164
16412
  * Licensed under the MIT License.
@@ -16270,7 +16518,7 @@
16270
16518
  * Initializer function to perform async startup tasks such as connecting to WAM extension
16271
16519
  * @param request {?InitializeApplicationRequest} correlation id
16272
16520
  */
16273
- async initialize(request) {
16521
+ async initialize(request, isBroker) {
16274
16522
  this.logger.trace("initialize called");
16275
16523
  if (this.initialized) {
16276
16524
  this.logger.info("initialize has already been called, exiting early.");
@@ -16286,11 +16534,18 @@
16286
16534
  const allowPlatformBroker = this.config.system.allowPlatformBroker;
16287
16535
  const initMeasurement = this.performanceClient.startMeasurement(PerformanceEvents.InitializeClientApplication, initCorrelationId);
16288
16536
  this.eventHandler.emitEvent(EventType.INITIALIZE_START);
16537
+ // Broker applications are initialized twice, so we avoid double-counting it
16538
+ if (!isBroker) {
16539
+ try {
16540
+ this.logMultipleInstances(initMeasurement);
16541
+ }
16542
+ catch { }
16543
+ }
16289
16544
  await invokeAsync(this.browserStorage.initialize.bind(this.browserStorage), PerformanceEvents.InitializeCache, this.logger, this.performanceClient, initCorrelationId)(initCorrelationId);
16290
16545
  if (allowPlatformBroker) {
16291
16546
  try {
16292
- this.nativeExtensionProvider =
16293
- await NativeMessageHandler.createProvider(this.logger, this.config.system.nativeBrokerHandshakeTimeout, this.performanceClient);
16547
+ // check if platform authentication is available via DOM or browser extension and create relevant handlers
16548
+ this.platformAuthProvider = await getPlatformAuthProvider(this.logger, this.performanceClient, initCorrelationId, this.config.system.nativeBrokerHandshakeTimeout);
16294
16549
  }
16295
16550
  catch (e) {
16296
16551
  this.logger.verbose(e);
@@ -16360,18 +16615,15 @@
16360
16615
  }
16361
16616
  const loggedInAccounts = this.getAllAccounts();
16362
16617
  const platformBrokerRequest = this.browserStorage.getCachedNativeRequest();
16363
- const useNative = platformBrokerRequest &&
16364
- NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeExtensionProvider) &&
16365
- this.nativeExtensionProvider &&
16366
- !hash;
16618
+ const useNative = platformBrokerRequest && this.platformAuthProvider && !hash;
16367
16619
  let rootMeasurement;
16368
16620
  this.eventHandler.emitEvent(EventType.HANDLE_REDIRECT_START, exports.InteractionType.Redirect);
16369
16621
  let redirectResponse;
16370
16622
  try {
16371
- if (useNative && this.nativeExtensionProvider) {
16623
+ if (useNative && this.platformAuthProvider) {
16372
16624
  rootMeasurement = this.performanceClient.startMeasurement(PerformanceEvents.AcquireTokenRedirect, platformBrokerRequest?.correlationId || "");
16373
16625
  this.logger.trace("handleRedirectPromise - acquiring token from native platform");
16374
- 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);
16626
+ const nativeClient = new PlatformAuthInteractionClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, ApiId.handleRedirectPromise, this.performanceClient, this.platformAuthProvider, platformBrokerRequest.accountId, this.nativeInternalStorage, platformBrokerRequest.correlationId);
16375
16627
  redirectResponse = invokeAsync(nativeClient.handleRedirectPromise.bind(nativeClient), PerformanceEvents.HandleNativeRedirectPromiseMeasurement, this.logger, this.performanceClient, rootMeasurement.event.correlationId)(this.performanceClient, rootMeasurement.event.correlationId);
16376
16628
  }
16377
16629
  else {
@@ -16500,15 +16752,15 @@
16500
16752
  this.eventHandler.emitEvent(EventType.LOGIN_START, exports.InteractionType.Redirect, request);
16501
16753
  }
16502
16754
  let result;
16503
- if (this.nativeExtensionProvider &&
16755
+ if (this.platformAuthProvider &&
16504
16756
  this.canUsePlatformBroker(request)) {
16505
- const nativeClient = new NativeInteractionClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, ApiId.acquireTokenRedirect, this.performanceClient, this.nativeExtensionProvider, this.getNativeAccountId(request), this.nativeInternalStorage, correlationId);
16757
+ const nativeClient = new PlatformAuthInteractionClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, ApiId.acquireTokenRedirect, this.performanceClient, this.platformAuthProvider, this.getNativeAccountId(request), this.nativeInternalStorage, correlationId);
16506
16758
  result = nativeClient
16507
16759
  .acquireTokenRedirect(request, atrMeasurement)
16508
16760
  .catch((e) => {
16509
16761
  if (e instanceof NativeAuthError &&
16510
16762
  isFatalNativeAuthError(e)) {
16511
- this.nativeExtensionProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
16763
+ this.platformAuthProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
16512
16764
  const redirectClient = this.createRedirectClient(correlationId);
16513
16765
  return redirectClient.acquireToken(request);
16514
16766
  }
@@ -16589,7 +16841,7 @@
16589
16841
  .catch((e) => {
16590
16842
  if (e instanceof NativeAuthError &&
16591
16843
  isFatalNativeAuthError(e)) {
16592
- this.nativeExtensionProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
16844
+ this.platformAuthProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
16593
16845
  const popupClient = this.createPopupClient(correlationId);
16594
16846
  return popupClient.acquireToken(request, pkce);
16595
16847
  }
@@ -16698,7 +16950,7 @@
16698
16950
  result = this.acquireTokenNative(validRequest, ApiId.ssoSilent).catch((e) => {
16699
16951
  // If native token acquisition fails for availability reasons fallback to standard flow
16700
16952
  if (e instanceof NativeAuthError && isFatalNativeAuthError(e)) {
16701
- this.nativeExtensionProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
16953
+ this.platformAuthProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
16702
16954
  const silentIframeClient = this.createSilentIframeClient(validRequest.correlationId);
16703
16955
  return silentIframeClient.acquireToken(validRequest);
16704
16956
  }
@@ -16800,7 +17052,7 @@
16800
17052
  // If native token acquisition fails for availability reasons fallback to standard flow
16801
17053
  if (e instanceof NativeAuthError &&
16802
17054
  isFatalNativeAuthError(e)) {
16803
- this.nativeExtensionProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
17055
+ this.platformAuthProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
16804
17056
  }
16805
17057
  throw e;
16806
17058
  });
@@ -17058,10 +17310,10 @@
17058
17310
  */
17059
17311
  async acquireTokenNative(request, apiId, accountId, cacheLookupPolicy) {
17060
17312
  this.logger.trace("acquireTokenNative called");
17061
- if (!this.nativeExtensionProvider) {
17313
+ if (!this.platformAuthProvider) {
17062
17314
  throw createBrowserAuthError(nativeConnectionNotEstablished);
17063
17315
  }
17064
- const nativeClient = new NativeInteractionClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, apiId, this.performanceClient, this.nativeExtensionProvider, accountId || this.getNativeAccountId(request), this.nativeInternalStorage, request.correlationId);
17316
+ const nativeClient = new PlatformAuthInteractionClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, apiId, this.performanceClient, this.platformAuthProvider, accountId || this.getNativeAccountId(request), this.nativeInternalStorage, request.correlationId);
17065
17317
  return nativeClient.acquireToken(request, cacheLookupPolicy);
17066
17318
  }
17067
17319
  /**
@@ -17070,8 +17322,12 @@
17070
17322
  */
17071
17323
  canUsePlatformBroker(request, accountId) {
17072
17324
  this.logger.trace("canUsePlatformBroker called");
17073
- if (!NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeExtensionProvider, request.authenticationScheme)) {
17074
- this.logger.trace("canUsePlatformBroker: isPlatformBrokerAvailable returned false, returning false");
17325
+ if (!this.platformAuthProvider) {
17326
+ this.logger.trace("canUsePlatformBroker: platform broker unavilable, returning false");
17327
+ return false;
17328
+ }
17329
+ if (!isPlatformAuthAllowed(this.config, this.logger, this.platformAuthProvider, request.authenticationScheme)) {
17330
+ this.logger.trace("canUsePlatformBroker: isBrokerAvailable returned false, returning false");
17075
17331
  return false;
17076
17332
  }
17077
17333
  if (request.prompt) {
@@ -17111,39 +17367,39 @@
17111
17367
  * @param correlationId
17112
17368
  */
17113
17369
  createPopupClient(correlationId) {
17114
- return new PopupClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, this.performanceClient, this.nativeInternalStorage, this.nativeExtensionProvider, correlationId);
17370
+ return new PopupClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, this.performanceClient, this.nativeInternalStorage, this.platformAuthProvider, correlationId);
17115
17371
  }
17116
17372
  /**
17117
17373
  * Returns new instance of the Redirect Interaction Client
17118
17374
  * @param correlationId
17119
17375
  */
17120
17376
  createRedirectClient(correlationId) {
17121
- return new RedirectClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, this.performanceClient, this.nativeInternalStorage, this.nativeExtensionProvider, correlationId);
17377
+ return new RedirectClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, this.performanceClient, this.nativeInternalStorage, this.platformAuthProvider, correlationId);
17122
17378
  }
17123
17379
  /**
17124
17380
  * Returns new instance of the Silent Iframe Interaction Client
17125
17381
  * @param correlationId
17126
17382
  */
17127
17383
  createSilentIframeClient(correlationId) {
17128
- return new SilentIframeClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, ApiId.ssoSilent, this.performanceClient, this.nativeInternalStorage, this.nativeExtensionProvider, correlationId);
17384
+ return new SilentIframeClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, ApiId.ssoSilent, this.performanceClient, this.nativeInternalStorage, this.platformAuthProvider, correlationId);
17129
17385
  }
17130
17386
  /**
17131
17387
  * Returns new instance of the Silent Cache Interaction Client
17132
17388
  */
17133
17389
  createSilentCacheClient(correlationId) {
17134
- return new SilentCacheClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, this.performanceClient, this.nativeExtensionProvider, correlationId);
17390
+ return new SilentCacheClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, this.performanceClient, this.platformAuthProvider, correlationId);
17135
17391
  }
17136
17392
  /**
17137
17393
  * Returns new instance of the Silent Refresh Interaction Client
17138
17394
  */
17139
17395
  createSilentRefreshClient(correlationId) {
17140
- return new SilentRefreshClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, this.performanceClient, this.nativeExtensionProvider, correlationId);
17396
+ return new SilentRefreshClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, this.performanceClient, this.platformAuthProvider, correlationId);
17141
17397
  }
17142
17398
  /**
17143
17399
  * Returns new instance of the Silent AuthCode Interaction Client
17144
17400
  */
17145
17401
  createSilentAuthCodeClient(correlationId) {
17146
- return new SilentAuthCodeClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, ApiId.acquireTokenByCode, this.performanceClient, this.nativeExtensionProvider, correlationId);
17402
+ return new SilentAuthCodeClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, ApiId.acquireTokenByCode, this.performanceClient, this.platformAuthProvider, correlationId);
17147
17403
  }
17148
17404
  /**
17149
17405
  * Adds event callbacks to array
@@ -17489,14 +17745,14 @@
17489
17745
  */
17490
17746
  async acquireTokenSilentNoIframe(silentRequest, cacheLookupPolicy) {
17491
17747
  // if the cache policy is set to access_token only, we should not be hitting the native layer yet
17492
- if (NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeExtensionProvider, silentRequest.authenticationScheme) &&
17748
+ if (isPlatformAuthAllowed(this.config, this.logger, this.platformAuthProvider, silentRequest.authenticationScheme) &&
17493
17749
  silentRequest.account.nativeAccountId) {
17494
17750
  this.logger.verbose("acquireTokenSilent - attempting to acquire token from native platform");
17495
17751
  return this.acquireTokenNative(silentRequest, ApiId.acquireTokenSilent_silentFlow, silentRequest.account.nativeAccountId, cacheLookupPolicy).catch(async (e) => {
17496
17752
  // If native token acquisition fails for availability reasons fallback to web flow
17497
17753
  if (e instanceof NativeAuthError && isFatalNativeAuthError(e)) {
17498
17754
  this.logger.verbose("acquireTokenSilent - native platform unavailable, falling back to web flow");
17499
- this.nativeExtensionProvider = undefined; // Prevent future requests from continuing to attempt
17755
+ this.platformAuthProvider = undefined; // Prevent future requests from continuing to attempt
17500
17756
  // Cache will not contain tokens, given that previous WAM requests succeeded. Skip cache and RT renewal and go straight to iframe renewal
17501
17757
  throw createClientAuthError(tokenRefreshRequired);
17502
17758
  }
@@ -17539,6 +17795,23 @@
17539
17795
  this.performanceClient.addFields({ usePreGeneratedPkce: !!res }, correlationId);
17540
17796
  return res;
17541
17797
  }
17798
+ logMultipleInstances(performanceEvent) {
17799
+ const clientId = this.config.auth.clientId;
17800
+ if (!window)
17801
+ return;
17802
+ // @ts-ignore
17803
+ window.msal = window.msal || {};
17804
+ // @ts-ignore
17805
+ window.msal.clientIds = window.msal.clientIds || [];
17806
+ // @ts-ignore
17807
+ const clientIds = window.msal.clientIds;
17808
+ if (clientIds.length > 0) {
17809
+ this.logger.verbose("There is already an instance of MSAL.js in the window.");
17810
+ }
17811
+ // @ts-ignore
17812
+ window.msal.clientIds.push(clientId);
17813
+ collectInstanceStats(clientId, performanceEvent, this.logger);
17814
+ }
17542
17815
  }
17543
17816
  /**
17544
17817
  * Determines whether an error thrown by the refresh token endpoint can be resolved without interaction
@@ -17825,7 +18098,9 @@
17825
18098
  * Specific implementation of initialize function for NestedAppAuthController
17826
18099
  * @returns
17827
18100
  */
17828
- async initialize(request) {
18101
+ async initialize(request,
18102
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
18103
+ isBroker) {
17829
18104
  const initCorrelationId = request?.correlationId || createNewGuid();
17830
18105
  await this.browserStorage.initialize(initCorrelationId);
17831
18106
  return Promise.resolve();
@@ -18347,6 +18622,7 @@
18347
18622
  * @param IController Optional parameter to explictly set the controller. (Will be removed when we remove public constructor)
18348
18623
  */
18349
18624
  constructor(configuration, controller) {
18625
+ this.isBroker = false;
18350
18626
  this.controller =
18351
18627
  controller ||
18352
18628
  new StandardController(new StandardOperatingContext(configuration));
@@ -18356,7 +18632,7 @@
18356
18632
  * @param request {?InitializeApplicationRequest}
18357
18633
  */
18358
18634
  async initialize(request) {
18359
- return this.controller.initialize(request);
18635
+ return this.controller.initialize(request, this.isBroker);
18360
18636
  }
18361
18637
  /**
18362
18638
  * Use when you want to obtain an access_token for your API via opening a popup window in the user's browser
@@ -19859,6 +20135,7 @@
19859
20135
  exports.WrapperSKU = WrapperSKU;
19860
20136
  exports.createNestablePublicClientApplication = createNestablePublicClientApplication;
19861
20137
  exports.createStandardPublicClientApplication = createStandardPublicClientApplication;
20138
+ exports.isPlatformBrokerAvailable = isPlatformBrokerAvailable;
19862
20139
  exports.stubbedPublicClientApplication = stubbedPublicClientApplication;
19863
20140
  exports.version = version;
19864
20141