@azure/msal-browser 4.12.0 → 4.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. package/dist/app/IPublicClientApplication.mjs +1 -1
  2. package/dist/app/PublicClientApplication.mjs +1 -1
  3. package/dist/app/PublicClientNext.mjs +1 -1
  4. package/dist/broker/nativeBroker/IPlatformAuthHandler.d.ts +12 -0
  5. package/dist/broker/nativeBroker/IPlatformAuthHandler.d.ts.map +1 -0
  6. package/dist/broker/nativeBroker/NativeStatusCodes.mjs +1 -1
  7. package/dist/broker/nativeBroker/PlatformAuthDOMHandler.d.ts +30 -0
  8. package/dist/broker/nativeBroker/PlatformAuthDOMHandler.d.ts.map +1 -0
  9. package/dist/broker/nativeBroker/PlatformAuthDOMHandler.mjs +143 -0
  10. package/dist/broker/nativeBroker/PlatformAuthDOMHandler.mjs.map +1 -0
  11. package/dist/broker/nativeBroker/{NativeMessageHandler.d.ts → PlatformAuthExtensionHandler.d.ts} +16 -16
  12. package/dist/broker/nativeBroker/PlatformAuthExtensionHandler.d.ts.map +1 -0
  13. package/dist/broker/nativeBroker/{NativeMessageHandler.mjs → PlatformAuthExtensionHandler.mjs} +66 -58
  14. package/dist/broker/nativeBroker/PlatformAuthExtensionHandler.mjs.map +1 -0
  15. package/dist/broker/nativeBroker/PlatformAuthProvider.d.ts +26 -0
  16. package/dist/broker/nativeBroker/PlatformAuthProvider.d.ts.map +1 -0
  17. package/dist/broker/nativeBroker/PlatformAuthProvider.mjs +108 -0
  18. package/dist/broker/nativeBroker/PlatformAuthProvider.mjs.map +1 -0
  19. package/dist/broker/nativeBroker/{NativeRequest.d.ts → PlatformAuthRequest.d.ts} +34 -3
  20. package/dist/broker/nativeBroker/PlatformAuthRequest.d.ts.map +1 -0
  21. package/dist/broker/nativeBroker/{NativeResponse.d.ts → PlatformAuthResponse.d.ts} +24 -2
  22. package/dist/broker/nativeBroker/PlatformAuthResponse.d.ts.map +1 -0
  23. package/dist/cache/AccountManager.mjs +1 -1
  24. package/dist/cache/AsyncMemoryStorage.mjs +1 -1
  25. package/dist/cache/BrowserCacheManager.d.ts +6 -2
  26. package/dist/cache/BrowserCacheManager.d.ts.map +1 -1
  27. package/dist/cache/BrowserCacheManager.mjs +17 -2
  28. package/dist/cache/BrowserCacheManager.mjs.map +1 -1
  29. package/dist/cache/CacheHelpers.mjs +1 -1
  30. package/dist/cache/CookieStorage.mjs +1 -1
  31. package/dist/cache/DatabaseStorage.mjs +1 -1
  32. package/dist/cache/LocalStorage.mjs +1 -1
  33. package/dist/cache/MemoryStorage.mjs +1 -1
  34. package/dist/cache/SessionStorage.mjs +1 -1
  35. package/dist/cache/TokenCache.mjs +1 -1
  36. package/dist/config/Configuration.mjs +1 -1
  37. package/dist/controllers/ControllerFactory.mjs +1 -1
  38. package/dist/controllers/NestedAppAuthController.mjs +1 -1
  39. package/dist/controllers/StandardController.d.ts +2 -2
  40. package/dist/controllers/StandardController.d.ts.map +1 -1
  41. package/dist/controllers/StandardController.mjs +30 -29
  42. package/dist/controllers/StandardController.mjs.map +1 -1
  43. package/dist/controllers/UnknownOperatingContextController.mjs +1 -1
  44. package/dist/crypto/BrowserCrypto.mjs +1 -1
  45. package/dist/crypto/CryptoOps.mjs +1 -1
  46. package/dist/crypto/PkceGenerator.mjs +1 -1
  47. package/dist/crypto/SignedHttpRequest.mjs +1 -1
  48. package/dist/encode/Base64Decode.mjs +1 -1
  49. package/dist/encode/Base64Encode.mjs +1 -1
  50. package/dist/error/BrowserAuthError.mjs +1 -1
  51. package/dist/error/BrowserAuthErrorCodes.mjs +1 -1
  52. package/dist/error/BrowserConfigurationAuthError.mjs +1 -1
  53. package/dist/error/BrowserConfigurationAuthErrorCodes.mjs +1 -1
  54. package/dist/error/NativeAuthError.mjs +1 -1
  55. package/dist/error/NativeAuthErrorCodes.mjs +1 -1
  56. package/dist/error/NestedAppAuthError.mjs +1 -1
  57. package/dist/event/EventHandler.mjs +1 -1
  58. package/dist/event/EventMessage.d.ts +10 -1
  59. package/dist/event/EventMessage.d.ts.map +1 -1
  60. package/dist/event/EventMessage.mjs +1 -1
  61. package/dist/event/EventMessage.mjs.map +1 -1
  62. package/dist/event/EventType.d.ts +1 -0
  63. package/dist/event/EventType.d.ts.map +1 -1
  64. package/dist/event/EventType.mjs +2 -1
  65. package/dist/event/EventType.mjs.map +1 -1
  66. package/dist/index.d.ts +2 -1
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.mjs +2 -1
  69. package/dist/index.mjs.map +1 -1
  70. package/dist/interaction_client/BaseInteractionClient.d.ts +3 -3
  71. package/dist/interaction_client/BaseInteractionClient.d.ts.map +1 -1
  72. package/dist/interaction_client/BaseInteractionClient.mjs +3 -3
  73. package/dist/interaction_client/HybridSpaAuthorizationCodeClient.mjs +1 -1
  74. package/dist/interaction_client/{NativeInteractionClient.d.ts → PlatformAuthInteractionClient.d.ts} +21 -23
  75. package/dist/interaction_client/PlatformAuthInteractionClient.d.ts.map +1 -0
  76. package/dist/interaction_client/{NativeInteractionClient.mjs → PlatformAuthInteractionClient.mjs} +80 -111
  77. package/dist/interaction_client/PlatformAuthInteractionClient.mjs.map +1 -0
  78. package/dist/interaction_client/PopupClient.d.ts +2 -2
  79. package/dist/interaction_client/PopupClient.d.ts.map +1 -1
  80. package/dist/interaction_client/PopupClient.mjs +7 -7
  81. package/dist/interaction_client/PopupClient.mjs.map +1 -1
  82. package/dist/interaction_client/RedirectClient.d.ts +2 -2
  83. package/dist/interaction_client/RedirectClient.d.ts.map +1 -1
  84. package/dist/interaction_client/RedirectClient.mjs +7 -8
  85. package/dist/interaction_client/RedirectClient.mjs.map +1 -1
  86. package/dist/interaction_client/SilentAuthCodeClient.d.ts +2 -2
  87. package/dist/interaction_client/SilentAuthCodeClient.d.ts.map +1 -1
  88. package/dist/interaction_client/SilentAuthCodeClient.mjs +3 -3
  89. package/dist/interaction_client/SilentCacheClient.mjs +1 -1
  90. package/dist/interaction_client/SilentIframeClient.d.ts +2 -2
  91. package/dist/interaction_client/SilentIframeClient.d.ts.map +1 -1
  92. package/dist/interaction_client/SilentIframeClient.mjs +7 -8
  93. package/dist/interaction_client/SilentIframeClient.mjs.map +1 -1
  94. package/dist/interaction_client/SilentRefreshClient.mjs +1 -1
  95. package/dist/interaction_client/StandardInteractionClient.mjs +1 -1
  96. package/dist/interaction_handler/InteractionHandler.mjs +1 -1
  97. package/dist/interaction_handler/SilentHandler.mjs +1 -1
  98. package/dist/naa/BridgeError.mjs +1 -1
  99. package/dist/naa/BridgeProxy.mjs +1 -1
  100. package/dist/naa/BridgeStatusCode.mjs +1 -1
  101. package/dist/naa/mapping/NestedAppAuthAdapter.mjs +1 -1
  102. package/dist/navigation/NavigationClient.mjs +3 -3
  103. package/dist/navigation/NavigationClient.mjs.map +1 -1
  104. package/dist/network/FetchClient.mjs +1 -1
  105. package/dist/operatingcontext/BaseOperatingContext.mjs +1 -1
  106. package/dist/operatingcontext/NestedAppOperatingContext.mjs +1 -1
  107. package/dist/operatingcontext/StandardOperatingContext.mjs +1 -1
  108. package/dist/operatingcontext/UnknownOperatingContext.mjs +1 -1
  109. package/dist/packageMetadata.d.ts +1 -1
  110. package/dist/packageMetadata.mjs +2 -2
  111. package/dist/protocol/Authorize.d.ts +4 -4
  112. package/dist/protocol/Authorize.d.ts.map +1 -1
  113. package/dist/protocol/Authorize.mjs +10 -9
  114. package/dist/protocol/Authorize.mjs.map +1 -1
  115. package/dist/request/RequestHelpers.mjs +1 -1
  116. package/dist/response/ResponseHandler.mjs +1 -1
  117. package/dist/telemetry/BrowserPerformanceClient.mjs +1 -1
  118. package/dist/telemetry/BrowserPerformanceMeasurement.mjs +1 -1
  119. package/dist/utils/BrowserConstants.d.ts +8 -1
  120. package/dist/utils/BrowserConstants.d.ts.map +1 -1
  121. package/dist/utils/BrowserConstants.mjs +11 -4
  122. package/dist/utils/BrowserConstants.mjs.map +1 -1
  123. package/dist/utils/BrowserProtocolUtils.mjs +1 -1
  124. package/dist/utils/BrowserUtils.mjs +1 -1
  125. package/dist/utils/MsalFrameStatsUtils.mjs +1 -1
  126. package/lib/msal-browser.cjs +1541 -1320
  127. package/lib/msal-browser.cjs.map +1 -1
  128. package/lib/msal-browser.js +1541 -1320
  129. package/lib/msal-browser.js.map +1 -1
  130. package/lib/msal-browser.min.js +66 -66
  131. package/lib/types/broker/nativeBroker/IPlatformAuthHandler.d.ts +12 -0
  132. package/lib/types/broker/nativeBroker/IPlatformAuthHandler.d.ts.map +1 -0
  133. package/lib/types/broker/nativeBroker/PlatformAuthDOMHandler.d.ts +30 -0
  134. package/lib/types/broker/nativeBroker/PlatformAuthDOMHandler.d.ts.map +1 -0
  135. package/lib/types/broker/nativeBroker/{NativeMessageHandler.d.ts → PlatformAuthExtensionHandler.d.ts} +16 -16
  136. package/lib/types/broker/nativeBroker/PlatformAuthExtensionHandler.d.ts.map +1 -0
  137. package/lib/types/broker/nativeBroker/PlatformAuthProvider.d.ts +26 -0
  138. package/lib/types/broker/nativeBroker/PlatformAuthProvider.d.ts.map +1 -0
  139. package/lib/types/broker/nativeBroker/{NativeRequest.d.ts → PlatformAuthRequest.d.ts} +34 -3
  140. package/lib/types/broker/nativeBroker/PlatformAuthRequest.d.ts.map +1 -0
  141. package/lib/types/broker/nativeBroker/{NativeResponse.d.ts → PlatformAuthResponse.d.ts} +24 -2
  142. package/lib/types/broker/nativeBroker/PlatformAuthResponse.d.ts.map +1 -0
  143. package/lib/types/cache/BrowserCacheManager.d.ts +6 -2
  144. package/lib/types/cache/BrowserCacheManager.d.ts.map +1 -1
  145. package/lib/types/controllers/StandardController.d.ts +2 -2
  146. package/lib/types/controllers/StandardController.d.ts.map +1 -1
  147. package/lib/types/event/EventMessage.d.ts +10 -1
  148. package/lib/types/event/EventMessage.d.ts.map +1 -1
  149. package/lib/types/event/EventType.d.ts +1 -0
  150. package/lib/types/event/EventType.d.ts.map +1 -1
  151. package/lib/types/index.d.ts +2 -1
  152. package/lib/types/index.d.ts.map +1 -1
  153. package/lib/types/interaction_client/BaseInteractionClient.d.ts +3 -3
  154. package/lib/types/interaction_client/BaseInteractionClient.d.ts.map +1 -1
  155. package/lib/types/interaction_client/{NativeInteractionClient.d.ts → PlatformAuthInteractionClient.d.ts} +21 -23
  156. package/lib/types/interaction_client/PlatformAuthInteractionClient.d.ts.map +1 -0
  157. package/lib/types/interaction_client/PopupClient.d.ts +2 -2
  158. package/lib/types/interaction_client/PopupClient.d.ts.map +1 -1
  159. package/lib/types/interaction_client/RedirectClient.d.ts +2 -2
  160. package/lib/types/interaction_client/RedirectClient.d.ts.map +1 -1
  161. package/lib/types/interaction_client/SilentAuthCodeClient.d.ts +2 -2
  162. package/lib/types/interaction_client/SilentAuthCodeClient.d.ts.map +1 -1
  163. package/lib/types/interaction_client/SilentIframeClient.d.ts +2 -2
  164. package/lib/types/interaction_client/SilentIframeClient.d.ts.map +1 -1
  165. package/lib/types/packageMetadata.d.ts +1 -1
  166. package/lib/types/protocol/Authorize.d.ts +4 -4
  167. package/lib/types/protocol/Authorize.d.ts.map +1 -1
  168. package/lib/types/utils/BrowserConstants.d.ts +8 -1
  169. package/lib/types/utils/BrowserConstants.d.ts.map +1 -1
  170. package/package.json +2 -2
  171. package/src/broker/nativeBroker/IPlatformAuthHandler.ts +17 -0
  172. package/src/broker/nativeBroker/PlatformAuthDOMHandler.ts +248 -0
  173. package/src/broker/nativeBroker/{NativeMessageHandler.ts → PlatformAuthExtensionHandler.ts} +90 -79
  174. package/src/broker/nativeBroker/PlatformAuthProvider.ts +164 -0
  175. package/src/broker/nativeBroker/{NativeRequest.ts → PlatformAuthRequest.ts} +41 -2
  176. package/src/broker/nativeBroker/{NativeResponse.ts → PlatformAuthResponse.ts} +25 -1
  177. package/src/cache/BrowserCacheManager.ts +27 -3
  178. package/src/controllers/StandardController.ts +51 -45
  179. package/src/event/EventMessage.ts +11 -0
  180. package/src/event/EventType.ts +1 -0
  181. package/src/index.ts +3 -0
  182. package/src/interaction_client/BaseInteractionClient.ts +4 -4
  183. package/src/interaction_client/{NativeInteractionClient.ts → PlatformAuthInteractionClient.ts} +136 -167
  184. package/src/interaction_client/PopupClient.ts +8 -7
  185. package/src/interaction_client/RedirectClient.ts +12 -12
  186. package/src/interaction_client/SilentAuthCodeClient.ts +3 -3
  187. package/src/interaction_client/SilentIframeClient.ts +12 -12
  188. package/src/navigation/NavigationClient.ts +2 -2
  189. package/src/packageMetadata.ts +1 -1
  190. package/src/protocol/Authorize.ts +12 -10
  191. package/src/utils/BrowserConstants.ts +9 -1
  192. package/dist/broker/nativeBroker/NativeMessageHandler.d.ts.map +0 -1
  193. package/dist/broker/nativeBroker/NativeMessageHandler.mjs.map +0 -1
  194. package/dist/broker/nativeBroker/NativeRequest.d.ts.map +0 -1
  195. package/dist/broker/nativeBroker/NativeResponse.d.ts.map +0 -1
  196. package/dist/interaction_client/NativeInteractionClient.d.ts.map +0 -1
  197. package/dist/interaction_client/NativeInteractionClient.mjs.map +0 -1
  198. package/lib/types/broker/nativeBroker/NativeMessageHandler.d.ts.map +0 -1
  199. package/lib/types/broker/nativeBroker/NativeRequest.d.ts.map +0 -1
  200. package/lib/types/broker/nativeBroker/NativeResponse.d.ts.map +0 -1
  201. package/lib/types/interaction_client/NativeInteractionClient.d.ts.map +0 -1
@@ -1,4 +1,4 @@
1
- /*! @azure/msal-browser v4.12.0 2025-05-06 */
1
+ /*! @azure/msal-browser v4.13.1 2025-06-10 */
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.6.0 2025-05-06 */
9
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
305
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
322
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
371
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
469
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
721
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
760
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
951
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
959
952
  /* eslint-disable header/header */
960
953
  const name$1 = "@azure/msal-common";
961
- const version$1 = "15.6.0";
954
+ const version$1 = "15.7.0";
962
955
 
963
- /*! @azure/msal-common v15.6.0 2025-05-06 */
956
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
976
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
1037
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
1092
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
1419
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
1473
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
1611
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
1708
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
1899
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
1939
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
2018
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
2033
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
2055
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
2079
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
2322
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
2387
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
2551
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
2691
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
2699
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
2726
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
3911
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
4011
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
4021
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
4071
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
4439
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
4451
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
4461
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
4471
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
4984
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
5080
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
5186
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
6025
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
6056
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
6075
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
6096
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
6183
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
6214
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
6362
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
6388
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
6476
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
6548
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
6632
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
6659
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
6990
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
7057
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
7075
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
7308
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
7517
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
7615
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
7630
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
7854
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
7912
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
8175
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
8183
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
8208
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
8248
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.6.0 2025-05-06 */
8327
+ /*! @azure/msal-common v15.7.0 2025-06-10 */
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.
@@ -10167,10 +10164,10 @@
10167
10164
  */
10168
10165
  static defaultNavigateWindow(url, options) {
10169
10166
  if (options.noHistory) {
10170
- window.location.replace(url);
10167
+ window.location.replace(url); // CodeQL [SM03712] Application owner controls the URL. User can't change it.
10171
10168
  }
10172
10169
  else {
10173
- window.location.assign(url);
10170
+ window.location.assign(url); // CodeQL [SM03712] Application owner controls the URL. User can't change it.
10174
10171
  }
10175
10172
  return new Promise((resolve) => {
10176
10173
  setTimeout(() => {
@@ -10432,7 +10429,7 @@
10432
10429
 
10433
10430
  /* eslint-disable header/header */
10434
10431
  const name = "@azure/msal-browser";
10435
- const version = "4.12.0";
10432
+ const version = "4.13.1";
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.
@@ -12888,14 +12900,14 @@
12888
12900
  * Licensed under the MIT License.
12889
12901
  */
12890
12902
  class BaseInteractionClient {
12891
- constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeMessageHandler, correlationId) {
12903
+ constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, platformAuthProvider, correlationId) {
12892
12904
  this.config = config;
12893
12905
  this.browserStorage = storageImpl;
12894
12906
  this.browserCrypto = browserCrypto;
12895
12907
  this.networkClient = this.config.system.networkClient;
12896
12908
  this.eventHandler = eventHandler;
12897
12909
  this.navigationClient = navigationClient;
12898
- this.nativeMessageHandler = nativeMessageHandler;
12910
+ this.platformAuthProvider = platformAuthProvider;
12899
12911
  this.correlationId = correlationId || createNewGuid();
12900
12912
  this.logger = logger.clone(BrowserConstants.MSAL_SKU, version, this.correlationId);
12901
12913
  this.performanceClient = performanceClient;
@@ -13251,6 +13263,159 @@
13251
13263
  }
13252
13264
  }
13253
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
+
13254
13419
  /*
13255
13420
  * Copyright (c) Microsoft Corporation. All rights reserved.
13256
13421
  * Licensed under the MIT License.
@@ -13335,930 +13500,1153 @@
13335
13500
  * Copyright (c) Microsoft Corporation. All rights reserved.
13336
13501
  * Licensed under the MIT License.
13337
13502
  */
13338
- class NativeMessageHandler {
13339
- constructor(logger, handshakeTimeoutMs, performanceClient, extensionId) {
13340
- this.logger = logger;
13341
- this.handshakeTimeoutMs = handshakeTimeoutMs;
13342
- this.extensionId = extensionId;
13343
- this.resolvers = new Map(); // Used for non-handshake messages
13344
- this.handshakeResolvers = new Map(); // Used for handshake messages
13345
- this.messageChannel = new MessageChannel();
13346
- this.windowListener = this.onWindowMessage.bind(this); // Window event callback doesn't have access to 'this' unless it's bound
13347
- this.performanceClient = performanceClient;
13348
- this.handshakeEvent = performanceClient.startMeasurement(PerformanceEvents.NativeMessageHandlerHandshake);
13349
- }
13503
+ class SilentCacheClient extends StandardInteractionClient {
13350
13504
  /**
13351
- * Sends a given message to the extension and resolves with the extension response
13352
- * @param body
13505
+ * Returns unexpired tokens from the cache, if available
13506
+ * @param silentRequest
13353
13507
  */
13354
- async sendMessage(body) {
13355
- this.logger.trace("NativeMessageHandler - sendMessage called.");
13356
- const req = {
13357
- channel: NativeConstants.CHANNEL_ID,
13358
- extensionId: this.extensionId,
13359
- responseId: createNewGuid(),
13360
- body: body,
13361
- };
13362
- this.logger.trace("NativeMessageHandler - Sending request to browser extension");
13363
- this.logger.tracePii(`NativeMessageHandler - Sending request to browser extension: ${JSON.stringify(req)}`);
13364
- this.messageChannel.port1.postMessage(req);
13365
- return new Promise((resolve, reject) => {
13366
- 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,
13367
13517
  });
13368
- }
13369
- /**
13370
- * Returns an instance of the MessageHandler that has successfully established a connection with an extension
13371
- * @param {Logger} logger
13372
- * @param {number} handshakeTimeoutMs
13373
- * @param {IPerformanceClient} performanceClient
13374
- * @param {ICrypto} crypto
13375
- */
13376
- static async createProvider(logger, handshakeTimeoutMs, performanceClient) {
13377
- logger.trace("NativeMessageHandler - createProvider called.");
13518
+ const silentAuthClient = new SilentFlowClient(clientConfig, this.performanceClient);
13519
+ this.logger.verbose("Silent auth client created");
13378
13520
  try {
13379
- const preferredProvider = new NativeMessageHandler(logger, handshakeTimeoutMs, performanceClient, NativeConstants.PREFERRED_EXTENSION_ID);
13380
- await preferredProvider.sendHandshakeRequest();
13381
- 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;
13382
13527
  }
13383
- catch (e) {
13384
- // If preferred extension fails for whatever reason, fallback to using any installed extension
13385
- const backupProvider = new NativeMessageHandler(logger, handshakeTimeoutMs, performanceClient);
13386
- await backupProvider.sendHandshakeRequest();
13387
- 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;
13388
13534
  }
13389
13535
  }
13390
13536
  /**
13391
- * Send handshake request helper.
13537
+ * API to silenty clear the browser cache.
13538
+ * @param logoutRequest
13392
13539
  */
13393
- async sendHandshakeRequest() {
13394
- this.logger.trace("NativeMessageHandler - sendHandshakeRequest called.");
13395
- // Register this event listener before sending handshake
13396
- window.addEventListener("message", this.windowListener, false); // false is important, because content script message processing should work first
13397
- const req = {
13398
- channel: NativeConstants.CHANNEL_ID,
13399
- extensionId: this.extensionId,
13400
- responseId: createNewGuid(),
13401
- body: {
13402
- method: NativeExtensionMethod.HandshakeRequest,
13403
- },
13404
- };
13405
- this.handshakeEvent.add({
13406
- extensionId: this.extensionId,
13407
- extensionHandshakeTimeoutMs: this.handshakeTimeoutMs,
13408
- });
13409
- this.messageChannel.port1.onmessage = (event) => {
13410
- this.onChannelMessage(event);
13411
- };
13412
- window.postMessage(req, window.origin, [this.messageChannel.port2]);
13413
- return new Promise((resolve, reject) => {
13414
- this.handshakeResolvers.set(req.responseId, { resolve, reject });
13415
- this.timeoutId = window.setTimeout(() => {
13416
- /*
13417
- * Throw an error if neither HandshakeResponse nor original Handshake request are received in a reasonable timeframe.
13418
- * This typically suggests an event handler stopped propagation of the Handshake request but did not respond to it on the MessageChannel port
13419
- */
13420
- window.removeEventListener("message", this.windowListener, false);
13421
- this.messageChannel.port1.close();
13422
- this.messageChannel.port2.close();
13423
- this.handshakeEvent.end({
13424
- extensionHandshakeTimedOut: true,
13425
- success: false,
13426
- });
13427
- reject(createBrowserAuthError(nativeHandshakeTimeout));
13428
- this.handshakeResolvers.delete(req.responseId);
13429
- }, 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(),
13430
13565
  });
13431
13566
  }
13432
13567
  /**
13433
- * Invoked when a message is posted to the window. If a handshake request is received it means the extension is not installed.
13434
- * @param event
13568
+ * Adds SKUs to request extra query parameters
13569
+ * @param request {PlatformAuthRequest}
13570
+ * @private
13435
13571
  */
13436
- onWindowMessage(event) {
13437
- this.logger.trace("NativeMessageHandler - onWindowMessage called");
13438
- // We only accept messages from ourselves
13439
- if (event.source !== window) {
13440
- return;
13441
- }
13442
- const request = event.data;
13443
- if (!request.channel ||
13444
- request.channel !== NativeConstants.CHANNEL_ID) {
13445
- return;
13446
- }
13447
- if (request.extensionId && request.extensionId !== this.extensionId) {
13448
- return;
13449
- }
13450
- if (request.body.method === NativeExtensionMethod.HandshakeRequest) {
13451
- const handshakeResolver = this.handshakeResolvers.get(request.responseId);
13452
- /*
13453
- * Filter out responses with no matched resolvers sooner to keep channel ports open while waiting for
13454
- * the proper response.
13455
- */
13456
- if (!handshakeResolver) {
13457
- this.logger.trace(`NativeMessageHandler.onWindowMessage - resolver can't be found for request ${request.responseId}`);
13458
- return;
13459
- }
13460
- // If we receive this message back it means no extension intercepted the request, meaning no extension supporting handshake protocol is installed
13461
- this.logger.verbose(request.extensionId
13462
- ? `Extension with id: ${request.extensionId} not installed`
13463
- : "No extension installed");
13464
- clearTimeout(this.timeoutId);
13465
- this.messageChannel.port1.close();
13466
- this.messageChannel.port2.close();
13467
- window.removeEventListener("message", this.windowListener, false);
13468
- this.handshakeEvent.end({
13469
- success: false,
13470
- extensionInstalled: false,
13471
- });
13472
- handshakeResolver.reject(createBrowserAuthError(nativeExtensionNotInstalled));
13473
- }
13572
+ addRequestSKUs(request) {
13573
+ request.extraParameters = {
13574
+ ...request.extraParameters,
13575
+ [X_CLIENT_EXTRA_SKU]: this.skus,
13576
+ };
13474
13577
  }
13475
13578
  /**
13476
- * Invoked when a message is received from the extension on the MessageChannel port
13477
- * @param event
13579
+ * Acquire token from native platform via browser extension
13580
+ * @param request
13478
13581
  */
13479
- onChannelMessage(event) {
13480
- this.logger.trace("NativeMessageHandler - onChannelMessage called.");
13481
- const request = event.data;
13482
- const resolver = this.resolvers.get(request.responseId);
13483
- 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);
13484
13589
  try {
13485
- const method = request.body.method;
13486
- if (method === NativeExtensionMethod.Response) {
13487
- if (!resolver) {
13488
- return;
13489
- }
13490
- const response = request.body.response;
13491
- this.logger.trace("NativeMessageHandler - Received response from browser extension");
13492
- this.logger.tracePii(`NativeMessageHandler - Received response from browser extension: ${JSON.stringify(response)}`);
13493
- if (response.status !== "Success") {
13494
- resolver.reject(createNativeAuthError(response.code, response.description, response.ext));
13495
- }
13496
- else if (response.result) {
13497
- if (response.result["code"] &&
13498
- response.result["description"]) {
13499
- resolver.reject(createNativeAuthError(response.result["code"], response.result["description"], response.result["ext"]));
13500
- }
13501
- else {
13502
- resolver.resolve(response.result);
13503
- }
13504
- }
13505
- else {
13506
- throw createAuthError(unexpectedError, "Event does not contain result.");
13507
- }
13508
- 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;
13509
13601
  }
13510
- else if (method === NativeExtensionMethod.HandshakeResponse) {
13511
- if (!handshakeResolver) {
13512
- this.logger.trace(`NativeMessageHandler.onChannelMessage - resolver can't be found for request ${request.responseId}`);
13513
- 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;
13514
13606
  }
13515
- clearTimeout(this.timeoutId); // Clear setTimeout
13516
- window.removeEventListener("message", this.windowListener, false); // Remove 'No extension' listener
13517
- this.extensionId = request.extensionId;
13518
- this.extensionVersion = request.body.version;
13519
- this.logger.verbose(`NativeMessageHandler - Received HandshakeResponse from extension: ${this.extensionId}`);
13520
- this.handshakeEvent.end({
13521
- 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({
13522
13614
  success: true,
13615
+ isNativeBroker: true,
13616
+ requestId: result.requestId,
13523
13617
  });
13524
- handshakeResolver.resolve();
13525
- this.handshakeResolvers.delete(request.responseId);
13526
- }
13527
- // 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
+ });
13528
13630
  }
13529
- catch (err) {
13530
- this.logger.error("Error parsing response from WAM Extension");
13531
- this.logger.errorPii(`Error parsing response from WAM Extension: ${err}`);
13532
- this.logger.errorPii(`Unable to parse ${event}`);
13533
- if (resolver) {
13534
- resolver.reject(err);
13535
- }
13536
- else if (handshakeResolver) {
13537
- handshakeResolver.reject(err);
13631
+ catch (e) {
13632
+ if (e instanceof NativeAuthError) {
13633
+ serverTelemetryManager.setNativeBrokerErrorCode(e.errorCode);
13538
13634
  }
13635
+ throw e;
13539
13636
  }
13540
13637
  }
13541
13638
  /**
13542
- * Returns the Id for the browser extension this handler is communicating with
13543
- * @returns
13639
+ * Creates silent flow request
13640
+ * @param request
13641
+ * @param cachedAccount
13642
+ * @returns CommonSilentFlowRequest
13544
13643
  */
13545
- getExtensionId() {
13546
- 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
+ };
13547
13652
  }
13548
13653
  /**
13549
- * Returns the version for the browser extension this handler is communicating with
13550
- * @returns
13654
+ * Fetches the tokens from the cache if un-expired
13655
+ * @param nativeAccountId
13656
+ * @param request
13657
+ * @returns authenticationResult
13551
13658
  */
13552
- getExtensionVersion() {
13553
- 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
+ }
13554
13688
  }
13555
13689
  /**
13556
- * Returns boolean indicating whether or not the request should attempt to use native broker
13557
- * @param logger
13558
- * @param config
13559
- * @param nativeExtensionProvider
13560
- * @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
13561
13693
  */
13562
- static isPlatformBrokerAvailable(config, logger, nativeExtensionProvider, authenticationScheme) {
13563
- logger.trace("isPlatformBrokerAvailable called");
13564
- if (!config.system.allowPlatformBroker) {
13565
- logger.trace("isPlatformBrokerAvailable: allowPlatformBroker is not enabled, returning false");
13566
- // Developer disabled WAM
13567
- return false;
13568
- }
13569
- if (!nativeExtensionProvider) {
13570
- logger.trace("isPlatformBrokerAvailable: Platform extension provider is not initialized, returning false");
13571
- // Extension is not available
13572
- 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);
13573
13701
  }
13574
- if (authenticationScheme) {
13575
- switch (authenticationScheme) {
13576
- case AuthenticationScheme.BEARER:
13577
- case AuthenticationScheme.POP:
13578
- logger.trace("isPlatformBrokerAvailable: authenticationScheme is supported, returning true");
13579
- return true;
13580
- default:
13581
- logger.trace("isPlatformBrokerAvailable: authenticationScheme is not supported, returning false");
13582
- 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
+ }
13583
13710
  }
13584
13711
  }
13585
- return true;
13586
- }
13587
- }
13588
-
13589
- /*
13590
- * Copyright (c) Microsoft Corporation. All rights reserved.
13591
- * Licensed under the MIT License.
13592
- */
13593
- /**
13594
- * Extracts the BrowserStateObject from the state string.
13595
- * @param browserCrypto
13596
- * @param state
13597
- */
13598
- function extractBrowserRequestState(browserCrypto, state) {
13599
- if (!state) {
13600
- return null;
13601
- }
13602
- try {
13603
- const requestStateObj = ProtocolUtils.parseRequestState(browserCrypto, state);
13604
- return requestStateObj.libraryState.meta;
13605
- }
13606
- catch (e) {
13607
- throw createClientAuthError(invalidState);
13608
- }
13609
- }
13610
-
13611
- /*
13612
- * Copyright (c) Microsoft Corporation. All rights reserved.
13613
- * Licensed under the MIT License.
13614
- */
13615
- function deserializeResponse(responseString, responseLocation, logger) {
13616
- // Deserialize hash fragment response parameters.
13617
- const serverParams = getDeserializedResponse(responseString);
13618
- if (!serverParams) {
13619
- if (!stripLeadingHashOrQuery(responseString)) {
13620
- // Hash or Query string is empty
13621
- 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.`);
13622
- throw createBrowserAuthError(hashEmptyError);
13623
- }
13624
- else {
13625
- 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.`);
13626
- logger.errorPii(`The ${responseLocation} detected is: ${responseString}`);
13627
- throw createBrowserAuthError(hashDoesNotContainKnownProperties);
13628
- }
13629
- }
13630
- return serverParams;
13631
- }
13632
- /**
13633
- * Returns the interaction type that the response object belongs to
13634
- */
13635
- function validateInteractionType(response, browserCrypto, interactionType) {
13636
- if (!response.state) {
13637
- throw createBrowserAuthError(noStateInHash);
13638
- }
13639
- const platformStateObj = extractBrowserRequestState(browserCrypto, response.state);
13640
- if (!platformStateObj) {
13641
- throw createBrowserAuthError(unableToParseState);
13642
- }
13643
- if (platformStateObj.interactionType !== interactionType) {
13644
- throw createBrowserAuthError(stateInteractionTypeMismatch);
13645
- }
13646
- }
13647
-
13648
- /*
13649
- * Copyright (c) Microsoft Corporation. All rights reserved.
13650
- * Licensed under the MIT License.
13651
- */
13652
- /**
13653
- * Abstract class which defines operations for a browser interaction handling class.
13654
- */
13655
- class InteractionHandler {
13656
- constructor(authCodeModule, storageImpl, authCodeRequest, logger, performanceClient) {
13657
- this.authModule = authCodeModule;
13658
- this.browserStorage = storageImpl;
13659
- this.authCodeRequest = authCodeRequest;
13660
- this.logger = logger;
13661
- 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
13662
13723
  }
13663
13724
  /**
13664
- * Function to handle response parameters from hash.
13665
- * @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
13666
13728
  */
13667
- async handleCodeResponse(response, request) {
13668
- this.performanceClient.addQueueMeasurement(PerformanceEvents.HandleCodeResponse, request.correlationId);
13669
- let authCodeResponse;
13670
- try {
13671
- 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;
13672
13734
  }
13673
- catch (e) {
13674
- if (e instanceof ServerError &&
13675
- e.subError === userCancelled) {
13676
- // Translate server error caused by user closing native prompt to corresponding first class MSAL error
13677
- throw createBrowserAuthError(userCancelled);
13678
- }
13679
- else {
13680
- 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);
13681
13741
  }
13742
+ return null;
13682
13743
  }
13683
- return invokeAsync(this.handleCodeResponseFromServer.bind(this), PerformanceEvents.HandleCodeResponseFromServer, this.logger, this.performanceClient, request.correlationId)(authCodeResponse, request);
13684
- }
13685
- /**
13686
- * Process auth code response from AAD
13687
- * @param authCodeResponse
13688
- * @param state
13689
- * @param authority
13690
- * @param networkModule
13691
- * @returns
13692
- */
13693
- async handleCodeResponseFromServer(authCodeResponse, request, validateNonce = true) {
13694
- this.performanceClient.addQueueMeasurement(PerformanceEvents.HandleCodeResponseFromServer, request.correlationId);
13695
- this.logger.trace("InteractionHandler.handleCodeResponseFromServer called");
13696
- // Assign code to request
13697
- this.authCodeRequest.code = authCodeResponse.code;
13698
- // Check for new cloud instance
13699
- if (authCodeResponse.cloud_instance_host_name) {
13700
- await invokeAsync(this.authModule.updateAuthority.bind(this.authModule), PerformanceEvents.UpdateTokenEndpointAuthority, this.logger, this.performanceClient, request.correlationId)(authCodeResponse.cloud_instance_host_name, request.correlationId);
13701
- }
13702
- // Nonce validation not needed when redirect not involved (e.g. hybrid spa, renewing token via rt)
13703
- if (validateNonce) {
13704
- // TODO: Assigning "response nonce" to "request nonce" is confusing. Refactor the function doing validation to accept request nonce directly
13705
- 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.");
13706
13747
  }
13707
- authCodeResponse.state = request.state;
13708
- // Add CCS parameters if available
13709
- if (authCodeResponse.client_info) {
13710
- 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;
13711
13757
  }
13712
- else {
13713
- const ccsCred = this.createCcsCredentials(request);
13714
- if (ccsCred) {
13715
- this.authCodeRequest.ccsCredential = ccsCred;
13716
- }
13758
+ catch (e) {
13759
+ throw e;
13717
13760
  }
13718
- // Acquire token with retrieved code.
13719
- const tokenResponse = (await invokeAsync(this.authModule.acquireToken.bind(this.authModule), PerformanceEvents.AuthClientAcquireToken, this.logger, this.performanceClient, request.correlationId)(this.authCodeRequest, authCodeResponse));
13720
- return tokenResponse;
13721
13761
  }
13722
13762
  /**
13723
- * Build ccs creds if available
13763
+ * Logout from native platform via browser extension
13764
+ * @param request
13724
13765
  */
13725
- createCcsCredentials(request) {
13726
- if (request.account) {
13727
- return {
13728
- credential: request.account.homeAccountId,
13729
- type: CcsCredentialType.HOME_ACCOUNT_ID,
13730
- };
13731
- }
13732
- else if (request.loginHint) {
13733
- return {
13734
- credential: request.loginHint,
13735
- type: CcsCredentialType.UPN,
13736
- };
13737
- }
13738
- return null;
13766
+ logout() {
13767
+ this.logger.trace("NativeInteractionClient - logout called.");
13768
+ return Promise.reject("Logout not implemented yet");
13739
13769
  }
13740
- }
13741
-
13742
- /*
13743
- * Copyright (c) Microsoft Corporation. All rights reserved.
13744
- * Licensed under the MIT License.
13745
- */
13746
- class SilentCacheClient extends StandardInteractionClient {
13747
13770
  /**
13748
- * Returns unexpired tokens from the cache, if available
13749
- * @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
13750
13775
  */
13751
- async acquireToken(silentRequest) {
13752
- this.performanceClient.addQueueMeasurement(PerformanceEvents.SilentCacheClientAcquireToken, silentRequest.correlationId);
13753
- // Telemetry manager only used to increment cacheHits here
13754
- const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenSilent_silentFlow);
13755
- const clientConfig = await invokeAsync(this.getClientConfiguration.bind(this), PerformanceEvents.StandardInteractionClientGetClientConfiguration, this.logger, this.performanceClient, this.correlationId)({
13756
- serverTelemetryManager,
13757
- requestAuthority: silentRequest.authority,
13758
- requestAzureCloudOptions: silentRequest.azureCloudOptions,
13759
- account: silentRequest.account,
13760
- });
13761
- const silentAuthClient = new SilentFlowClient(clientConfig, this.performanceClient);
13762
- this.logger.verbose("Silent auth client created");
13763
- try {
13764
- const response = await invokeAsync(silentAuthClient.acquireCachedToken.bind(silentAuthClient), PerformanceEvents.SilentFlowClientAcquireCachedToken, this.logger, this.performanceClient, silentRequest.correlationId)(silentRequest);
13765
- const authResponse = response[0];
13766
- this.performanceClient.addFields({
13767
- fromCache: true,
13768
- }, silentRequest.correlationId);
13769
- 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");
13770
13788
  }
13771
- catch (error) {
13772
- if (error instanceof BrowserAuthError &&
13773
- error.errorCode === cryptoKeyNotFound) {
13774
- this.logger.verbose("Signing keypair for bound access token not found. Refreshing bound access token and generating a new crypto keypair.");
13775
- }
13776
- 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);
13777
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;
13778
13809
  }
13779
13810
  /**
13780
- * API to silenty clear the browser cache.
13781
- * @param logoutRequest
13811
+ * creates an homeAccountIdentifier for the account
13812
+ * @param response
13813
+ * @param idTokenObj
13814
+ * @returns
13782
13815
  */
13783
- logout(logoutRequest) {
13784
- this.logger.verbose("logoutRedirect called");
13785
- const validLogoutRequest = this.initializeLogoutRequest(logoutRequest);
13786
- return this.clearCacheOnLogout(validLogoutRequest?.account);
13787
- }
13788
- }
13789
-
13790
- /*
13791
- * Copyright (c) Microsoft Corporation. All rights reserved.
13792
- * Licensed under the MIT License.
13793
- */
13794
- class NativeInteractionClient extends BaseInteractionClient {
13795
- constructor(config, browserStorage, browserCrypto, logger, eventHandler, navigationClient, apiId, performanceClient, provider, accountId, nativeStorageImpl, correlationId) {
13796
- super(config, browserStorage, browserCrypto, logger, eventHandler, navigationClient, performanceClient, provider, correlationId);
13797
- this.apiId = apiId;
13798
- this.accountId = accountId;
13799
- this.nativeMessageHandler = provider;
13800
- this.nativeStorageManager = nativeStorageImpl;
13801
- this.silentCacheClient = new SilentCacheClient(config, this.nativeStorageManager, browserCrypto, logger, eventHandler, navigationClient, performanceClient, provider, correlationId);
13802
- const extensionName = this.nativeMessageHandler.getExtensionId() ===
13803
- NativeConstants.PREFERRED_EXTENSION_ID
13804
- ? "chrome"
13805
- : this.nativeMessageHandler.getExtensionId()?.length
13806
- ? "unknown"
13807
- : undefined;
13808
- this.skus = ServerTelemetryManager.makeExtraSkuString({
13809
- libraryName: BrowserConstants.MSAL_SKU,
13810
- libraryVersion: version,
13811
- extensionName: extensionName,
13812
- extensionVersion: this.nativeMessageHandler.getExtensionVersion(),
13813
- });
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;
13814
13820
  }
13815
13821
  /**
13816
- * Adds SKUs to request extra query parameters
13817
- * @param request {NativeTokenRequest}
13818
- * @private
13822
+ * Helper to generate scopes
13823
+ * @param response
13824
+ * @param request
13825
+ * @returns
13819
13826
  */
13820
- addRequestSKUs(request) {
13821
- request.extraParameters = {
13822
- ...request.extraParameters,
13823
- [X_CLIENT_EXTRA_SKU]: this.skus,
13824
- };
13827
+ generateScopes(requestScopes, responseScopes) {
13828
+ return responseScopes
13829
+ ? ScopeSet.fromString(responseScopes)
13830
+ : ScopeSet.fromString(requestScopes);
13825
13831
  }
13826
13832
  /**
13827
- * 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
13828
13834
  * @param request
13835
+ * @param response
13829
13836
  */
13830
- async acquireToken(request, cacheLookupPolicy) {
13831
- this.performanceClient.addQueueMeasurement(PerformanceEvents.NativeInteractionClientAcquireToken, request.correlationId);
13832
- this.logger.trace("NativeInteractionClient - acquireToken called.");
13833
- // start the perf measurement
13834
- const nativeATMeasurement = this.performanceClient.startMeasurement(PerformanceEvents.NativeInteractionClientAcquireToken, request.correlationId);
13835
- const reqTimestamp = nowSeconds();
13836
- const serverTelemetryManager = this.initializeServerTelemetryManager(this.apiId);
13837
- try {
13838
- // initialize native request
13839
- const nativeRequest = await this.initializeNativeRequest(request);
13840
- // check if the tokens can be retrieved from internal cache
13841
- try {
13842
- const result = await this.acquireTokensFromCache(this.accountId, nativeRequest);
13843
- nativeATMeasurement.end({
13844
- success: true,
13845
- isNativeBroker: false,
13846
- fromCache: true,
13847
- });
13848
- return result;
13849
- }
13850
- catch (e) {
13851
- if (cacheLookupPolicy === CacheLookupPolicy.AccessToken) {
13852
- this.logger.info("MSAL internal Cache does not contain tokens, return error as per cache policy");
13853
- throw e;
13854
- }
13855
- // continue with a native call for any and all errors
13856
- 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;
13857
13848
  }
13858
- const { ...nativeTokenRequest } = nativeRequest;
13859
- // fall back to native calls
13860
- const messageBody = {
13861
- method: NativeExtensionMethod.GetToken,
13862
- 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,
13863
13856
  };
13864
- const response = await this.nativeMessageHandler.sendMessage(messageBody);
13865
- const validatedResponse = this.validateNativeResponse(response);
13866
- return await this.handleNativeResponse(validatedResponse, nativeRequest, reqTimestamp)
13867
- .then((result) => {
13868
- nativeATMeasurement.end({
13869
- success: true,
13870
- isNativeBroker: true,
13871
- requestId: result.requestId,
13872
- });
13873
- serverTelemetryManager.clearNativeBrokerErrorCode();
13874
- return result;
13875
- })
13876
- .catch((error) => {
13877
- nativeATMeasurement.end({
13878
- success: false,
13879
- errorCode: error.errorCode,
13880
- subErrorCode: error.subError,
13881
- isNativeBroker: true,
13882
- });
13883
- throw error;
13884
- });
13885
- }
13886
- catch (e) {
13887
- if (e instanceof NativeAuthError) {
13888
- 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);
13889
13863
  }
13890
- throw e;
13864
+ return popTokenGenerator.signPopToken(response.access_token, request.keyId, shrParameters);
13865
+ }
13866
+ else {
13867
+ return response.access_token;
13891
13868
  }
13892
13869
  }
13893
13870
  /**
13894
- * Creates silent flow request
13871
+ * Generates authentication result
13872
+ * @param response
13895
13873
  * @param request
13896
- * @param cachedAccount
13897
- * @returns CommonSilentFlowRequest
13874
+ * @param idTokenObj
13875
+ * @param accountEntity
13876
+ * @param authority
13877
+ * @param reqTimestamp
13878
+ * @returns
13898
13879
  */
13899
- createSilentCacheRequest(request, cachedAccount) {
13900
- return {
13901
- 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,
13902
13920
  correlationId: this.correlationId,
13903
- scopes: ScopeSet.fromString(request.scope).asArray(),
13904
- account: cachedAccount,
13905
- forceRefresh: false,
13921
+ state: response.state,
13922
+ fromNativeBroker: true,
13906
13923
  };
13924
+ return result;
13907
13925
  }
13908
13926
  /**
13909
- * Fetches the tokens from the cache if un-expired
13910
- * @param nativeAccountId
13911
- * @param request
13912
- * @returns authenticationResult
13927
+ * cache the account entity in browser storage
13928
+ * @param accountEntity
13913
13929
  */
13914
- async acquireTokensFromCache(nativeAccountId, request) {
13915
- if (!nativeAccountId) {
13916
- this.logger.warning("NativeInteractionClient:acquireTokensFromCache - No nativeAccountId provided");
13917
- throw createClientAuthError(noAccountFound);
13918
- }
13919
- // fetch the account from browser cache
13920
- const account = this.browserStorage.getBaseAccountInfo({
13921
- 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}`);
13922
13936
  });
13923
- if (!account) {
13924
- throw createClientAuthError(noAccountFound);
13925
- }
13926
- // leverage silent flow for cached tokens retrieval
13927
- try {
13928
- const silentRequest = this.createSilentCacheRequest(request, account);
13929
- const result = await this.silentCacheClient.acquireToken(silentRequest);
13930
- const fullAccount = {
13931
- ...account,
13932
- idTokenClaims: result?.idTokenClaims,
13933
- idToken: result?.idToken,
13934
- };
13935
- return {
13936
- ...result,
13937
- account: fullAccount,
13938
- };
13939
- }
13940
- catch (e) {
13941
- throw e;
13942
- }
13943
13937
  }
13944
13938
  /**
13945
- * Acquires a token from native platform then redirects to the redirectUri instead of returning the response
13946
- * @param {RedirectRequest} request
13947
- * @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
13948
13947
  */
13949
- async acquireTokenRedirect(request, rootMeasurement) {
13950
- this.logger.trace("NativeInteractionClient - acquireTokenRedirect called.");
13951
- const { ...remainingParameters } = request;
13952
- delete remainingParameters.onRedirectNavigate;
13953
- const nativeRequest = await this.initializeNativeRequest(remainingParameters);
13954
- const messageBody = {
13955
- method: NativeExtensionMethod.GetToken,
13956
- 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,
13957
13962
  };
13958
- try {
13959
- const response = await this.nativeMessageHandler.sendMessage(messageBody);
13960
- 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;
13961
13976
  }
13962
- catch (e) {
13963
- // Only throw fatal errors here to allow application to fallback to regular redirect. Otherwise proceed and the error will be thrown in handleRedirectPromise
13964
- if (e instanceof NativeAuthError) {
13965
- const serverTelemetryManager = this.initializeServerTelemetryManager(this.apiId);
13966
- serverTelemetryManager.setNativeBrokerErrorCode(e.errorCode);
13967
- if (isFatalNativeAuthError(e)) {
13968
- throw e;
13969
- }
13970
- }
13971
- }
13972
- this.browserStorage.setTemporaryCache(TemporaryCacheKeys.NATIVE_REQUEST, JSON.stringify(nativeRequest), true);
13973
- const navigationOptions = {
13974
- apiId: ApiId.acquireTokenRedirect,
13975
- timeout: this.config.system.redirectNavigationTimeout,
13976
- noHistory: false,
13977
- };
13978
- const redirectUri = this.config.auth.navigateToLoginRequestUrl
13979
- ? window.location.href
13980
- : this.getRedirectUri(request.redirectUri);
13981
- rootMeasurement.end({ success: true });
13982
- await this.navigationClient.navigateExternal(redirectUri, navigationOptions); // Need to treat this as external to ensure handleRedirectPromise is run again
13983
- }
13984
- /**
13985
- * If the previous page called native platform for a token using redirect APIs, send the same request again and return the response
13986
- * @param performanceClient {IPerformanceClient?}
13987
- * @param correlationId {string?} correlation identifier
13988
- */
13989
- async handleRedirectPromise(performanceClient, correlationId) {
13990
- this.logger.trace("NativeInteractionClient - handleRedirectPromise called.");
13991
- if (!this.browserStorage.isInteractionInProgress(true)) {
13992
- this.logger.info("handleRedirectPromise called but there is no interaction in progress, returning null.");
13993
- return null;
13994
- }
13995
- // remove prompt from the request to prevent WAM from prompting twice
13996
- const cachedRequest = this.browserStorage.getCachedNativeRequest();
13997
- if (!cachedRequest) {
13998
- this.logger.verbose("NativeInteractionClient - handleRedirectPromise called but there is no cached request, returning null.");
13999
- if (performanceClient && correlationId) {
14000
- performanceClient?.addFields({ errorCode: "no_cached_request" }, correlationId);
14001
- }
14002
- return null;
14003
- }
14004
- const { prompt, ...request } = cachedRequest;
14005
- if (prompt) {
14006
- 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.");
14007
- }
14008
- this.browserStorage.removeItem(this.browserStorage.generateCacheKey(TemporaryCacheKeys.NATIVE_REQUEST));
14009
- const messageBody = {
14010
- method: NativeExtensionMethod.GetToken,
14011
- request: request,
14012
- };
14013
- const reqTimestamp = nowSeconds();
14014
- try {
14015
- this.logger.verbose("NativeInteractionClient - handleRedirectPromise sending message to native broker.");
14016
- const response = await this.nativeMessageHandler.sendMessage(messageBody);
14017
- this.validateNativeResponse(response);
14018
- const result = this.handleNativeResponse(response, request, reqTimestamp);
14019
- const res = await result;
14020
- const serverTelemetryManager = this.initializeServerTelemetryManager(this.apiId);
14021
- serverTelemetryManager.clearNativeBrokerErrorCode();
14022
- return res;
14023
- }
14024
- catch (e) {
14025
- throw e;
14026
- }
14027
- }
14028
- /**
14029
- * Logout from native platform via browser extension
14030
- * @param request
14031
- */
14032
- logout() {
14033
- this.logger.trace("NativeInteractionClient - logout called.");
14034
- return Promise.reject("Logout not implemented yet");
14035
- }
14036
- /**
14037
- * Transform response from native platform into AuthenticationResult object which will be returned to the end user
14038
- * @param response
14039
- * @param request
14040
- * @param reqTimestamp
14041
- */
14042
- async handleNativeResponse(response, request, reqTimestamp) {
14043
- this.logger.trace("NativeInteractionClient - handleNativeResponse called.");
14044
- // generate identifiers
14045
- const idTokenClaims = extractTokenClaims(response.id_token, base64Decode);
14046
- const homeAccountIdentifier = this.createHomeAccountIdentifier(response, idTokenClaims);
14047
- const cachedhomeAccountId = this.browserStorage.getAccountInfoFilteredBy({
14048
- nativeAccountId: request.accountId,
14049
- })?.homeAccountId;
14050
- // add exception for double brokering, please note this is temporary and will be fortified in future
14051
- if (request.extraParameters?.child_client_id &&
14052
- response.account.id !== request.accountId) {
14053
- this.logger.info("handleNativeServerResponse: Double broker flow detected, ignoring accountId mismatch");
14054
- }
14055
- else if (homeAccountIdentifier !== cachedhomeAccountId &&
14056
- response.account.id !== request.accountId) {
14057
- // 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
14058
- throw createNativeAuthError(userSwitch);
14059
- }
14060
- // Get the preferred_cache domain for the given authority
14061
- const authority = await this.getDiscoveredAuthority({
14062
- requestAuthority: request.authority,
14063
- });
14064
- const baseAccount = buildAccountToCache(this.browserStorage, authority, homeAccountIdentifier, base64Decode, idTokenClaims, response.client_info, undefined, // environment
14065
- idTokenClaims.tid, undefined, // auth code payload
14066
- response.account.id, this.logger);
14067
- // Ensure expires_in is in number format
14068
- response.expires_in = Number(response.expires_in);
14069
- // generate authenticationResult
14070
- const result = await this.generateAuthenticationResult(response, request, idTokenClaims, baseAccount, authority.canonicalAuthority, reqTimestamp);
14071
- // cache accounts and tokens in the appropriate storage
14072
- await this.cacheAccount(baseAccount);
14073
- await this.cacheNativeTokens(response, request, homeAccountIdentifier, idTokenClaims, response.access_token, result.tenantId, reqTimestamp);
14074
- 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;
14075
13995
  }
14076
13996
  /**
14077
- * creates an homeAccountIdentifier for the account
13997
+ * Gets MATS telemetry from native response
14078
13998
  * @param response
14079
- * @param idTokenObj
14080
13999
  * @returns
14081
14000
  */
14082
- createHomeAccountIdentifier(response, idTokenClaims) {
14083
- // Save account in browser storage
14084
- const homeAccountIdentifier = AccountEntity.generateHomeAccountId(response.client_info || Constants.EMPTY_STRING, AuthorityType.Default, this.logger, this.browserCrypto, idTokenClaims);
14085
- 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;
14086
14011
  }
14087
14012
  /**
14088
- * Helper to generate scopes
14013
+ * Returns whether or not response came from native cache
14089
14014
  * @param response
14090
- * @param request
14091
14015
  * @returns
14092
14016
  */
14093
- generateScopes(response, request) {
14094
- return response.scope
14095
- ? ScopeSet.fromString(response.scope)
14096
- : 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;
14097
14023
  }
14098
14024
  /**
14099
- * 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
14100
14026
  * @param request
14101
- * @param response
14102
14027
  */
14103
- async generatePopAccessToken(response, request) {
14104
- if (request.tokenType === AuthenticationScheme.POP &&
14105
- request.signPopToken) {
14106
- /**
14107
- * This code prioritizes SHR returned from the native layer. In case of error/SHR not calculated from WAM and the AT
14108
- * is still received, SHR is calculated locally
14109
- */
14110
- // Check if native layer returned an SHR token
14111
- if (response.shr) {
14112
- this.logger.trace("handleNativeServerResponse: SHR is enabled in native layer");
14113
- return response.shr;
14114
- }
14115
- // Generate SHR in msal js if WAM does not compute it when POP is enabled
14116
- 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
14117
14064
  const shrParameters = {
14118
- resourceRequestMethod: request.resourceRequestMethod,
14119
14065
  resourceRequestUri: request.resourceRequestUri,
14066
+ resourceRequestMethod: request.resourceRequestMethod,
14120
14067
  shrClaims: request.shrClaims,
14121
14068
  shrNonce: request.shrNonce,
14122
14069
  };
14123
- /**
14124
- * KeyID must be present in the native request from when the PoP key was generated in order for
14125
- * PopTokenGenerator to query the full key for signing
14126
- */
14127
- if (!request.keyId) {
14128
- 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;
14129
14078
  }
14130
- 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;
14131
14085
  }
14132
- else {
14133
- 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);
14134
14126
  }
14135
14127
  }
14136
14128
  /**
14137
- * Generates authentication result
14138
- * @param response
14139
- * @param request
14140
- * @param idTokenObj
14141
- * @param accountEntity
14142
- * @param authority
14143
- * @param reqTimestamp
14144
- * @returns
14129
+ * Handles extra broker request parameters
14130
+ * @param request {PlatformAuthRequest}
14131
+ * @private
14145
14132
  */
14146
- async generateAuthenticationResult(response, request, idTokenClaims, accountEntity, authority, reqTimestamp) {
14147
- // Add Native Broker fields to Telemetry
14148
- const mats = this.addTelemetryFromNativeResponse(response);
14149
- // If scopes not returned in server response, use request scopes
14150
- const responseScopes = response.scope
14151
- ? ScopeSet.fromString(response.scope)
14152
- : ScopeSet.fromString(request.scope);
14153
- const accountProperties = response.account.properties || {};
14154
- const uid = accountProperties["UID"] ||
14155
- idTokenClaims.oid ||
14156
- idTokenClaims.sub ||
14157
- Constants.EMPTY_STRING;
14158
- const tid = accountProperties["TenantId"] ||
14159
- idTokenClaims.tid ||
14160
- Constants.EMPTY_STRING;
14161
- const accountInfo = updateAccountTenantProfileData(accountEntity.getAccountInfo(), undefined, // tenantProfile optional
14162
- idTokenClaims, response.id_token);
14163
- /**
14164
- * In pairwise broker flows, this check prevents the broker's native account id
14165
- * from being returned over the embedded app's account id.
14166
- */
14167
- if (accountInfo.nativeAccountId !== response.account.id) {
14168
- 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;
14169
14140
  }
14170
- // generate PoP token as needed
14171
- const responseAccessToken = await this.generatePopAccessToken(response, request);
14172
- const tokenType = request.tokenType === AuthenticationScheme.POP
14173
- ? AuthenticationScheme.POP
14174
- : AuthenticationScheme.BEARER;
14175
- const result = {
14176
- authority: authority,
14177
- uniqueId: uid,
14178
- tenantId: tid,
14179
- scopes: responseScopes.asArray(),
14180
- account: accountInfo,
14181
- idToken: response.id_token,
14182
- idTokenClaims: idTokenClaims,
14183
- accessToken: responseAccessToken,
14184
- fromCache: mats ? this.isResponseFromCache(mats) : false,
14185
- // Request timestamp and NativeResponse expires_in are in seconds, converting to Date for AuthenticationResult
14186
- expiresOn: toDateFromSeconds(reqTimestamp + response.expires_in),
14187
- tokenType: tokenType,
14188
- correlationId: this.correlationId,
14189
- state: response.state,
14190
- 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,
14191
14156
  };
14192
- 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;
14193
14440
  }
14194
14441
  /**
14195
- * cache the account entity in browser storage
14196
- * @param accountEntity
14442
+ * Sends a given message to the extension and resolves with the extension response
14443
+ * @param request
14197
14444
  */
14198
- async cacheAccount(accountEntity) {
14199
- // Store the account info and hence `nativeAccountId` in browser cache
14200
- await this.browserStorage.setAccount(accountEntity, this.correlationId);
14201
- // Remove any existing cached tokens for this account in browser storage
14202
- this.browserStorage.removeAccountContext(accountEntity).catch((e) => {
14203
- 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 });
14204
14464
  });
14465
+ const validatedResponse = this.validatePlatformBrokerResponse(response);
14466
+ return validatedResponse;
14205
14467
  }
14206
14468
  /**
14207
- * Stores the access_token and id_token in inmemory storage
14208
- * @param response
14209
- * @param request
14210
- * @param homeAccountIdentifier
14211
- * @param idTokenObj
14212
- * @param responseAccessToken
14213
- * @param tenantId
14214
- * @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
14215
14474
  */
14216
- cacheNativeTokens(response, request, homeAccountIdentifier, idTokenClaims, responseAccessToken, tenantId, reqTimestamp) {
14217
- const cachedIdToken = createIdTokenEntity(homeAccountIdentifier, request.authority, response.id_token || "", request.clientId, idTokenClaims.tid || "");
14218
- // cache accessToken in inmemory storage
14219
- const expiresIn = request.tokenType === AuthenticationScheme.POP
14220
- ? Constants.SHR_NONCE_VALIDITY
14221
- : (typeof response.expires_in === "string"
14222
- ? parseInt(response.expires_in, 10)
14223
- : response.expires_in) || 0;
14224
- const tokenExpirationSeconds = reqTimestamp + expiresIn;
14225
- const responseScopes = this.generateScopes(response, request);
14226
- const cachedAccessToken = createAccessTokenEntity(homeAccountIdentifier, request.authority, responseAccessToken, request.clientId, idTokenClaims.tid || tenantId, responseScopes.printScopes(), tokenExpirationSeconds, 0, base64Decode, undefined, request.tokenType, undefined, request.keyId);
14227
- const nativeCacheRecord = {
14228
- idToken: cachedIdToken,
14229
- 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
+ },
14230
14503
  };
14231
- 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
+ });
14232
14530
  }
14233
- addTelemetryFromNativeResponse(response) {
14234
- const mats = this.getMATSFromResponse(response);
14235
- if (!mats) {
14236
- 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
+ }
14237
14643
  }
14238
- this.performanceClient.addFields({
14239
- extensionId: this.nativeMessageHandler.getExtensionId(),
14240
- extensionVersion: this.nativeMessageHandler.getExtensionVersion(),
14241
- matsBrokerVersion: mats.broker_version,
14242
- matsAccountJoinOnStart: mats.account_join_on_start,
14243
- matsAccountJoinOnEnd: mats.account_join_on_end,
14244
- matsDeviceJoin: mats.device_join,
14245
- matsPromptBehavior: mats.prompt_behavior,
14246
- matsApiErrorCode: mats.api_error_code,
14247
- matsUiVisible: mats.ui_visible,
14248
- matsSilentCode: mats.silent_code,
14249
- matsSilentBiSubCode: mats.silent_bi_sub_code,
14250
- matsSilentMessage: mats.silent_message,
14251
- matsSilentStatus: mats.silent_status,
14252
- matsHttpStatus: mats.http_status,
14253
- matsHttpEventCount: mats.http_event_count,
14254
- }, this.correlationId);
14255
- return mats;
14256
14644
  }
14257
14645
  /**
14258
14646
  * Validates native platform response before processing
14259
14647
  * @param response
14260
14648
  */
14261
- validateNativeResponse(response) {
14649
+ validatePlatformBrokerResponse(response) {
14262
14650
  if (response.hasOwnProperty("access_token") &&
14263
14651
  response.hasOwnProperty("id_token") &&
14264
14652
  response.hasOwnProperty("client_info") &&
@@ -14272,425 +14660,258 @@
14272
14660
  }
14273
14661
  }
14274
14662
  /**
14275
- * Gets MATS telemetry from native response
14276
- * @param response
14277
- * @returns
14278
- */
14279
- getMATSFromResponse(response) {
14280
- if (response.properties.MATS) {
14281
- try {
14282
- return JSON.parse(response.properties.MATS);
14283
- }
14284
- catch (e) {
14285
- this.logger.error("NativeInteractionClient - Error parsing MATS telemetry, returning null instead");
14286
- }
14287
- }
14288
- return null;
14289
- }
14290
- /**
14291
- * Returns whether or not response came from native cache
14292
- * @param response
14663
+ * Returns the Id for the browser extension this handler is communicating with
14293
14664
  * @returns
14294
14665
  */
14295
- isResponseFromCache(mats) {
14296
- if (typeof mats.is_cached === "undefined") {
14297
- this.logger.verbose("NativeInteractionClient - MATS telemetry does not contain field indicating if response was served from cache. Returning false.");
14298
- return false;
14299
- }
14300
- return !!mats.is_cached;
14301
- }
14302
- /**
14303
- * Translates developer provided request object into NativeRequest object
14304
- * @param request
14305
- */
14306
- async initializeNativeRequest(request) {
14307
- this.logger.trace("NativeInteractionClient - initializeNativeRequest called");
14308
- const requestAuthority = request.authority || this.config.auth.authority;
14309
- if (request.account) {
14310
- // validate authority
14311
- await this.getDiscoveredAuthority({
14312
- requestAuthority,
14313
- requestAzureCloudOptions: request.azureCloudOptions,
14314
- account: request.account,
14315
- });
14316
- }
14317
- const canonicalAuthority = new UrlString(requestAuthority);
14318
- canonicalAuthority.validateAsUri();
14319
- // 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.
14320
- const { scopes, ...remainingProperties } = request;
14321
- const scopeSet = new ScopeSet(scopes || []);
14322
- scopeSet.appendScopes(OIDC_DEFAULT_SCOPES);
14323
- const getPrompt = () => {
14324
- // If request is silent, prompt is always none
14325
- switch (this.apiId) {
14326
- case ApiId.ssoSilent:
14327
- case ApiId.acquireTokenSilent_silentFlow:
14328
- this.logger.trace("initializeNativeRequest: silent request sets prompt to none");
14329
- return PromptValue.NONE;
14330
- }
14331
- // Prompt not provided, request may proceed and native broker decides if it needs to prompt
14332
- if (!request.prompt) {
14333
- this.logger.trace("initializeNativeRequest: prompt was not provided");
14334
- return undefined;
14335
- }
14336
- // If request is interactive, check if prompt provided is allowed to go directly to native broker
14337
- switch (request.prompt) {
14338
- case PromptValue.NONE:
14339
- case PromptValue.CONSENT:
14340
- case PromptValue.LOGIN:
14341
- this.logger.trace("initializeNativeRequest: prompt is compatible with native flow");
14342
- return request.prompt;
14343
- default:
14344
- this.logger.trace(`initializeNativeRequest: prompt = ${request.prompt} is not compatible with native flow`);
14345
- throw createBrowserAuthError(nativePromptNotSupported);
14346
- }
14347
- };
14348
- const validatedRequest = {
14349
- ...remainingProperties,
14350
- accountId: this.accountId,
14351
- clientId: this.config.auth.clientId,
14352
- authority: canonicalAuthority.urlString,
14353
- scope: scopeSet.printScopes(),
14354
- redirectUri: this.getRedirectUri(request.redirectUri),
14355
- prompt: getPrompt(),
14356
- correlationId: this.correlationId,
14357
- tokenType: request.authenticationScheme,
14358
- windowTitleSubstring: document.title,
14359
- extraParameters: {
14360
- ...request.extraQueryParameters,
14361
- ...request.tokenQueryParameters,
14362
- },
14363
- extendedExpiryToken: false,
14364
- keyId: request.popKid,
14365
- };
14366
- // Check for PoP token requests: signPopToken should only be set to true if popKid is not set
14367
- if (validatedRequest.signPopToken && !!request.popKid) {
14368
- throw createBrowserAuthError(invalidPopTokenRequest);
14369
- }
14370
- this.handleExtraBrokerParams(validatedRequest);
14371
- validatedRequest.extraParameters =
14372
- validatedRequest.extraParameters || {};
14373
- validatedRequest.extraParameters.telemetry =
14374
- NativeConstants.MATS_TELEMETRY;
14375
- if (request.authenticationScheme === AuthenticationScheme.POP) {
14376
- // add POP request type
14377
- const shrParameters = {
14378
- resourceRequestUri: request.resourceRequestUri,
14379
- resourceRequestMethod: request.resourceRequestMethod,
14380
- shrClaims: request.shrClaims,
14381
- shrNonce: request.shrNonce,
14382
- };
14383
- const popTokenGenerator = new PopTokenGenerator(this.browserCrypto);
14384
- // generate reqCnf if not provided in the request
14385
- let reqCnfData;
14386
- if (!validatedRequest.keyId) {
14387
- const generatedReqCnfData = await invokeAsync(popTokenGenerator.generateCnf.bind(popTokenGenerator), PerformanceEvents.PopTokenGenerateCnf, this.logger, this.performanceClient, request.correlationId)(shrParameters, this.logger);
14388
- reqCnfData = generatedReqCnfData.reqCnfString;
14389
- validatedRequest.keyId = generatedReqCnfData.kid;
14390
- validatedRequest.signPopToken = true;
14391
- }
14392
- else {
14393
- reqCnfData = this.browserCrypto.base64UrlEncode(JSON.stringify({ kid: validatedRequest.keyId }));
14394
- validatedRequest.signPopToken = false;
14395
- }
14396
- // SPAs require whole string to be passed to broker
14397
- validatedRequest.reqCnf = reqCnfData;
14398
- }
14399
- this.addRequestSKUs(validatedRequest);
14400
- return validatedRequest;
14401
- }
14402
- /**
14403
- * Handles extra broker request parameters
14404
- * @param request {NativeTokenRequest}
14405
- * @private
14406
- */
14407
- handleExtraBrokerParams(request) {
14408
- const hasExtraBrokerParams = request.extraParameters &&
14409
- request.extraParameters.hasOwnProperty(BROKER_CLIENT_ID) &&
14410
- request.extraParameters.hasOwnProperty(BROKER_REDIRECT_URI) &&
14411
- request.extraParameters.hasOwnProperty(CLIENT_ID);
14412
- if (!request.embeddedClientId && !hasExtraBrokerParams) {
14413
- return;
14414
- }
14415
- let child_client_id = "";
14416
- const child_redirect_uri = request.redirectUri;
14417
- if (request.embeddedClientId) {
14418
- request.redirectUri = this.config.auth.redirectUri;
14419
- child_client_id = request.embeddedClientId;
14420
- }
14421
- else if (request.extraParameters) {
14422
- request.redirectUri =
14423
- request.extraParameters[BROKER_REDIRECT_URI];
14424
- child_client_id =
14425
- request.extraParameters[CLIENT_ID];
14426
- }
14427
- request.extraParameters = {
14428
- child_client_id,
14429
- child_redirect_uri,
14430
- };
14431
- this.performanceClient?.addFields({
14432
- embeddedClientId: child_client_id,
14433
- embeddedRedirectUri: child_redirect_uri,
14434
- }, request.correlationId);
14435
- }
14436
- }
14437
-
14438
- /*
14439
- * Copyright (c) Microsoft Corporation. All rights reserved.
14440
- * Licensed under the MIT License.
14441
- */
14442
- /**
14443
- * Returns map of parameters that are applicable to all calls to /authorize whether using PKCE or EAR
14444
- * @param config
14445
- * @param authority
14446
- * @param request
14447
- * @param logger
14448
- * @param performanceClient
14449
- * @returns
14450
- */
14451
- async function getStandardParameters(config, authority, request, logger, performanceClient) {
14452
- const parameters = getStandardAuthorizeRequestParameters({ ...config.auth, authority: authority }, request, logger, performanceClient);
14453
- addLibraryInfo(parameters, {
14454
- sku: BrowserConstants.MSAL_SKU,
14455
- version: version,
14456
- os: "",
14457
- cpu: "",
14458
- });
14459
- if (config.auth.protocolMode !== ProtocolMode.OIDC) {
14460
- addApplicationTelemetry(parameters, config.telemetry.application);
14666
+ getExtensionId() {
14667
+ return this.extensionId;
14461
14668
  }
14462
- if (request.platformBroker) {
14463
- // signal ests that this is a WAM call
14464
- addNativeBroker(parameters);
14465
- // pass the req_cnf for POP
14466
- if (request.authenticationScheme === AuthenticationScheme.POP) {
14467
- const cryptoOps = new CryptoOps(logger, performanceClient);
14468
- const popTokenGenerator = new PopTokenGenerator(cryptoOps);
14469
- // req_cnf is always sent as a string for SPAs
14470
- let reqCnfData;
14471
- if (!request.popKid) {
14472
- const generatedReqCnfData = await invokeAsync(popTokenGenerator.generateCnf.bind(popTokenGenerator), PerformanceEvents.PopTokenGenerateCnf, logger, performanceClient, request.correlationId)(request, logger);
14473
- reqCnfData = generatedReqCnfData.reqCnfString;
14474
- }
14475
- else {
14476
- reqCnfData = cryptoOps.encodeKid(request.popKid);
14477
- }
14478
- addPopToken(parameters, reqCnfData);
14479
- }
14669
+ /**
14670
+ * Returns the version for the browser extension this handler is communicating with
14671
+ * @returns
14672
+ */
14673
+ getExtensionVersion() {
14674
+ return this.extensionVersion;
14480
14675
  }
14481
- instrumentBrokerParams(parameters, request.correlationId, performanceClient);
14482
- return parameters;
14483
- }
14484
- /**
14485
- * Gets the full /authorize URL with request parameters when using Auth Code + PKCE
14486
- * @param config
14487
- * @param authority
14488
- * @param request
14489
- * @param logger
14490
- * @param performanceClient
14491
- * @returns
14492
- */
14493
- async function getAuthCodeRequestUrl(config, authority, request, logger, performanceClient) {
14494
- if (!request.codeChallenge) {
14495
- throw createClientConfigurationError(pkceParamsMissing);
14676
+ getExtensionName() {
14677
+ return this.getExtensionId() ===
14678
+ PlatformAuthConstants.PREFERRED_EXTENSION_ID
14679
+ ? "chrome"
14680
+ : this.getExtensionId()?.length
14681
+ ? "unknown"
14682
+ : undefined;
14496
14683
  }
14497
- const parameters = await invokeAsync(getStandardParameters, PerformanceEvents.GetStandardParams, logger, performanceClient, request.correlationId)(config, authority, request, logger, performanceClient);
14498
- addResponseType(parameters, OAuthResponseType.CODE);
14499
- addCodeChallengeParams(parameters, request.codeChallenge, Constants.S256_CODE_CHALLENGE_METHOD);
14500
- addExtraQueryParameters(parameters, request.extraQueryParameters || {});
14501
- return getAuthorizeUrl(authority, parameters, config.auth.encodeExtraQueryParams, request.extraQueryParameters);
14502
- }
14503
- /**
14504
- * Gets the form that will be posted to /authorize with request parameters when using EAR
14684
+ }
14685
+
14686
+ /*
14687
+ * Copyright (c) Microsoft Corporation. All rights reserved.
14688
+ * Licensed under the MIT License.
14505
14689
  */
14506
- async function getEARForm(frame, config, authority, request, logger, performanceClient) {
14507
- if (!request.earJwk) {
14508
- throw createBrowserAuthError(earJwkEmpty);
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;
14509
14696
  }
14510
- const parameters = await getStandardParameters(config, authority, request, logger, performanceClient);
14511
- addResponseType(parameters, OAuthResponseType.IDTOKEN_TOKEN_REFRESHTOKEN);
14512
- addEARParameters(parameters, request.earJwk);
14513
- const queryParams = new Map();
14514
- addExtraQueryParameters(queryParams, request.extraQueryParameters || {});
14515
- const url = getAuthorizeUrl(authority, queryParams, config.auth.encodeExtraQueryParams, request.extraQueryParameters);
14516
- return createForm(frame, url, parameters);
14517
- }
14518
- /**
14519
- * Creates form element in the provided document with auth parameters in the post body
14520
- * @param frame
14521
- * @param authorizeUrl
14522
- * @param parameters
14523
- * @returns
14524
- */
14525
- function createForm(frame, authorizeUrl, parameters) {
14526
- const form = frame.createElement("form");
14527
- form.method = "post";
14528
- form.action = authorizeUrl;
14529
- parameters.forEach((value, key) => {
14530
- const param = frame.createElement("input");
14531
- param.hidden = true;
14532
- param.name = key;
14533
- param.value = value;
14534
- form.appendChild(param);
14535
- });
14536
- frame.body.appendChild(form);
14537
- return form;
14538
- }
14539
- /**
14540
- * Response handler when server returns accountId on the /authorize request
14541
- * @param request
14542
- * @param accountId
14543
- * @param apiId
14544
- * @param config
14545
- * @param browserStorage
14546
- * @param nativeStorage
14547
- * @param eventHandler
14548
- * @param logger
14549
- * @param performanceClient
14550
- * @param nativeMessageHandler
14551
- * @returns
14552
- */
14553
- async function handleResponsePlatformBroker(request, accountId, apiId, config, browserStorage, nativeStorage, eventHandler, logger, performanceClient, nativeMessageHandler) {
14554
- if (!nativeMessageHandler) {
14555
- throw createBrowserAuthError(nativeConnectionNotEstablished);
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;
14556
14710
  }
14557
- const browserCrypto = new CryptoOps(logger, performanceClient);
14558
- const nativeInteractionClient = new NativeInteractionClient(config, browserStorage, browserCrypto, logger, eventHandler, config.system.navigationClient, apiId, performanceClient, nativeMessageHandler, accountId, nativeStorage, request.correlationId);
14559
- const { userRequestState } = ProtocolUtils.parseRequestState(browserCrypto, request.state);
14560
- return invokeAsync(nativeInteractionClient.acquireToken.bind(nativeInteractionClient), PerformanceEvents.NativeInteractionClientAcquireToken, logger, performanceClient, request.correlationId)({
14561
- ...request,
14562
- state: userRequestState,
14563
- prompt: undefined, // Server should handle the prompt, ideally native broker can do this part silently
14564
- });
14565
- }
14566
- /**
14567
- * Response handler when server returns code on the /authorize request
14568
- * @param request
14569
- * @param response
14570
- * @param codeVerifier
14571
- * @param authClient
14572
- * @param browserStorage
14573
- * @param logger
14574
- * @param performanceClient
14575
- * @returns
14576
- */
14577
- async function handleResponseCode(request, response, codeVerifier, apiId, config, authClient, browserStorage, nativeStorage, eventHandler, logger, performanceClient, nativeMessageHandler) {
14578
- // Remove throttle if it exists
14579
- ThrottlingUtils.removeThrottle(browserStorage, config.auth.clientId, request);
14580
- if (response.accountId) {
14581
- return invokeAsync(handleResponsePlatformBroker, PerformanceEvents.HandleResponsePlatformBroker, logger, performanceClient, request.correlationId)(request, response.accountId, apiId, config, browserStorage, nativeStorage, eventHandler, logger, performanceClient, nativeMessageHandler);
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;
14582
14717
  }
14583
- const authCodeRequest = {
14584
- ...request,
14585
- code: response.code || "",
14586
- codeVerifier: codeVerifier,
14587
- };
14588
- // Create popup interaction handler.
14589
- const interactionHandler = new InteractionHandler(authClient, browserStorage, authCodeRequest, logger, performanceClient);
14590
- // Handle response from hash string.
14591
- const result = await invokeAsync(interactionHandler.handleCodeResponse.bind(interactionHandler), PerformanceEvents.HandleCodeResponse, logger, performanceClient, request.correlationId)(response, request);
14592
- return result;
14593
- }
14594
- /**
14595
- * Response handler when server returns ear_jwe on the /authorize request
14596
- * @param request
14597
- * @param response
14598
- * @param apiId
14599
- * @param config
14600
- * @param authority
14601
- * @param browserStorage
14602
- * @param nativeStorage
14603
- * @param eventHandler
14604
- * @param logger
14605
- * @param performanceClient
14606
- * @param nativeMessageHandler
14607
- * @returns
14608
- */
14609
- async function handleResponseEAR(request, response, apiId, config, authority, browserStorage, nativeStorage, eventHandler, logger, performanceClient, nativeMessageHandler) {
14610
- // Remove throttle if it exists
14611
- ThrottlingUtils.removeThrottle(browserStorage, config.auth.clientId, request);
14612
- // Validate state & check response for errors
14613
- validateAuthorizationResponse(response, request.state);
14614
- if (!response.ear_jwe) {
14615
- throw createBrowserAuthError(earJweEmpty);
14718
+ getExtensionVersion() {
14719
+ return "";
14616
14720
  }
14617
- if (!request.earJwk) {
14618
- throw createBrowserAuthError(earJwkEmpty);
14721
+ getExtensionName() {
14722
+ return PlatformAuthConstants.DOM_API_NAME;
14619
14723
  }
14620
- const decryptedData = JSON.parse(await invokeAsync(decryptEarResponse, PerformanceEvents.DecryptEarResponse, logger, performanceClient, request.correlationId)(request.earJwk, response.ear_jwe));
14621
- if (decryptedData.accountId) {
14622
- return invokeAsync(handleResponsePlatformBroker, PerformanceEvents.HandleResponsePlatformBroker, logger, performanceClient, request.correlationId)(request, decryptedData.accountId, apiId, config, browserStorage, nativeStorage, eventHandler, logger, performanceClient, nativeMessageHandler);
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;
14623
14818
  }
14624
- const responseHandler = new ResponseHandler(config.auth.clientId, browserStorage, new CryptoOps(logger, performanceClient), logger, null, null, performanceClient);
14625
- // Validate response. This function throws a server error if an error is returned by the server.
14626
- responseHandler.validateTokenResponse(decryptedData);
14627
- // Temporary until response handler is refactored to be more flow agnostic.
14628
- const additionalData = {
14629
- code: "",
14630
- state: request.state,
14631
- nonce: request.nonce,
14632
- client_info: decryptedData.client_info,
14633
- cloud_graph_host_name: decryptedData.cloud_graph_host_name,
14634
- cloud_instance_host_name: decryptedData.cloud_instance_host_name,
14635
- cloud_instance_name: decryptedData.cloud_instance_name,
14636
- msgraph_host: decryptedData.msgraph_host,
14637
- };
14638
- return (await invokeAsync(responseHandler.handleServerTokenResponse.bind(responseHandler), PerformanceEvents.HandleServerTokenResponse, logger, performanceClient, request.correlationId)(decryptedData, authority, nowSeconds(), request, additionalData, undefined, undefined, undefined, undefined));
14639
14819
  }
14640
14820
 
14641
14821
  /*
14642
14822
  * Copyright (c) Microsoft Corporation. All rights reserved.
14643
14823
  * Licensed under the MIT License.
14644
14824
  */
14645
- // Constant byte array length
14646
- const RANDOM_BYTE_ARR_LENGTH = 32;
14647
- /**
14648
- * This file defines APIs to generate PKCE codes and code verifiers.
14649
- */
14650
14825
  /**
14651
- * 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
14652
14830
  */
14653
- async function generatePkceCodes(performanceClient, logger, correlationId) {
14654
- performanceClient.addQueueMeasurement(PerformanceEvents.GeneratePkceCodes, correlationId);
14655
- const codeVerifier = invoke(generateCodeVerifier, PerformanceEvents.GenerateCodeVerifier, logger, performanceClient, correlationId)(performanceClient, logger, correlationId);
14656
- const codeChallenge = await invokeAsync(generateCodeChallengeFromVerifier, PerformanceEvents.GenerateCodeChallengeFromVerifier, logger, performanceClient, correlationId)(codeVerifier, performanceClient, logger, correlationId);
14657
- return {
14658
- verifier: codeVerifier,
14659
- challenge: codeChallenge,
14660
- };
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()));
14661
14840
  }
14662
- /**
14663
- * Generates a random 32 byte buffer and returns the base64
14664
- * encoded string to be used as a PKCE Code Verifier
14665
- */
14666
- 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;
14667
14847
  try {
14668
- // Generate random values as utf-8
14669
- const buffer = new Uint8Array(RANDOM_BYTE_ARR_LENGTH);
14670
- invoke(getRandomValues, PerformanceEvents.GetRandomValues, logger, performanceClient, correlationId)(buffer);
14671
- // encode verifier as base64
14672
- const pkceCodeVerifierB64 = urlEncodeArr(buffer);
14673
- 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
+ }
14674
14862
  }
14675
14863
  catch (e) {
14676
- throw createBrowserAuthError(pkceNotCreated);
14864
+ logger.trace("Platform auth not available", e);
14677
14865
  }
14866
+ return platformAuthProvider;
14678
14867
  }
14679
14868
  /**
14680
- * Creates a base64 encoded PKCE Code Challenge string from the
14681
- * 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
14682
14872
  */
14683
- async function generateCodeChallengeFromVerifier(pkceCodeVerifier, performanceClient, logger, correlationId) {
14684
- performanceClient.addQueueMeasurement(PerformanceEvents.GenerateCodeChallengeFromVerifier, correlationId);
14873
+ function isDomEnabledForPlatformAuth() {
14874
+ let sessionStorage;
14685
14875
  try {
14686
- // hashed verifier
14687
- const pkceHashedCodeVerifier = await invokeAsync(sha256Digest, PerformanceEvents.Sha256Digest, logger, performanceClient, correlationId)(pkceCodeVerifier, performanceClient, correlationId);
14688
- // encode hash as base64
14689
- 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";
14690
14879
  }
14691
14880
  catch (e) {
14692
- throw createBrowserAuthError(pkceNotCreated);
14881
+ return false;
14693
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
+ }
14913
+ }
14914
+ return true;
14694
14915
  }
14695
14916
 
14696
14917
  /*
@@ -14698,8 +14919,8 @@
14698
14919
  * Licensed under the MIT License.
14699
14920
  */
14700
14921
  class PopupClient extends StandardInteractionClient {
14701
- constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeStorageImpl, nativeMessageHandler, correlationId) {
14702
- 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);
14703
14924
  // Properly sets this reference for the unload event.
14704
14925
  this.unloadWindow = this.unloadWindow.bind(this);
14705
14926
  this.nativeStorage = nativeStorageImpl;
@@ -14787,7 +15008,7 @@
14787
15008
  if (popupParams.popup) {
14788
15009
  preconnect(validRequest.authority);
14789
15010
  }
14790
- const isPlatformBroker = NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeMessageHandler, request.authenticationScheme);
15011
+ const isPlatformBroker = isPlatformAuthAllowed(this.config, this.logger, this.platformAuthProvider, request.authenticationScheme);
14791
15012
  validRequest.platformBroker = isPlatformBroker;
14792
15013
  if (this.config.auth.protocolMode === ProtocolMode.EAR) {
14793
15014
  return this.executeEarFlow(validRequest, popupParams);
@@ -14829,7 +15050,7 @@
14829
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.
14830
15051
  const responseString = await this.monitorPopupForHash(popupWindow, popupParams.popupWindowParent);
14831
15052
  const serverParams = invoke(deserializeResponse, PerformanceEvents.DeserializeResponse, this.logger, this.performanceClient, this.correlationId)(responseString, this.config.auth.OIDCOptions.serverResponseType, this.logger);
14832
- 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);
14833
15054
  }
14834
15055
  catch (e) {
14835
15056
  // Close the synchronous popup if an error is thrown before the window unload event is registered
@@ -14865,7 +15086,7 @@
14865
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.
14866
15087
  const responseString = await invokeAsync(this.monitorPopupForHash.bind(this), PerformanceEvents.SilentHandlerMonitorIframeForHash, this.logger, this.performanceClient, correlationId)(popupWindow, popupParams.popupWindowParent);
14867
15088
  const serverParams = invoke(deserializeResponse, PerformanceEvents.DeserializeResponse, this.logger, this.performanceClient, this.correlationId)(responseString, this.config.auth.OIDCOptions.serverResponseType, this.logger);
14868
- 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);
14869
15090
  }
14870
15091
  /**
14871
15092
  *
@@ -15162,8 +15383,8 @@
15162
15383
  return navigation?.type;
15163
15384
  }
15164
15385
  class RedirectClient extends StandardInteractionClient {
15165
- constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeStorageImpl, nativeMessageHandler, correlationId) {
15166
- 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);
15167
15388
  this.nativeStorage = nativeStorageImpl;
15168
15389
  }
15169
15390
  /**
@@ -15172,8 +15393,7 @@
15172
15393
  */
15173
15394
  async acquireToken(request) {
15174
15395
  const validRequest = await invokeAsync(this.initializeAuthorizationRequest.bind(this), PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest, this.logger, this.performanceClient, this.correlationId)(request, exports.InteractionType.Redirect);
15175
- validRequest.platformBroker =
15176
- NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeMessageHandler, request.authenticationScheme);
15396
+ validRequest.platformBroker = isPlatformAuthAllowed(this.config, this.logger, this.platformAuthProvider, request.authenticationScheme);
15177
15397
  const handleBackButton = (event) => {
15178
15398
  // Clear temporary cache if the back button is clicked during the redirect flow.
15179
15399
  if (event.persisted) {
@@ -15413,10 +15633,10 @@
15413
15633
  requestExtraQueryParameters: request.extraQueryParameters,
15414
15634
  account: request.account,
15415
15635
  });
15416
- 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);
15417
15637
  }
15418
15638
  const authClient = await invokeAsync(this.createAuthCodeClient.bind(this), PerformanceEvents.StandardInteractionClientCreateAuthCodeClient, this.logger, this.performanceClient, this.correlationId)({ serverTelemetryManager, requestAuthority: request.authority });
15419
- 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);
15420
15640
  }
15421
15641
  /**
15422
15642
  * Redirects window to given URL.
@@ -15700,8 +15920,8 @@
15700
15920
  * Licensed under the MIT License.
15701
15921
  */
15702
15922
  class SilentIframeClient extends StandardInteractionClient {
15703
- constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, apiId, performanceClient, nativeStorageImpl, nativeMessageHandler, correlationId) {
15704
- 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);
15705
15925
  this.apiId = apiId;
15706
15926
  this.nativeStorage = nativeStorageImpl;
15707
15927
  }
@@ -15731,8 +15951,7 @@
15731
15951
  }
15732
15952
  // Create silent request
15733
15953
  const silentRequest = await invokeAsync(this.initializeAuthorizationRequest.bind(this), PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest, this.logger, this.performanceClient, request.correlationId)(inputRequest, exports.InteractionType.Silent);
15734
- silentRequest.platformBroker =
15735
- NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeMessageHandler, silentRequest.authenticationScheme);
15954
+ silentRequest.platformBroker = isPlatformAuthAllowed(this.config, this.logger, this.platformAuthProvider, silentRequest.authenticationScheme);
15736
15955
  preconnect(silentRequest.authority);
15737
15956
  if (this.config.auth.protocolMode === ProtocolMode.EAR) {
15738
15957
  return this.executeEarFlow(silentRequest);
@@ -15798,7 +16017,7 @@
15798
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.
15799
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);
15800
16019
  const serverParams = invoke(deserializeResponse, PerformanceEvents.DeserializeResponse, this.logger, this.performanceClient, correlationId)(responseString, responseType, this.logger);
15801
- 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);
15802
16021
  }
15803
16022
  /**
15804
16023
  * Currently Unsupported
@@ -15829,7 +16048,7 @@
15829
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.
15830
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);
15831
16050
  const serverParams = invoke(deserializeResponse, PerformanceEvents.DeserializeResponse, this.logger, this.performanceClient, correlationId)(responseString, responseType, this.logger);
15832
- 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);
15833
16052
  }
15834
16053
  }
15835
16054
 
@@ -16110,8 +16329,8 @@
16110
16329
  * Licensed under the MIT License.
16111
16330
  */
16112
16331
  class SilentAuthCodeClient extends StandardInteractionClient {
16113
- constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, apiId, performanceClient, nativeMessageHandler, correlationId) {
16114
- 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);
16115
16334
  this.apiId = apiId;
16116
16335
  }
16117
16336
  /**
@@ -16325,8 +16544,8 @@
16325
16544
  await invokeAsync(this.browserStorage.initialize.bind(this.browserStorage), PerformanceEvents.InitializeCache, this.logger, this.performanceClient, initCorrelationId)(initCorrelationId);
16326
16545
  if (allowPlatformBroker) {
16327
16546
  try {
16328
- this.nativeExtensionProvider =
16329
- 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);
16330
16549
  }
16331
16550
  catch (e) {
16332
16551
  this.logger.verbose(e);
@@ -16396,18 +16615,15 @@
16396
16615
  }
16397
16616
  const loggedInAccounts = this.getAllAccounts();
16398
16617
  const platformBrokerRequest = this.browserStorage.getCachedNativeRequest();
16399
- const useNative = platformBrokerRequest &&
16400
- NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeExtensionProvider) &&
16401
- this.nativeExtensionProvider &&
16402
- !hash;
16618
+ const useNative = platformBrokerRequest && this.platformAuthProvider && !hash;
16403
16619
  let rootMeasurement;
16404
16620
  this.eventHandler.emitEvent(EventType.HANDLE_REDIRECT_START, exports.InteractionType.Redirect);
16405
16621
  let redirectResponse;
16406
16622
  try {
16407
- if (useNative && this.nativeExtensionProvider) {
16623
+ if (useNative && this.platformAuthProvider) {
16408
16624
  rootMeasurement = this.performanceClient.startMeasurement(PerformanceEvents.AcquireTokenRedirect, platformBrokerRequest?.correlationId || "");
16409
16625
  this.logger.trace("handleRedirectPromise - acquiring token from native platform");
16410
- 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);
16411
16627
  redirectResponse = invokeAsync(nativeClient.handleRedirectPromise.bind(nativeClient), PerformanceEvents.HandleNativeRedirectPromiseMeasurement, this.logger, this.performanceClient, rootMeasurement.event.correlationId)(this.performanceClient, rootMeasurement.event.correlationId);
16412
16628
  }
16413
16629
  else {
@@ -16536,15 +16752,15 @@
16536
16752
  this.eventHandler.emitEvent(EventType.LOGIN_START, exports.InteractionType.Redirect, request);
16537
16753
  }
16538
16754
  let result;
16539
- if (this.nativeExtensionProvider &&
16755
+ if (this.platformAuthProvider &&
16540
16756
  this.canUsePlatformBroker(request)) {
16541
- 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);
16542
16758
  result = nativeClient
16543
16759
  .acquireTokenRedirect(request, atrMeasurement)
16544
16760
  .catch((e) => {
16545
16761
  if (e instanceof NativeAuthError &&
16546
16762
  isFatalNativeAuthError(e)) {
16547
- 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
16548
16764
  const redirectClient = this.createRedirectClient(correlationId);
16549
16765
  return redirectClient.acquireToken(request);
16550
16766
  }
@@ -16625,7 +16841,7 @@
16625
16841
  .catch((e) => {
16626
16842
  if (e instanceof NativeAuthError &&
16627
16843
  isFatalNativeAuthError(e)) {
16628
- 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
16629
16845
  const popupClient = this.createPopupClient(correlationId);
16630
16846
  return popupClient.acquireToken(request, pkce);
16631
16847
  }
@@ -16734,7 +16950,7 @@
16734
16950
  result = this.acquireTokenNative(validRequest, ApiId.ssoSilent).catch((e) => {
16735
16951
  // If native token acquisition fails for availability reasons fallback to standard flow
16736
16952
  if (e instanceof NativeAuthError && isFatalNativeAuthError(e)) {
16737
- 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
16738
16954
  const silentIframeClient = this.createSilentIframeClient(validRequest.correlationId);
16739
16955
  return silentIframeClient.acquireToken(validRequest);
16740
16956
  }
@@ -16836,7 +17052,7 @@
16836
17052
  // If native token acquisition fails for availability reasons fallback to standard flow
16837
17053
  if (e instanceof NativeAuthError &&
16838
17054
  isFatalNativeAuthError(e)) {
16839
- 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
16840
17056
  }
16841
17057
  throw e;
16842
17058
  });
@@ -17094,10 +17310,10 @@
17094
17310
  */
17095
17311
  async acquireTokenNative(request, apiId, accountId, cacheLookupPolicy) {
17096
17312
  this.logger.trace("acquireTokenNative called");
17097
- if (!this.nativeExtensionProvider) {
17313
+ if (!this.platformAuthProvider) {
17098
17314
  throw createBrowserAuthError(nativeConnectionNotEstablished);
17099
17315
  }
17100
- 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);
17101
17317
  return nativeClient.acquireToken(request, cacheLookupPolicy);
17102
17318
  }
17103
17319
  /**
@@ -17106,8 +17322,12 @@
17106
17322
  */
17107
17323
  canUsePlatformBroker(request, accountId) {
17108
17324
  this.logger.trace("canUsePlatformBroker called");
17109
- if (!NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeExtensionProvider, request.authenticationScheme)) {
17110
- 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");
17111
17331
  return false;
17112
17332
  }
17113
17333
  if (request.prompt) {
@@ -17147,39 +17367,39 @@
17147
17367
  * @param correlationId
17148
17368
  */
17149
17369
  createPopupClient(correlationId) {
17150
- 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);
17151
17371
  }
17152
17372
  /**
17153
17373
  * Returns new instance of the Redirect Interaction Client
17154
17374
  * @param correlationId
17155
17375
  */
17156
17376
  createRedirectClient(correlationId) {
17157
- 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);
17158
17378
  }
17159
17379
  /**
17160
17380
  * Returns new instance of the Silent Iframe Interaction Client
17161
17381
  * @param correlationId
17162
17382
  */
17163
17383
  createSilentIframeClient(correlationId) {
17164
- 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);
17165
17385
  }
17166
17386
  /**
17167
17387
  * Returns new instance of the Silent Cache Interaction Client
17168
17388
  */
17169
17389
  createSilentCacheClient(correlationId) {
17170
- 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);
17171
17391
  }
17172
17392
  /**
17173
17393
  * Returns new instance of the Silent Refresh Interaction Client
17174
17394
  */
17175
17395
  createSilentRefreshClient(correlationId) {
17176
- 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);
17177
17397
  }
17178
17398
  /**
17179
17399
  * Returns new instance of the Silent AuthCode Interaction Client
17180
17400
  */
17181
17401
  createSilentAuthCodeClient(correlationId) {
17182
- 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);
17183
17403
  }
17184
17404
  /**
17185
17405
  * Adds event callbacks to array
@@ -17525,14 +17745,14 @@
17525
17745
  */
17526
17746
  async acquireTokenSilentNoIframe(silentRequest, cacheLookupPolicy) {
17527
17747
  // if the cache policy is set to access_token only, we should not be hitting the native layer yet
17528
- if (NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeExtensionProvider, silentRequest.authenticationScheme) &&
17748
+ if (isPlatformAuthAllowed(this.config, this.logger, this.platformAuthProvider, silentRequest.authenticationScheme) &&
17529
17749
  silentRequest.account.nativeAccountId) {
17530
17750
  this.logger.verbose("acquireTokenSilent - attempting to acquire token from native platform");
17531
17751
  return this.acquireTokenNative(silentRequest, ApiId.acquireTokenSilent_silentFlow, silentRequest.account.nativeAccountId, cacheLookupPolicy).catch(async (e) => {
17532
17752
  // If native token acquisition fails for availability reasons fallback to web flow
17533
17753
  if (e instanceof NativeAuthError && isFatalNativeAuthError(e)) {
17534
17754
  this.logger.verbose("acquireTokenSilent - native platform unavailable, falling back to web flow");
17535
- this.nativeExtensionProvider = undefined; // Prevent future requests from continuing to attempt
17755
+ this.platformAuthProvider = undefined; // Prevent future requests from continuing to attempt
17536
17756
  // Cache will not contain tokens, given that previous WAM requests succeeded. Skip cache and RT renewal and go straight to iframe renewal
17537
17757
  throw createClientAuthError(tokenRefreshRequired);
17538
17758
  }
@@ -19915,6 +20135,7 @@
19915
20135
  exports.WrapperSKU = WrapperSKU;
19916
20136
  exports.createNestablePublicClientApplication = createNestablePublicClientApplication;
19917
20137
  exports.createStandardPublicClientApplication = createStandardPublicClientApplication;
20138
+ exports.isPlatformBrokerAvailable = isPlatformBrokerAvailable;
19918
20139
  exports.stubbedPublicClientApplication = stubbedPublicClientApplication;
19919
20140
  exports.version = version;
19920
20141