@azure/msal-browser 4.11.1 → 4.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. package/dist/app/IPublicClientApplication.mjs +1 -1
  2. package/dist/app/PublicClientApplication.d.ts +1 -0
  3. package/dist/app/PublicClientApplication.d.ts.map +1 -1
  4. package/dist/app/PublicClientApplication.mjs +3 -2
  5. package/dist/app/PublicClientApplication.mjs.map +1 -1
  6. package/dist/app/PublicClientNext.mjs +1 -1
  7. package/dist/broker/nativeBroker/IPlatformAuthHandler.d.ts +12 -0
  8. package/dist/broker/nativeBroker/IPlatformAuthHandler.d.ts.map +1 -0
  9. package/dist/broker/nativeBroker/NativeStatusCodes.mjs +1 -1
  10. package/dist/broker/nativeBroker/PlatformAuthDOMHandler.d.ts +30 -0
  11. package/dist/broker/nativeBroker/PlatformAuthDOMHandler.d.ts.map +1 -0
  12. package/dist/broker/nativeBroker/PlatformAuthDOMHandler.mjs +143 -0
  13. package/dist/broker/nativeBroker/PlatformAuthDOMHandler.mjs.map +1 -0
  14. package/dist/broker/nativeBroker/{NativeMessageHandler.d.ts → PlatformAuthExtensionHandler.d.ts} +16 -16
  15. package/dist/broker/nativeBroker/PlatformAuthExtensionHandler.d.ts.map +1 -0
  16. package/dist/broker/nativeBroker/{NativeMessageHandler.mjs → PlatformAuthExtensionHandler.mjs} +66 -58
  17. package/dist/broker/nativeBroker/PlatformAuthExtensionHandler.mjs.map +1 -0
  18. package/dist/broker/nativeBroker/PlatformAuthProvider.d.ts +26 -0
  19. package/dist/broker/nativeBroker/PlatformAuthProvider.d.ts.map +1 -0
  20. package/dist/broker/nativeBroker/PlatformAuthProvider.mjs +108 -0
  21. package/dist/broker/nativeBroker/PlatformAuthProvider.mjs.map +1 -0
  22. package/dist/broker/nativeBroker/{NativeRequest.d.ts → PlatformAuthRequest.d.ts} +34 -3
  23. package/dist/broker/nativeBroker/PlatformAuthRequest.d.ts.map +1 -0
  24. package/dist/broker/nativeBroker/{NativeResponse.d.ts → PlatformAuthResponse.d.ts} +24 -2
  25. package/dist/broker/nativeBroker/PlatformAuthResponse.d.ts.map +1 -0
  26. package/dist/cache/AccountManager.mjs +1 -1
  27. package/dist/cache/AsyncMemoryStorage.mjs +1 -1
  28. package/dist/cache/BrowserCacheManager.d.ts +6 -2
  29. package/dist/cache/BrowserCacheManager.d.ts.map +1 -1
  30. package/dist/cache/BrowserCacheManager.mjs +29 -3
  31. package/dist/cache/BrowserCacheManager.mjs.map +1 -1
  32. package/dist/cache/CacheHelpers.mjs +1 -1
  33. package/dist/cache/CookieStorage.mjs +1 -1
  34. package/dist/cache/DatabaseStorage.mjs +1 -1
  35. package/dist/cache/LocalStorage.mjs +1 -1
  36. package/dist/cache/MemoryStorage.mjs +1 -1
  37. package/dist/cache/SessionStorage.mjs +1 -1
  38. package/dist/cache/TokenCache.mjs +1 -1
  39. package/dist/config/Configuration.mjs +1 -1
  40. package/dist/controllers/ControllerFactory.mjs +1 -1
  41. package/dist/controllers/IController.d.ts +1 -1
  42. package/dist/controllers/IController.d.ts.map +1 -1
  43. package/dist/controllers/NestedAppAuthController.d.ts +1 -1
  44. package/dist/controllers/NestedAppAuthController.d.ts.map +1 -1
  45. package/dist/controllers/NestedAppAuthController.mjs +4 -2
  46. package/dist/controllers/NestedAppAuthController.mjs.map +1 -1
  47. package/dist/controllers/StandardController.d.ts +4 -3
  48. package/dist/controllers/StandardController.d.ts.map +1 -1
  49. package/dist/controllers/StandardController.mjs +56 -30
  50. package/dist/controllers/StandardController.mjs.map +1 -1
  51. package/dist/controllers/UnknownOperatingContextController.mjs +1 -1
  52. package/dist/crypto/BrowserCrypto.mjs +1 -1
  53. package/dist/crypto/CryptoOps.mjs +1 -1
  54. package/dist/crypto/PkceGenerator.mjs +1 -1
  55. package/dist/crypto/SignedHttpRequest.mjs +1 -1
  56. package/dist/encode/Base64Decode.mjs +1 -1
  57. package/dist/encode/Base64Encode.mjs +1 -1
  58. package/dist/error/BrowserAuthError.mjs +1 -1
  59. package/dist/error/BrowserAuthErrorCodes.mjs +1 -1
  60. package/dist/error/BrowserConfigurationAuthError.mjs +1 -1
  61. package/dist/error/BrowserConfigurationAuthErrorCodes.mjs +1 -1
  62. package/dist/error/NativeAuthError.mjs +1 -1
  63. package/dist/error/NativeAuthErrorCodes.mjs +1 -1
  64. package/dist/error/NestedAppAuthError.mjs +1 -1
  65. package/dist/event/EventHandler.mjs +1 -1
  66. package/dist/event/EventMessage.d.ts +10 -1
  67. package/dist/event/EventMessage.d.ts.map +1 -1
  68. package/dist/event/EventMessage.mjs +1 -1
  69. package/dist/event/EventMessage.mjs.map +1 -1
  70. package/dist/event/EventType.d.ts +1 -0
  71. package/dist/event/EventType.d.ts.map +1 -1
  72. package/dist/event/EventType.mjs +2 -1
  73. package/dist/event/EventType.mjs.map +1 -1
  74. package/dist/index.d.ts +2 -1
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.mjs +2 -1
  77. package/dist/index.mjs.map +1 -1
  78. package/dist/interaction_client/BaseInteractionClient.d.ts +3 -3
  79. package/dist/interaction_client/BaseInteractionClient.d.ts.map +1 -1
  80. package/dist/interaction_client/BaseInteractionClient.mjs +3 -3
  81. package/dist/interaction_client/HybridSpaAuthorizationCodeClient.mjs +1 -1
  82. package/dist/interaction_client/{NativeInteractionClient.d.ts → PlatformAuthInteractionClient.d.ts} +21 -23
  83. package/dist/interaction_client/PlatformAuthInteractionClient.d.ts.map +1 -0
  84. package/dist/interaction_client/{NativeInteractionClient.mjs → PlatformAuthInteractionClient.mjs} +80 -111
  85. package/dist/interaction_client/PlatformAuthInteractionClient.mjs.map +1 -0
  86. package/dist/interaction_client/PopupClient.d.ts +2 -2
  87. package/dist/interaction_client/PopupClient.d.ts.map +1 -1
  88. package/dist/interaction_client/PopupClient.mjs +7 -7
  89. package/dist/interaction_client/PopupClient.mjs.map +1 -1
  90. package/dist/interaction_client/RedirectClient.d.ts +2 -2
  91. package/dist/interaction_client/RedirectClient.d.ts.map +1 -1
  92. package/dist/interaction_client/RedirectClient.mjs +7 -8
  93. package/dist/interaction_client/RedirectClient.mjs.map +1 -1
  94. package/dist/interaction_client/SilentAuthCodeClient.d.ts +2 -2
  95. package/dist/interaction_client/SilentAuthCodeClient.d.ts.map +1 -1
  96. package/dist/interaction_client/SilentAuthCodeClient.mjs +3 -3
  97. package/dist/interaction_client/SilentCacheClient.mjs +1 -1
  98. package/dist/interaction_client/SilentIframeClient.d.ts +2 -2
  99. package/dist/interaction_client/SilentIframeClient.d.ts.map +1 -1
  100. package/dist/interaction_client/SilentIframeClient.mjs +7 -8
  101. package/dist/interaction_client/SilentIframeClient.mjs.map +1 -1
  102. package/dist/interaction_client/SilentRefreshClient.mjs +1 -1
  103. package/dist/interaction_client/StandardInteractionClient.mjs +1 -1
  104. package/dist/interaction_handler/InteractionHandler.mjs +1 -1
  105. package/dist/interaction_handler/SilentHandler.mjs +1 -1
  106. package/dist/naa/BridgeError.mjs +1 -1
  107. package/dist/naa/BridgeProxy.mjs +1 -1
  108. package/dist/naa/BridgeStatusCode.mjs +1 -1
  109. package/dist/naa/mapping/NestedAppAuthAdapter.mjs +1 -1
  110. package/dist/navigation/NavigationClient.mjs +1 -1
  111. package/dist/network/FetchClient.mjs +1 -1
  112. package/dist/operatingcontext/BaseOperatingContext.mjs +1 -1
  113. package/dist/operatingcontext/NestedAppOperatingContext.mjs +1 -1
  114. package/dist/operatingcontext/StandardOperatingContext.mjs +1 -1
  115. package/dist/operatingcontext/UnknownOperatingContext.mjs +1 -1
  116. package/dist/packageMetadata.d.ts +1 -1
  117. package/dist/packageMetadata.mjs +2 -2
  118. package/dist/protocol/Authorize.d.ts +4 -4
  119. package/dist/protocol/Authorize.d.ts.map +1 -1
  120. package/dist/protocol/Authorize.mjs +10 -9
  121. package/dist/protocol/Authorize.mjs.map +1 -1
  122. package/dist/request/RequestHelpers.mjs +1 -1
  123. package/dist/response/ResponseHandler.mjs +1 -1
  124. package/dist/telemetry/BrowserPerformanceClient.mjs +1 -1
  125. package/dist/telemetry/BrowserPerformanceMeasurement.mjs +1 -1
  126. package/dist/utils/BrowserConstants.d.ts +8 -1
  127. package/dist/utils/BrowserConstants.d.ts.map +1 -1
  128. package/dist/utils/BrowserConstants.mjs +11 -4
  129. package/dist/utils/BrowserConstants.mjs.map +1 -1
  130. package/dist/utils/BrowserProtocolUtils.mjs +1 -1
  131. package/dist/utils/BrowserUtils.mjs +1 -1
  132. package/dist/utils/MsalFrameStatsUtils.d.ts +3 -0
  133. package/dist/utils/MsalFrameStatsUtils.d.ts.map +1 -0
  134. package/dist/utils/MsalFrameStatsUtils.mjs +23 -0
  135. package/dist/utils/MsalFrameStatsUtils.mjs.map +1 -0
  136. package/lib/msal-browser.cjs +1600 -1323
  137. package/lib/msal-browser.cjs.map +1 -1
  138. package/lib/msal-browser.js +1600 -1323
  139. package/lib/msal-browser.js.map +1 -1
  140. package/lib/msal-browser.min.js +66 -66
  141. package/lib/types/app/PublicClientApplication.d.ts +1 -0
  142. package/lib/types/app/PublicClientApplication.d.ts.map +1 -1
  143. package/lib/types/broker/nativeBroker/IPlatformAuthHandler.d.ts +12 -0
  144. package/lib/types/broker/nativeBroker/IPlatformAuthHandler.d.ts.map +1 -0
  145. package/lib/types/broker/nativeBroker/PlatformAuthDOMHandler.d.ts +30 -0
  146. package/lib/types/broker/nativeBroker/PlatformAuthDOMHandler.d.ts.map +1 -0
  147. package/lib/types/broker/nativeBroker/{NativeMessageHandler.d.ts → PlatformAuthExtensionHandler.d.ts} +16 -16
  148. package/lib/types/broker/nativeBroker/PlatformAuthExtensionHandler.d.ts.map +1 -0
  149. package/lib/types/broker/nativeBroker/PlatformAuthProvider.d.ts +26 -0
  150. package/lib/types/broker/nativeBroker/PlatformAuthProvider.d.ts.map +1 -0
  151. package/lib/types/broker/nativeBroker/{NativeRequest.d.ts → PlatformAuthRequest.d.ts} +34 -3
  152. package/lib/types/broker/nativeBroker/PlatformAuthRequest.d.ts.map +1 -0
  153. package/lib/types/broker/nativeBroker/{NativeResponse.d.ts → PlatformAuthResponse.d.ts} +24 -2
  154. package/lib/types/broker/nativeBroker/PlatformAuthResponse.d.ts.map +1 -0
  155. package/lib/types/cache/BrowserCacheManager.d.ts +6 -2
  156. package/lib/types/cache/BrowserCacheManager.d.ts.map +1 -1
  157. package/lib/types/controllers/IController.d.ts +1 -1
  158. package/lib/types/controllers/IController.d.ts.map +1 -1
  159. package/lib/types/controllers/NestedAppAuthController.d.ts +1 -1
  160. package/lib/types/controllers/NestedAppAuthController.d.ts.map +1 -1
  161. package/lib/types/controllers/StandardController.d.ts +4 -3
  162. package/lib/types/controllers/StandardController.d.ts.map +1 -1
  163. package/lib/types/event/EventMessage.d.ts +10 -1
  164. package/lib/types/event/EventMessage.d.ts.map +1 -1
  165. package/lib/types/event/EventType.d.ts +1 -0
  166. package/lib/types/event/EventType.d.ts.map +1 -1
  167. package/lib/types/index.d.ts +2 -1
  168. package/lib/types/index.d.ts.map +1 -1
  169. package/lib/types/interaction_client/BaseInteractionClient.d.ts +3 -3
  170. package/lib/types/interaction_client/BaseInteractionClient.d.ts.map +1 -1
  171. package/lib/types/interaction_client/{NativeInteractionClient.d.ts → PlatformAuthInteractionClient.d.ts} +21 -23
  172. package/lib/types/interaction_client/PlatformAuthInteractionClient.d.ts.map +1 -0
  173. package/lib/types/interaction_client/PopupClient.d.ts +2 -2
  174. package/lib/types/interaction_client/PopupClient.d.ts.map +1 -1
  175. package/lib/types/interaction_client/RedirectClient.d.ts +2 -2
  176. package/lib/types/interaction_client/RedirectClient.d.ts.map +1 -1
  177. package/lib/types/interaction_client/SilentAuthCodeClient.d.ts +2 -2
  178. package/lib/types/interaction_client/SilentAuthCodeClient.d.ts.map +1 -1
  179. package/lib/types/interaction_client/SilentIframeClient.d.ts +2 -2
  180. package/lib/types/interaction_client/SilentIframeClient.d.ts.map +1 -1
  181. package/lib/types/packageMetadata.d.ts +1 -1
  182. package/lib/types/protocol/Authorize.d.ts +4 -4
  183. package/lib/types/protocol/Authorize.d.ts.map +1 -1
  184. package/lib/types/utils/BrowserConstants.d.ts +8 -1
  185. package/lib/types/utils/BrowserConstants.d.ts.map +1 -1
  186. package/lib/types/utils/MsalFrameStatsUtils.d.ts +3 -0
  187. package/lib/types/utils/MsalFrameStatsUtils.d.ts.map +1 -0
  188. package/package.json +3 -2
  189. package/src/app/PublicClientApplication.ts +2 -1
  190. package/src/broker/nativeBroker/IPlatformAuthHandler.ts +17 -0
  191. package/src/broker/nativeBroker/PlatformAuthDOMHandler.ts +248 -0
  192. package/src/broker/nativeBroker/{NativeMessageHandler.ts → PlatformAuthExtensionHandler.ts} +90 -79
  193. package/src/broker/nativeBroker/PlatformAuthProvider.ts +164 -0
  194. package/src/broker/nativeBroker/{NativeRequest.ts → PlatformAuthRequest.ts} +41 -2
  195. package/src/broker/nativeBroker/{NativeResponse.ts → PlatformAuthResponse.ts} +25 -1
  196. package/src/cache/BrowserCacheManager.ts +40 -4
  197. package/src/controllers/IController.ts +4 -1
  198. package/src/controllers/NestedAppAuthController.ts +5 -1
  199. package/src/controllers/StandardController.ts +87 -46
  200. package/src/event/EventMessage.ts +11 -0
  201. package/src/event/EventType.ts +1 -0
  202. package/src/index.ts +3 -0
  203. package/src/interaction_client/BaseInteractionClient.ts +4 -4
  204. package/src/interaction_client/{NativeInteractionClient.ts → PlatformAuthInteractionClient.ts} +136 -167
  205. package/src/interaction_client/PopupClient.ts +8 -7
  206. package/src/interaction_client/RedirectClient.ts +12 -12
  207. package/src/interaction_client/SilentAuthCodeClient.ts +3 -3
  208. package/src/interaction_client/SilentIframeClient.ts +12 -12
  209. package/src/packageMetadata.ts +1 -1
  210. package/src/protocol/Authorize.ts +12 -10
  211. package/src/utils/BrowserConstants.ts +9 -1
  212. package/src/utils/MsalFrameStatsUtils.ts +32 -0
  213. package/dist/broker/nativeBroker/NativeMessageHandler.d.ts.map +0 -1
  214. package/dist/broker/nativeBroker/NativeMessageHandler.mjs.map +0 -1
  215. package/dist/broker/nativeBroker/NativeRequest.d.ts.map +0 -1
  216. package/dist/broker/nativeBroker/NativeResponse.d.ts.map +0 -1
  217. package/dist/interaction_client/NativeInteractionClient.d.ts.map +0 -1
  218. package/dist/interaction_client/NativeInteractionClient.mjs.map +0 -1
  219. package/lib/types/broker/nativeBroker/NativeMessageHandler.d.ts.map +0 -1
  220. package/lib/types/broker/nativeBroker/NativeRequest.d.ts.map +0 -1
  221. package/lib/types/broker/nativeBroker/NativeResponse.d.ts.map +0 -1
  222. package/lib/types/interaction_client/NativeInteractionClient.d.ts.map +0 -1
@@ -1,8 +1,8 @@
1
- /*! @azure/msal-browser v4.11.1 2025-04-29 */
1
+ /*! @azure/msal-browser v4.13.0 2025-05-30 */
2
2
  'use strict';
3
3
  'use strict';
4
4
 
5
- /*! @azure/msal-common v15.5.2 2025-04-29 */
5
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6
6
  /*
7
7
  * Copyright (c) Microsoft Corporation. All rights reserved.
8
8
  * Licensed under the MIT License.
@@ -256,13 +256,6 @@ const Errors = {
256
256
  INVALID_GRANT_ERROR: "invalid_grant",
257
257
  CLIENT_MISMATCH_ERROR: "client_mismatch",
258
258
  };
259
- /**
260
- * Response codes
261
- */
262
- const ResponseCodes = {
263
- httpSuccess: 200,
264
- httpBadRequest: 400,
265
- };
266
259
  /**
267
260
  * Region Discovery Sources
268
261
  */
@@ -305,7 +298,7 @@ const JsonWebTokenTypes = {
305
298
  // Token renewal offset default in seconds
306
299
  const DEFAULT_TOKEN_RENEWAL_OFFSET_SEC = 300;
307
300
 
308
- /*! @azure/msal-common v15.5.2 2025-04-29 */
301
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
309
302
  /*
310
303
  * Copyright (c) Microsoft Corporation. All rights reserved.
311
304
  * Licensed under the MIT License.
@@ -322,7 +315,7 @@ var AuthErrorCodes = /*#__PURE__*/Object.freeze({
322
315
  unexpectedError: unexpectedError
323
316
  });
324
317
 
325
- /*! @azure/msal-common v15.5.2 2025-04-29 */
318
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
326
319
 
327
320
  /*
328
321
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -371,7 +364,7 @@ function createAuthError(code, additionalMessage) {
371
364
  : AuthErrorMessages[code]);
372
365
  }
373
366
 
374
- /*! @azure/msal-common v15.5.2 2025-04-29 */
367
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
375
368
  /*
376
369
  * Copyright (c) Microsoft Corporation. All rights reserved.
377
370
  * Licensed under the MIT License.
@@ -469,7 +462,7 @@ var ClientAuthErrorCodes = /*#__PURE__*/Object.freeze({
469
462
  userTimeoutReached: userTimeoutReached
470
463
  });
471
464
 
472
- /*! @azure/msal-common v15.5.2 2025-04-29 */
465
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
473
466
 
474
467
  /*
475
468
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -721,7 +714,7 @@ function createClientAuthError(errorCode, additionalMessage) {
721
714
  return new ClientAuthError(errorCode, additionalMessage);
722
715
  }
723
716
 
724
- /*! @azure/msal-common v15.5.2 2025-04-29 */
717
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
725
718
 
726
719
  /*
727
720
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -760,7 +753,7 @@ const DEFAULT_CRYPTO_IMPLEMENTATION = {
760
753
  },
761
754
  };
762
755
 
763
- /*! @azure/msal-common v15.5.2 2025-04-29 */
756
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
764
757
 
765
758
  /*
766
759
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -951,12 +944,12 @@ class Logger {
951
944
  }
952
945
  }
953
946
 
954
- /*! @azure/msal-common v15.5.2 2025-04-29 */
947
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
955
948
  /* eslint-disable header/header */
956
949
  const name$1 = "@azure/msal-common";
957
- const version$1 = "15.5.2";
950
+ const version$1 = "15.7.0";
958
951
 
959
- /*! @azure/msal-common v15.5.2 2025-04-29 */
952
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
960
953
  /*
961
954
  * Copyright (c) Microsoft Corporation. All rights reserved.
962
955
  * Licensed under the MIT License.
@@ -976,7 +969,7 @@ const AzureCloudInstance = {
976
969
  AzureUsGovernment: "https://login.microsoftonline.us",
977
970
  };
978
971
 
979
- /*! @azure/msal-common v15.5.2 2025-04-29 */
972
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
980
973
 
981
974
  /*
982
975
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -1037,7 +1030,7 @@ function checkMaxAge(authTime, maxAge) {
1037
1030
  }
1038
1031
  }
1039
1032
 
1040
- /*! @azure/msal-common v15.5.2 2025-04-29 */
1033
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
1041
1034
  /*
1042
1035
  * Copyright (c) Microsoft Corporation. All rights reserved.
1043
1036
  * Licensed under the MIT License.
@@ -1092,7 +1085,7 @@ function wasClockTurnedBack(cachedAt) {
1092
1085
  return cachedAtSec > nowSeconds();
1093
1086
  }
1094
1087
 
1095
- /*! @azure/msal-common v15.5.2 2025-04-29 */
1088
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
1096
1089
 
1097
1090
  /*
1098
1091
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -1419,7 +1412,7 @@ function isAuthorityMetadataExpired(metadata) {
1419
1412
  return metadata.expiresAt <= nowSeconds();
1420
1413
  }
1421
1414
 
1422
- /*! @azure/msal-common v15.5.2 2025-04-29 */
1415
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
1423
1416
  /*
1424
1417
  * Copyright (c) Microsoft Corporation. All rights reserved.
1425
1418
  * Licensed under the MIT License.
@@ -1473,7 +1466,7 @@ var ClientConfigurationErrorCodes = /*#__PURE__*/Object.freeze({
1473
1466
  urlParseError: urlParseError
1474
1467
  });
1475
1468
 
1476
- /*! @azure/msal-common v15.5.2 2025-04-29 */
1469
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
1477
1470
 
1478
1471
  /*
1479
1472
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -1611,7 +1604,7 @@ function createClientConfigurationError(errorCode) {
1611
1604
  return new ClientConfigurationError(errorCode);
1612
1605
  }
1613
1606
 
1614
- /*! @azure/msal-common v15.5.2 2025-04-29 */
1607
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
1615
1608
  /*
1616
1609
  * Copyright (c) Microsoft Corporation. All rights reserved.
1617
1610
  * Licensed under the MIT License.
@@ -1708,7 +1701,7 @@ class StringUtils {
1708
1701
  }
1709
1702
  }
1710
1703
 
1711
- /*! @azure/msal-common v15.5.2 2025-04-29 */
1704
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
1712
1705
 
1713
1706
  /*
1714
1707
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -1899,7 +1892,7 @@ class ScopeSet {
1899
1892
  }
1900
1893
  }
1901
1894
 
1902
- /*! @azure/msal-common v15.5.2 2025-04-29 */
1895
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
1903
1896
 
1904
1897
  /*
1905
1898
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -1939,7 +1932,7 @@ function buildClientInfoFromHomeAccountId(homeAccountId) {
1939
1932
  };
1940
1933
  }
1941
1934
 
1942
- /*! @azure/msal-common v15.5.2 2025-04-29 */
1935
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
1943
1936
  /*
1944
1937
  * Copyright (c) Microsoft Corporation. All rights reserved.
1945
1938
  * Licensed under the MIT License.
@@ -2018,7 +2011,7 @@ function updateAccountTenantProfileData(baseAccountInfo, tenantProfile, idTokenC
2018
2011
  return updatedAccountInfo;
2019
2012
  }
2020
2013
 
2021
- /*! @azure/msal-common v15.5.2 2025-04-29 */
2014
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
2022
2015
  /*
2023
2016
  * Copyright (c) Microsoft Corporation. All rights reserved.
2024
2017
  * Licensed under the MIT License.
@@ -2033,7 +2026,7 @@ const AuthorityType = {
2033
2026
  Ciam: 3,
2034
2027
  };
2035
2028
 
2036
- /*! @azure/msal-common v15.5.2 2025-04-29 */
2029
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
2037
2030
  /*
2038
2031
  * Copyright (c) Microsoft Corporation. All rights reserved.
2039
2032
  * Licensed under the MIT License.
@@ -2055,7 +2048,7 @@ function getTenantIdFromIdTokenClaims(idTokenClaims) {
2055
2048
  return null;
2056
2049
  }
2057
2050
 
2058
- /*! @azure/msal-common v15.5.2 2025-04-29 */
2051
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
2059
2052
  /*
2060
2053
  * Copyright (c) Microsoft Corporation. All rights reserved.
2061
2054
  * Licensed under the MIT License.
@@ -2079,7 +2072,7 @@ const ProtocolMode = {
2079
2072
  EAR: "EAR",
2080
2073
  };
2081
2074
 
2082
- /*! @azure/msal-common v15.5.2 2025-04-29 */
2075
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
2083
2076
 
2084
2077
  /*
2085
2078
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -2322,7 +2315,7 @@ class AccountEntity {
2322
2315
  }
2323
2316
  }
2324
2317
 
2325
- /*! @azure/msal-common v15.5.2 2025-04-29 */
2318
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
2326
2319
 
2327
2320
  /*
2328
2321
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -2387,7 +2380,7 @@ function mapToQueryString(parameters, encodeExtraParams = true, extraQueryParame
2387
2380
  return queryParameterArray.join("&");
2388
2381
  }
2389
2382
 
2390
- /*! @azure/msal-common v15.5.2 2025-04-29 */
2383
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
2391
2384
 
2392
2385
  /*
2393
2386
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -2551,7 +2544,7 @@ class UrlString {
2551
2544
  }
2552
2545
  }
2553
2546
 
2554
- /*! @azure/msal-common v15.5.2 2025-04-29 */
2547
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
2555
2548
 
2556
2549
  /*
2557
2550
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -2691,7 +2684,7 @@ function getCloudDiscoveryMetadataFromNetworkResponse(response, authorityHost) {
2691
2684
  return null;
2692
2685
  }
2693
2686
 
2694
- /*! @azure/msal-common v15.5.2 2025-04-29 */
2687
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
2695
2688
  /*
2696
2689
  * Copyright (c) Microsoft Corporation. All rights reserved.
2697
2690
  * Licensed under the MIT License.
@@ -2699,7 +2692,7 @@ function getCloudDiscoveryMetadataFromNetworkResponse(response, authorityHost) {
2699
2692
  const cacheQuotaExceededErrorCode = "cache_quota_exceeded";
2700
2693
  const cacheUnknownErrorCode = "cache_error_unknown";
2701
2694
 
2702
- /*! @azure/msal-common v15.5.2 2025-04-29 */
2695
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
2703
2696
 
2704
2697
  /*
2705
2698
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -2726,7 +2719,7 @@ class CacheError extends Error {
2726
2719
  }
2727
2720
  }
2728
2721
 
2729
- /*! @azure/msal-common v15.5.2 2025-04-29 */
2722
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
2730
2723
 
2731
2724
  /*
2732
2725
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -3911,7 +3904,7 @@ class DefaultStorageClass extends CacheManager {
3911
3904
  }
3912
3905
  }
3913
3906
 
3914
- /*! @azure/msal-common v15.5.2 2025-04-29 */
3907
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
3915
3908
 
3916
3909
  /*
3917
3910
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -4011,7 +4004,7 @@ function isOidcProtocolMode(config) {
4011
4004
  return (config.authOptions.authority.options.protocolMode === ProtocolMode.OIDC);
4012
4005
  }
4013
4006
 
4014
- /*! @azure/msal-common v15.5.2 2025-04-29 */
4007
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
4015
4008
  /*
4016
4009
  * Copyright (c) Microsoft Corporation. All rights reserved.
4017
4010
  * Licensed under the MIT License.
@@ -4021,7 +4014,7 @@ const CcsCredentialType = {
4021
4014
  UPN: "UPN",
4022
4015
  };
4023
4016
 
4024
- /*! @azure/msal-common v15.5.2 2025-04-29 */
4017
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
4025
4018
  /*
4026
4019
  * Copyright (c) Microsoft Corporation. All rights reserved.
4027
4020
  * Licensed under the MIT License.
@@ -4071,7 +4064,7 @@ const INSTANCE_AWARE = "instance_aware";
4071
4064
  const EAR_JWK = "ear_jwk";
4072
4065
  const EAR_JWE_CRYPTO = "ear_jwe_crypto";
4073
4066
 
4074
- /*! @azure/msal-common v15.5.2 2025-04-29 */
4067
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
4075
4068
 
4076
4069
  /*
4077
4070
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -4439,7 +4432,7 @@ function addEARParameters(parameters, jwk) {
4439
4432
  parameters.set(EAR_JWE_CRYPTO, jweCryptoB64Encoded);
4440
4433
  }
4441
4434
 
4442
- /*! @azure/msal-common v15.5.2 2025-04-29 */
4435
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
4443
4436
  /*
4444
4437
  * Copyright (c) Microsoft Corporation. All rights reserved.
4445
4438
  * Licensed under the MIT License.
@@ -4451,7 +4444,7 @@ function isOpenIdConfigResponse(response) {
4451
4444
  response.hasOwnProperty("jwks_uri"));
4452
4445
  }
4453
4446
 
4454
- /*! @azure/msal-common v15.5.2 2025-04-29 */
4447
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
4455
4448
  /*
4456
4449
  * Copyright (c) Microsoft Corporation. All rights reserved.
4457
4450
  * Licensed under the MIT License.
@@ -4461,7 +4454,7 @@ function isCloudInstanceDiscoveryResponse(response) {
4461
4454
  response.hasOwnProperty("metadata"));
4462
4455
  }
4463
4456
 
4464
- /*! @azure/msal-common v15.5.2 2025-04-29 */
4457
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
4465
4458
  /*
4466
4459
  * Copyright (c) Microsoft Corporation. All rights reserved.
4467
4460
  * Licensed under the MIT License.
@@ -4471,7 +4464,7 @@ function isCloudInstanceDiscoveryErrorResponse(response) {
4471
4464
  response.hasOwnProperty("error_description"));
4472
4465
  }
4473
4466
 
4474
- /*! @azure/msal-common v15.5.2 2025-04-29 */
4467
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
4475
4468
  /*
4476
4469
  * Copyright (c) Microsoft Corporation. All rights reserved.
4477
4470
  * Licensed under the MIT License.
@@ -4984,7 +4977,7 @@ const IntFields = new Set([
4984
4977
  "encryptedCacheExpiredCount",
4985
4978
  ]);
4986
4979
 
4987
- /*! @azure/msal-common v15.5.2 2025-04-29 */
4980
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
4988
4981
  /*
4989
4982
  * Copyright (c) Microsoft Corporation. All rights reserved.
4990
4983
  * Licensed under the MIT License.
@@ -5080,7 +5073,7 @@ const invokeAsync = (callback, eventName, logger, telemetryClient, correlationId
5080
5073
  };
5081
5074
  };
5082
5075
 
5083
- /*! @azure/msal-common v15.5.2 2025-04-29 */
5076
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
5084
5077
 
5085
5078
  /*
5086
5079
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -5107,15 +5100,13 @@ class RegionDiscovery {
5107
5100
  const options = RegionDiscovery.IMDS_OPTIONS;
5108
5101
  try {
5109
5102
  const localIMDSVersionResponse = await invokeAsync(this.getRegionFromIMDS.bind(this), PerformanceEvents.RegionDiscoveryGetRegionFromIMDS, this.logger, this.performanceClient, this.correlationId)(Constants.IMDS_VERSION, options);
5110
- if (localIMDSVersionResponse.status ===
5111
- ResponseCodes.httpSuccess) {
5103
+ if (localIMDSVersionResponse.status === HttpStatus.SUCCESS) {
5112
5104
  autodetectedRegionName = localIMDSVersionResponse.body;
5113
5105
  regionDiscoveryMetadata.region_source =
5114
5106
  RegionDiscoverySources.IMDS;
5115
5107
  }
5116
5108
  // If the response using the local IMDS version failed, try to fetch the current version of IMDS and retry.
5117
- if (localIMDSVersionResponse.status ===
5118
- ResponseCodes.httpBadRequest) {
5109
+ if (localIMDSVersionResponse.status === HttpStatus.BAD_REQUEST) {
5119
5110
  const currentIMDSVersion = await invokeAsync(this.getCurrentVersion.bind(this), PerformanceEvents.RegionDiscoveryGetCurrentVersion, this.logger, this.performanceClient, this.correlationId)(options);
5120
5111
  if (!currentIMDSVersion) {
5121
5112
  regionDiscoveryMetadata.region_source =
@@ -5123,8 +5114,7 @@ class RegionDiscovery {
5123
5114
  return null;
5124
5115
  }
5125
5116
  const currentIMDSVersionResponse = await invokeAsync(this.getRegionFromIMDS.bind(this), PerformanceEvents.RegionDiscoveryGetRegionFromIMDS, this.logger, this.performanceClient, this.correlationId)(currentIMDSVersion, options);
5126
- if (currentIMDSVersionResponse.status ===
5127
- ResponseCodes.httpSuccess) {
5117
+ if (currentIMDSVersionResponse.status === HttpStatus.SUCCESS) {
5128
5118
  autodetectedRegionName =
5129
5119
  currentIMDSVersionResponse.body;
5130
5120
  regionDiscoveryMetadata.region_source =
@@ -5169,7 +5159,7 @@ class RegionDiscovery {
5169
5159
  try {
5170
5160
  const response = await this.networkInterface.sendGetRequestAsync(`${Constants.IMDS_ENDPOINT}?format=json`, options);
5171
5161
  // When IMDS endpoint is called without the api version query param, bad request response comes back with latest version.
5172
- if (response.status === ResponseCodes.httpBadRequest &&
5162
+ if (response.status === HttpStatus.BAD_REQUEST &&
5173
5163
  response.body &&
5174
5164
  response.body["newest-versions"] &&
5175
5165
  response.body["newest-versions"].length > 0) {
@@ -5189,7 +5179,7 @@ RegionDiscovery.IMDS_OPTIONS = {
5189
5179
  },
5190
5180
  };
5191
5181
 
5192
- /*! @azure/msal-common v15.5.2 2025-04-29 */
5182
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
5193
5183
 
5194
5184
  /*
5195
5185
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -6028,7 +6018,7 @@ function buildStaticAuthorityOptions(authOptions) {
6028
6018
  };
6029
6019
  }
6030
6020
 
6031
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6021
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6032
6022
 
6033
6023
  /*
6034
6024
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -6059,7 +6049,7 @@ async function createDiscoveredInstance(authorityUri, networkClient, cacheManage
6059
6049
  }
6060
6050
  }
6061
6051
 
6062
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6052
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6063
6053
 
6064
6054
  /*
6065
6055
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -6078,7 +6068,7 @@ class ServerError extends AuthError {
6078
6068
  }
6079
6069
  }
6080
6070
 
6081
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6071
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6082
6072
  /*
6083
6073
  * Copyright (c) Microsoft Corporation. All rights reserved.
6084
6074
  * Licensed under the MIT License.
@@ -6099,7 +6089,7 @@ function getRequestThumbprint(clientId, request, homeAccountId) {
6099
6089
  };
6100
6090
  }
6101
6091
 
6102
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6092
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6103
6093
 
6104
6094
  /*
6105
6095
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -6186,7 +6176,7 @@ class ThrottlingUtils {
6186
6176
  }
6187
6177
  }
6188
6178
 
6189
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6179
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6190
6180
 
6191
6181
  /*
6192
6182
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -6217,7 +6207,7 @@ function createNetworkError(error, httpStatus, responseHeaders, additionalError)
6217
6207
  return new NetworkError(error, httpStatus, responseHeaders);
6218
6208
  }
6219
6209
 
6220
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6210
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6221
6211
 
6222
6212
  /*
6223
6213
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -6365,7 +6355,7 @@ class BaseClient {
6365
6355
  }
6366
6356
  }
6367
6357
 
6368
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6358
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6369
6359
  /*
6370
6360
  * Copyright (c) Microsoft Corporation. All rights reserved.
6371
6361
  * Licensed under the MIT License.
@@ -6391,7 +6381,7 @@ var InteractionRequiredAuthErrorCodes = /*#__PURE__*/Object.freeze({
6391
6381
  refreshTokenExpired: refreshTokenExpired
6392
6382
  });
6393
6383
 
6394
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6384
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6395
6385
 
6396
6386
  /*
6397
6387
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -6479,7 +6469,7 @@ function createInteractionRequiredAuthError(errorCode) {
6479
6469
  return new InteractionRequiredAuthError(errorCode, InteractionRequiredAuthErrorMessages[errorCode]);
6480
6470
  }
6481
6471
 
6482
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6472
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6483
6473
 
6484
6474
  /*
6485
6475
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -6551,7 +6541,7 @@ class ProtocolUtils {
6551
6541
  }
6552
6542
  }
6553
6543
 
6554
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6544
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6555
6545
 
6556
6546
  /*
6557
6547
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -6635,7 +6625,7 @@ class PopTokenGenerator {
6635
6625
  }
6636
6626
  }
6637
6627
 
6638
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6628
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6639
6629
  /*
6640
6630
  * Copyright (c) Microsoft Corporation. All rights reserved.
6641
6631
  * Licensed under the MIT License.
@@ -6662,7 +6652,7 @@ class PopTokenGenerator {
6662
6652
  }
6663
6653
  }
6664
6654
 
6665
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6655
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6666
6656
 
6667
6657
  /*
6668
6658
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -6993,7 +6983,7 @@ function buildAccountToCache(cacheStorage, authority, homeAccountId, base64Decod
6993
6983
  return baseAccount;
6994
6984
  }
6995
6985
 
6996
- /*! @azure/msal-common v15.5.2 2025-04-29 */
6986
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
6997
6987
 
6998
6988
  /*
6999
6989
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -7060,7 +7050,7 @@ class RequestValidator {
7060
7050
  }
7061
7051
  }
7062
7052
 
7063
- /*! @azure/msal-common v15.5.2 2025-04-29 */
7053
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
7064
7054
  /*
7065
7055
  * Copyright (c) Microsoft Corporation. All rights reserved.
7066
7056
  * Licensed under the MIT License.
@@ -7078,7 +7068,7 @@ async function getClientAssertion(clientAssertion, clientId, tokenEndpoint) {
7078
7068
  }
7079
7069
  }
7080
7070
 
7081
- /*! @azure/msal-common v15.5.2 2025-04-29 */
7071
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
7082
7072
 
7083
7073
  /*
7084
7074
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -7311,7 +7301,7 @@ class AuthorizationCodeClient extends BaseClient {
7311
7301
  }
7312
7302
  }
7313
7303
 
7314
- /*! @azure/msal-common v15.5.2 2025-04-29 */
7304
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
7315
7305
 
7316
7306
  /*
7317
7307
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -7520,7 +7510,7 @@ class RefreshTokenClient extends BaseClient {
7520
7510
  }
7521
7511
  }
7522
7512
 
7523
- /*! @azure/msal-common v15.5.2 2025-04-29 */
7513
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
7524
7514
 
7525
7515
  /*
7526
7516
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -7618,7 +7608,7 @@ class SilentFlowClient extends BaseClient {
7618
7608
  }
7619
7609
  }
7620
7610
 
7621
- /*! @azure/msal-common v15.5.2 2025-04-29 */
7611
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
7622
7612
 
7623
7613
  /*
7624
7614
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -7633,7 +7623,7 @@ const StubbedNetworkModule = {
7633
7623
  },
7634
7624
  };
7635
7625
 
7636
- /*! @azure/msal-common v15.5.2 2025-04-29 */
7626
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
7637
7627
 
7638
7628
  /*
7639
7629
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -7857,7 +7847,7 @@ function extractLoginHint(account) {
7857
7847
  return account.idTokenClaims?.login_hint || null;
7858
7848
  }
7859
7849
 
7860
- /*! @azure/msal-common v15.5.2 2025-04-29 */
7850
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
7861
7851
 
7862
7852
  /*
7863
7853
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -7915,7 +7905,7 @@ class AuthenticationHeaderParser {
7915
7905
  }
7916
7906
  }
7917
7907
 
7918
- /*! @azure/msal-common v15.5.2 2025-04-29 */
7908
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
7919
7909
 
7920
7910
  /*
7921
7911
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -8178,7 +8168,7 @@ class ServerTelemetryManager {
8178
8168
  }
8179
8169
  }
8180
8170
 
8181
- /*! @azure/msal-common v15.5.2 2025-04-29 */
8171
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
8182
8172
  /*
8183
8173
  * Copyright (c) Microsoft Corporation. All rights reserved.
8184
8174
  * Licensed under the MIT License.
@@ -8186,7 +8176,7 @@ class ServerTelemetryManager {
8186
8176
  const missingKidError = "missing_kid_error";
8187
8177
  const missingAlgError = "missing_alg_error";
8188
8178
 
8189
- /*! @azure/msal-common v15.5.2 2025-04-29 */
8179
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
8190
8180
 
8191
8181
  /*
8192
8182
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -8211,7 +8201,7 @@ function createJoseHeaderError(code) {
8211
8201
  return new JoseHeaderError(code, JoseHeaderErrorMessages[code]);
8212
8202
  }
8213
8203
 
8214
- /*! @azure/msal-common v15.5.2 2025-04-29 */
8204
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
8215
8205
 
8216
8206
  /*
8217
8207
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -8251,7 +8241,7 @@ class JoseHeader {
8251
8241
  }
8252
8242
  }
8253
8243
 
8254
- /*! @azure/msal-common v15.5.2 2025-04-29 */
8244
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
8255
8245
 
8256
8246
  /*
8257
8247
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -8330,7 +8320,7 @@ class StubPerformanceClient {
8330
8320
  }
8331
8321
  }
8332
8322
 
8333
- /*! @azure/msal-common v15.5.2 2025-04-29 */
8323
+ /*! @azure/msal-common v15.7.0 2025-05-30 */
8334
8324
 
8335
8325
  /*
8336
8326
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -9349,10 +9339,15 @@ const BrowserConstants = {
9349
9339
  */
9350
9340
  MSAL_SKU: "msal.js.browser",
9351
9341
  };
9352
- const NativeConstants = {
9342
+ const PlatformAuthConstants = {
9353
9343
  CHANNEL_ID: "53ee284d-920a-4b59-9d30-a60315b26836",
9354
9344
  PREFERRED_EXTENSION_ID: "ppnbnpeolgkicgegkbkbjmhlideopiji",
9355
9345
  MATS_TELEMETRY: "MATS",
9346
+ MICROSOFT_ENTRA_BROKERID: "MicrosoftEntra",
9347
+ DOM_API_NAME: "DOM API",
9348
+ PLATFORM_DOM_APIS: "get-token-and-sign-out",
9349
+ PLATFORM_DOM_PROVIDER: "PlatformAuthDOMHandler",
9350
+ PLATFORM_EXTENSION_PROVIDER: "PlatformAuthExtensionHandler",
9356
9351
  };
9357
9352
  const NativeExtensionMethod = {
9358
9353
  HandshakeRequest: "Handshake",
@@ -9390,6 +9385,7 @@ const TemporaryCacheKeys = {
9390
9385
  const StaticCacheKeys = {
9391
9386
  ACCOUNT_KEYS: "msal.account.keys",
9392
9387
  TOKEN_KEYS: "msal.token.keys",
9388
+ VERSION: "msal.version",
9393
9389
  };
9394
9390
  /**
9395
9391
  * Cache keys stored in-memory
@@ -9518,7 +9514,8 @@ const iFrameRenewalPolicies = [
9518
9514
  ];
9519
9515
  const LOG_LEVEL_CACHE_KEY = "msal.browser.log.level";
9520
9516
  const LOG_PII_CACHE_KEY = "msal.browser.log.pii";
9521
- const BROWSER_PERF_ENABLED_KEY = "msal.browser.performance.enabled";
9517
+ const BROWSER_PERF_ENABLED_KEY = "msal.browser.performance.enabled";
9518
+ const PLATFORM_AUTH_DOM_SUPPORT = "msal.browser.platform.auth.dom";
9522
9519
 
9523
9520
  /*
9524
9521
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -10428,7 +10425,7 @@ function buildConfiguration({ auth: userInputAuth, cache: userInputCache, system
10428
10425
 
10429
10426
  /* eslint-disable header/header */
10430
10427
  const name = "@azure/msal-browser";
10431
- const version = "4.11.1";
10428
+ const version = "4.13.0";
10432
10429
 
10433
10430
  /*
10434
10431
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -11780,6 +11777,7 @@ const EventType = {
11780
11777
  LOGOUT_FAILURE: "msal:logoutFailure",
11781
11778
  LOGOUT_END: "msal:logoutEnd",
11782
11779
  RESTORE_FROM_BFCACHE: "msal:restoreFromBFCache",
11780
+ BROKER_CONNECTION_ESTABLISHED: "msal:brokerConnectionEstablished",
11783
11781
  };
11784
11782
 
11785
11783
  /*
@@ -11805,6 +11803,20 @@ class BrowserCacheManager extends CacheManager {
11805
11803
  }
11806
11804
  async initialize(correlationId) {
11807
11805
  await this.browserStorage.initialize(correlationId);
11806
+ this.trackVersionChanges(correlationId);
11807
+ }
11808
+ /**
11809
+ * Tracks upgrades and downgrades for telemetry and debugging purposes
11810
+ */
11811
+ trackVersionChanges(correlationId) {
11812
+ const previousVersion = this.browserStorage.getItem(StaticCacheKeys.VERSION);
11813
+ if (previousVersion) {
11814
+ this.logger.info(`MSAL.js was last initialized by version: ${previousVersion}`);
11815
+ this.performanceClient.addFields({ previousLibraryVersion: previousVersion }, correlationId);
11816
+ }
11817
+ if (previousVersion !== version) {
11818
+ this.browserStorage.setItem(StaticCacheKeys.VERSION, version);
11819
+ }
11808
11820
  }
11809
11821
  /**
11810
11822
  * Parses passed value as JSON object, JSON.parse() will throw an error.
@@ -12525,7 +12537,17 @@ class BrowserCacheManager extends CacheManager {
12525
12537
  getInteractionInProgress() {
12526
12538
  const key = `${Constants.CACHE_PREFIX}.${TemporaryCacheKeys.INTERACTION_STATUS_KEY}`;
12527
12539
  const value = this.getTemporaryCache(key, false);
12528
- return value ? JSON.parse(value) : null;
12540
+ try {
12541
+ return value ? JSON.parse(value) : null;
12542
+ }
12543
+ catch (e) {
12544
+ // Remove interaction and other temp keys if interaction status can't be parsed
12545
+ this.logger.error(`Cannot parse interaction status. Removing temporary cache items and clearing url hash. Retrying interaction should fix the error`);
12546
+ this.removeTemporaryItem(key);
12547
+ this.resetRequestCache();
12548
+ clearHash(window);
12549
+ return null;
12550
+ }
12529
12551
  }
12530
12552
  setInteractionInProgress(inProgress, type = INTERACTION_TYPE.SIGNIN) {
12531
12553
  // Ensure we don't overwrite interaction in progress for a different clientId
@@ -12874,14 +12896,14 @@ class EventHandler {
12874
12896
  * Licensed under the MIT License.
12875
12897
  */
12876
12898
  class BaseInteractionClient {
12877
- constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeMessageHandler, correlationId) {
12899
+ constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, platformAuthProvider, correlationId) {
12878
12900
  this.config = config;
12879
12901
  this.browserStorage = storageImpl;
12880
12902
  this.browserCrypto = browserCrypto;
12881
12903
  this.networkClient = this.config.system.networkClient;
12882
12904
  this.eventHandler = eventHandler;
12883
12905
  this.navigationClient = navigationClient;
12884
- this.nativeMessageHandler = nativeMessageHandler;
12906
+ this.platformAuthProvider = platformAuthProvider;
12885
12907
  this.correlationId = correlationId || createNewGuid();
12886
12908
  this.logger = logger.clone(BrowserConstants.MSAL_SKU, version, this.correlationId);
12887
12909
  this.performanceClient = performanceClient;
@@ -13237,6 +13259,159 @@ class StandardInteractionClient extends BaseInteractionClient {
13237
13259
  }
13238
13260
  }
13239
13261
 
13262
+ /*
13263
+ * Copyright (c) Microsoft Corporation. All rights reserved.
13264
+ * Licensed under the MIT License.
13265
+ */
13266
+ /**
13267
+ * Extracts the BrowserStateObject from the state string.
13268
+ * @param browserCrypto
13269
+ * @param state
13270
+ */
13271
+ function extractBrowserRequestState(browserCrypto, state) {
13272
+ if (!state) {
13273
+ return null;
13274
+ }
13275
+ try {
13276
+ const requestStateObj = ProtocolUtils.parseRequestState(browserCrypto, state);
13277
+ return requestStateObj.libraryState.meta;
13278
+ }
13279
+ catch (e) {
13280
+ throw createClientAuthError(invalidState);
13281
+ }
13282
+ }
13283
+
13284
+ /*
13285
+ * Copyright (c) Microsoft Corporation. All rights reserved.
13286
+ * Licensed under the MIT License.
13287
+ */
13288
+ function deserializeResponse(responseString, responseLocation, logger) {
13289
+ // Deserialize hash fragment response parameters.
13290
+ const serverParams = getDeserializedResponse(responseString);
13291
+ if (!serverParams) {
13292
+ if (!stripLeadingHashOrQuery(responseString)) {
13293
+ // Hash or Query string is empty
13294
+ 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.`);
13295
+ throw createBrowserAuthError(hashEmptyError);
13296
+ }
13297
+ else {
13298
+ 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.`);
13299
+ logger.errorPii(`The ${responseLocation} detected is: ${responseString}`);
13300
+ throw createBrowserAuthError(hashDoesNotContainKnownProperties);
13301
+ }
13302
+ }
13303
+ return serverParams;
13304
+ }
13305
+ /**
13306
+ * Returns the interaction type that the response object belongs to
13307
+ */
13308
+ function validateInteractionType(response, browserCrypto, interactionType) {
13309
+ if (!response.state) {
13310
+ throw createBrowserAuthError(noStateInHash);
13311
+ }
13312
+ const platformStateObj = extractBrowserRequestState(browserCrypto, response.state);
13313
+ if (!platformStateObj) {
13314
+ throw createBrowserAuthError(unableToParseState);
13315
+ }
13316
+ if (platformStateObj.interactionType !== interactionType) {
13317
+ throw createBrowserAuthError(stateInteractionTypeMismatch);
13318
+ }
13319
+ }
13320
+
13321
+ /*
13322
+ * Copyright (c) Microsoft Corporation. All rights reserved.
13323
+ * Licensed under the MIT License.
13324
+ */
13325
+ /**
13326
+ * Abstract class which defines operations for a browser interaction handling class.
13327
+ */
13328
+ class InteractionHandler {
13329
+ constructor(authCodeModule, storageImpl, authCodeRequest, logger, performanceClient) {
13330
+ this.authModule = authCodeModule;
13331
+ this.browserStorage = storageImpl;
13332
+ this.authCodeRequest = authCodeRequest;
13333
+ this.logger = logger;
13334
+ this.performanceClient = performanceClient;
13335
+ }
13336
+ /**
13337
+ * Function to handle response parameters from hash.
13338
+ * @param locationHash
13339
+ */
13340
+ async handleCodeResponse(response, request) {
13341
+ this.performanceClient.addQueueMeasurement(PerformanceEvents.HandleCodeResponse, request.correlationId);
13342
+ let authCodeResponse;
13343
+ try {
13344
+ authCodeResponse = getAuthorizationCodePayload(response, request.state);
13345
+ }
13346
+ catch (e) {
13347
+ if (e instanceof ServerError &&
13348
+ e.subError === userCancelled) {
13349
+ // Translate server error caused by user closing native prompt to corresponding first class MSAL error
13350
+ throw createBrowserAuthError(userCancelled);
13351
+ }
13352
+ else {
13353
+ throw e;
13354
+ }
13355
+ }
13356
+ return invokeAsync(this.handleCodeResponseFromServer.bind(this), PerformanceEvents.HandleCodeResponseFromServer, this.logger, this.performanceClient, request.correlationId)(authCodeResponse, request);
13357
+ }
13358
+ /**
13359
+ * Process auth code response from AAD
13360
+ * @param authCodeResponse
13361
+ * @param state
13362
+ * @param authority
13363
+ * @param networkModule
13364
+ * @returns
13365
+ */
13366
+ async handleCodeResponseFromServer(authCodeResponse, request, validateNonce = true) {
13367
+ this.performanceClient.addQueueMeasurement(PerformanceEvents.HandleCodeResponseFromServer, request.correlationId);
13368
+ this.logger.trace("InteractionHandler.handleCodeResponseFromServer called");
13369
+ // Assign code to request
13370
+ this.authCodeRequest.code = authCodeResponse.code;
13371
+ // Check for new cloud instance
13372
+ if (authCodeResponse.cloud_instance_host_name) {
13373
+ await invokeAsync(this.authModule.updateAuthority.bind(this.authModule), PerformanceEvents.UpdateTokenEndpointAuthority, this.logger, this.performanceClient, request.correlationId)(authCodeResponse.cloud_instance_host_name, request.correlationId);
13374
+ }
13375
+ // Nonce validation not needed when redirect not involved (e.g. hybrid spa, renewing token via rt)
13376
+ if (validateNonce) {
13377
+ // TODO: Assigning "response nonce" to "request nonce" is confusing. Refactor the function doing validation to accept request nonce directly
13378
+ authCodeResponse.nonce = request.nonce || undefined;
13379
+ }
13380
+ authCodeResponse.state = request.state;
13381
+ // Add CCS parameters if available
13382
+ if (authCodeResponse.client_info) {
13383
+ this.authCodeRequest.clientInfo = authCodeResponse.client_info;
13384
+ }
13385
+ else {
13386
+ const ccsCred = this.createCcsCredentials(request);
13387
+ if (ccsCred) {
13388
+ this.authCodeRequest.ccsCredential = ccsCred;
13389
+ }
13390
+ }
13391
+ // Acquire token with retrieved code.
13392
+ const tokenResponse = (await invokeAsync(this.authModule.acquireToken.bind(this.authModule), PerformanceEvents.AuthClientAcquireToken, this.logger, this.performanceClient, request.correlationId)(this.authCodeRequest, authCodeResponse));
13393
+ return tokenResponse;
13394
+ }
13395
+ /**
13396
+ * Build ccs creds if available
13397
+ */
13398
+ createCcsCredentials(request) {
13399
+ if (request.account) {
13400
+ return {
13401
+ credential: request.account.homeAccountId,
13402
+ type: CcsCredentialType.HOME_ACCOUNT_ID,
13403
+ };
13404
+ }
13405
+ else if (request.loginHint) {
13406
+ return {
13407
+ credential: request.loginHint,
13408
+ type: CcsCredentialType.UPN,
13409
+ };
13410
+ }
13411
+ return null;
13412
+ }
13413
+ }
13414
+
13240
13415
  /*
13241
13416
  * Copyright (c) Microsoft Corporation. All rights reserved.
13242
13417
  * Licensed under the MIT License.
@@ -13321,930 +13496,1153 @@ function createNativeAuthError(code, description, ext) {
13321
13496
  * Copyright (c) Microsoft Corporation. All rights reserved.
13322
13497
  * Licensed under the MIT License.
13323
13498
  */
13324
- class NativeMessageHandler {
13325
- constructor(logger, handshakeTimeoutMs, performanceClient, extensionId) {
13326
- this.logger = logger;
13327
- this.handshakeTimeoutMs = handshakeTimeoutMs;
13328
- this.extensionId = extensionId;
13329
- this.resolvers = new Map(); // Used for non-handshake messages
13330
- this.handshakeResolvers = new Map(); // Used for handshake messages
13331
- this.messageChannel = new MessageChannel();
13332
- this.windowListener = this.onWindowMessage.bind(this); // Window event callback doesn't have access to 'this' unless it's bound
13333
- this.performanceClient = performanceClient;
13334
- this.handshakeEvent = performanceClient.startMeasurement(PerformanceEvents.NativeMessageHandlerHandshake);
13335
- }
13499
+ class SilentCacheClient extends StandardInteractionClient {
13336
13500
  /**
13337
- * Sends a given message to the extension and resolves with the extension response
13338
- * @param body
13501
+ * Returns unexpired tokens from the cache, if available
13502
+ * @param silentRequest
13339
13503
  */
13340
- async sendMessage(body) {
13341
- this.logger.trace("NativeMessageHandler - sendMessage called.");
13342
- const req = {
13343
- channel: NativeConstants.CHANNEL_ID,
13344
- extensionId: this.extensionId,
13345
- responseId: createNewGuid(),
13346
- body: body,
13347
- };
13348
- this.logger.trace("NativeMessageHandler - Sending request to browser extension");
13349
- this.logger.tracePii(`NativeMessageHandler - Sending request to browser extension: ${JSON.stringify(req)}`);
13350
- this.messageChannel.port1.postMessage(req);
13351
- return new Promise((resolve, reject) => {
13352
- this.resolvers.set(req.responseId, { resolve, reject });
13504
+ async acquireToken(silentRequest) {
13505
+ this.performanceClient.addQueueMeasurement(PerformanceEvents.SilentCacheClientAcquireToken, silentRequest.correlationId);
13506
+ // Telemetry manager only used to increment cacheHits here
13507
+ const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenSilent_silentFlow);
13508
+ const clientConfig = await invokeAsync(this.getClientConfiguration.bind(this), PerformanceEvents.StandardInteractionClientGetClientConfiguration, this.logger, this.performanceClient, this.correlationId)({
13509
+ serverTelemetryManager,
13510
+ requestAuthority: silentRequest.authority,
13511
+ requestAzureCloudOptions: silentRequest.azureCloudOptions,
13512
+ account: silentRequest.account,
13353
13513
  });
13354
- }
13355
- /**
13356
- * Returns an instance of the MessageHandler that has successfully established a connection with an extension
13357
- * @param {Logger} logger
13358
- * @param {number} handshakeTimeoutMs
13359
- * @param {IPerformanceClient} performanceClient
13360
- * @param {ICrypto} crypto
13361
- */
13362
- static async createProvider(logger, handshakeTimeoutMs, performanceClient) {
13363
- logger.trace("NativeMessageHandler - createProvider called.");
13514
+ const silentAuthClient = new SilentFlowClient(clientConfig, this.performanceClient);
13515
+ this.logger.verbose("Silent auth client created");
13364
13516
  try {
13365
- const preferredProvider = new NativeMessageHandler(logger, handshakeTimeoutMs, performanceClient, NativeConstants.PREFERRED_EXTENSION_ID);
13366
- await preferredProvider.sendHandshakeRequest();
13367
- return preferredProvider;
13517
+ const response = await invokeAsync(silentAuthClient.acquireCachedToken.bind(silentAuthClient), PerformanceEvents.SilentFlowClientAcquireCachedToken, this.logger, this.performanceClient, silentRequest.correlationId)(silentRequest);
13518
+ const authResponse = response[0];
13519
+ this.performanceClient.addFields({
13520
+ fromCache: true,
13521
+ }, silentRequest.correlationId);
13522
+ return authResponse;
13368
13523
  }
13369
- catch (e) {
13370
- // If preferred extension fails for whatever reason, fallback to using any installed extension
13371
- const backupProvider = new NativeMessageHandler(logger, handshakeTimeoutMs, performanceClient);
13372
- await backupProvider.sendHandshakeRequest();
13373
- return backupProvider;
13524
+ catch (error) {
13525
+ if (error instanceof BrowserAuthError &&
13526
+ error.errorCode === cryptoKeyNotFound) {
13527
+ this.logger.verbose("Signing keypair for bound access token not found. Refreshing bound access token and generating a new crypto keypair.");
13528
+ }
13529
+ throw error;
13374
13530
  }
13375
13531
  }
13376
13532
  /**
13377
- * Send handshake request helper.
13533
+ * API to silenty clear the browser cache.
13534
+ * @param logoutRequest
13378
13535
  */
13379
- async sendHandshakeRequest() {
13380
- this.logger.trace("NativeMessageHandler - sendHandshakeRequest called.");
13381
- // Register this event listener before sending handshake
13382
- window.addEventListener("message", this.windowListener, false); // false is important, because content script message processing should work first
13383
- const req = {
13384
- channel: NativeConstants.CHANNEL_ID,
13385
- extensionId: this.extensionId,
13386
- responseId: createNewGuid(),
13387
- body: {
13388
- method: NativeExtensionMethod.HandshakeRequest,
13389
- },
13390
- };
13391
- this.handshakeEvent.add({
13392
- extensionId: this.extensionId,
13393
- extensionHandshakeTimeoutMs: this.handshakeTimeoutMs,
13394
- });
13395
- this.messageChannel.port1.onmessage = (event) => {
13396
- this.onChannelMessage(event);
13397
- };
13398
- window.postMessage(req, window.origin, [this.messageChannel.port2]);
13399
- return new Promise((resolve, reject) => {
13400
- this.handshakeResolvers.set(req.responseId, { resolve, reject });
13401
- this.timeoutId = window.setTimeout(() => {
13402
- /*
13403
- * Throw an error if neither HandshakeResponse nor original Handshake request are received in a reasonable timeframe.
13404
- * This typically suggests an event handler stopped propagation of the Handshake request but did not respond to it on the MessageChannel port
13405
- */
13406
- window.removeEventListener("message", this.windowListener, false);
13407
- this.messageChannel.port1.close();
13408
- this.messageChannel.port2.close();
13409
- this.handshakeEvent.end({
13410
- extensionHandshakeTimedOut: true,
13411
- success: false,
13412
- });
13413
- reject(createBrowserAuthError(nativeHandshakeTimeout));
13414
- this.handshakeResolvers.delete(req.responseId);
13415
- }, this.handshakeTimeoutMs); // Use a reasonable timeout in milliseconds here
13536
+ logout(logoutRequest) {
13537
+ this.logger.verbose("logoutRedirect called");
13538
+ const validLogoutRequest = this.initializeLogoutRequest(logoutRequest);
13539
+ return this.clearCacheOnLogout(validLogoutRequest?.account);
13540
+ }
13541
+ }
13542
+
13543
+ /*
13544
+ * Copyright (c) Microsoft Corporation. All rights reserved.
13545
+ * Licensed under the MIT License.
13546
+ */
13547
+ class PlatformAuthInteractionClient extends BaseInteractionClient {
13548
+ constructor(config, browserStorage, browserCrypto, logger, eventHandler, navigationClient, apiId, performanceClient, provider, accountId, nativeStorageImpl, correlationId) {
13549
+ super(config, browserStorage, browserCrypto, logger, eventHandler, navigationClient, performanceClient, provider, correlationId);
13550
+ this.apiId = apiId;
13551
+ this.accountId = accountId;
13552
+ this.platformAuthProvider = provider;
13553
+ this.nativeStorageManager = nativeStorageImpl;
13554
+ this.silentCacheClient = new SilentCacheClient(config, this.nativeStorageManager, browserCrypto, logger, eventHandler, navigationClient, performanceClient, provider, correlationId);
13555
+ const extensionName = this.platformAuthProvider.getExtensionName();
13556
+ this.skus = ServerTelemetryManager.makeExtraSkuString({
13557
+ libraryName: BrowserConstants.MSAL_SKU,
13558
+ libraryVersion: version,
13559
+ extensionName: extensionName,
13560
+ extensionVersion: this.platformAuthProvider.getExtensionVersion(),
13416
13561
  });
13417
13562
  }
13418
13563
  /**
13419
- * Invoked when a message is posted to the window. If a handshake request is received it means the extension is not installed.
13420
- * @param event
13564
+ * Adds SKUs to request extra query parameters
13565
+ * @param request {PlatformAuthRequest}
13566
+ * @private
13421
13567
  */
13422
- onWindowMessage(event) {
13423
- this.logger.trace("NativeMessageHandler - onWindowMessage called");
13424
- // We only accept messages from ourselves
13425
- if (event.source !== window) {
13426
- return;
13427
- }
13428
- const request = event.data;
13429
- if (!request.channel ||
13430
- request.channel !== NativeConstants.CHANNEL_ID) {
13431
- return;
13432
- }
13433
- if (request.extensionId && request.extensionId !== this.extensionId) {
13434
- return;
13435
- }
13436
- if (request.body.method === NativeExtensionMethod.HandshakeRequest) {
13437
- const handshakeResolver = this.handshakeResolvers.get(request.responseId);
13438
- /*
13439
- * Filter out responses with no matched resolvers sooner to keep channel ports open while waiting for
13440
- * the proper response.
13441
- */
13442
- if (!handshakeResolver) {
13443
- this.logger.trace(`NativeMessageHandler.onWindowMessage - resolver can't be found for request ${request.responseId}`);
13444
- return;
13445
- }
13446
- // If we receive this message back it means no extension intercepted the request, meaning no extension supporting handshake protocol is installed
13447
- this.logger.verbose(request.extensionId
13448
- ? `Extension with id: ${request.extensionId} not installed`
13449
- : "No extension installed");
13450
- clearTimeout(this.timeoutId);
13451
- this.messageChannel.port1.close();
13452
- this.messageChannel.port2.close();
13453
- window.removeEventListener("message", this.windowListener, false);
13454
- this.handshakeEvent.end({
13455
- success: false,
13456
- extensionInstalled: false,
13457
- });
13458
- handshakeResolver.reject(createBrowserAuthError(nativeExtensionNotInstalled));
13459
- }
13568
+ addRequestSKUs(request) {
13569
+ request.extraParameters = {
13570
+ ...request.extraParameters,
13571
+ [X_CLIENT_EXTRA_SKU]: this.skus,
13572
+ };
13460
13573
  }
13461
13574
  /**
13462
- * Invoked when a message is received from the extension on the MessageChannel port
13463
- * @param event
13575
+ * Acquire token from native platform via browser extension
13576
+ * @param request
13464
13577
  */
13465
- onChannelMessage(event) {
13466
- this.logger.trace("NativeMessageHandler - onChannelMessage called.");
13467
- const request = event.data;
13468
- const resolver = this.resolvers.get(request.responseId);
13469
- const handshakeResolver = this.handshakeResolvers.get(request.responseId);
13578
+ async acquireToken(request, cacheLookupPolicy) {
13579
+ this.performanceClient.addQueueMeasurement(PerformanceEvents.NativeInteractionClientAcquireToken, request.correlationId);
13580
+ this.logger.trace("NativeInteractionClient - acquireToken called.");
13581
+ // start the perf measurement
13582
+ const nativeATMeasurement = this.performanceClient.startMeasurement(PerformanceEvents.NativeInteractionClientAcquireToken, request.correlationId);
13583
+ const reqTimestamp = nowSeconds();
13584
+ const serverTelemetryManager = this.initializeServerTelemetryManager(this.apiId);
13470
13585
  try {
13471
- const method = request.body.method;
13472
- if (method === NativeExtensionMethod.Response) {
13473
- if (!resolver) {
13474
- return;
13475
- }
13476
- const response = request.body.response;
13477
- this.logger.trace("NativeMessageHandler - Received response from browser extension");
13478
- this.logger.tracePii(`NativeMessageHandler - Received response from browser extension: ${JSON.stringify(response)}`);
13479
- if (response.status !== "Success") {
13480
- resolver.reject(createNativeAuthError(response.code, response.description, response.ext));
13481
- }
13482
- else if (response.result) {
13483
- if (response.result["code"] &&
13484
- response.result["description"]) {
13485
- resolver.reject(createNativeAuthError(response.result["code"], response.result["description"], response.result["ext"]));
13486
- }
13487
- else {
13488
- resolver.resolve(response.result);
13489
- }
13490
- }
13491
- else {
13492
- throw createAuthError(unexpectedError, "Event does not contain result.");
13493
- }
13494
- this.resolvers.delete(request.responseId);
13586
+ // initialize native request
13587
+ const nativeRequest = await this.initializeNativeRequest(request);
13588
+ // check if the tokens can be retrieved from internal cache
13589
+ try {
13590
+ const result = await this.acquireTokensFromCache(this.accountId, nativeRequest);
13591
+ nativeATMeasurement.end({
13592
+ success: true,
13593
+ isNativeBroker: false,
13594
+ fromCache: true,
13595
+ });
13596
+ return result;
13495
13597
  }
13496
- else if (method === NativeExtensionMethod.HandshakeResponse) {
13497
- if (!handshakeResolver) {
13498
- this.logger.trace(`NativeMessageHandler.onChannelMessage - resolver can't be found for request ${request.responseId}`);
13499
- return;
13598
+ catch (e) {
13599
+ if (cacheLookupPolicy === CacheLookupPolicy.AccessToken) {
13600
+ this.logger.info("MSAL internal Cache does not contain tokens, return error as per cache policy");
13601
+ throw e;
13500
13602
  }
13501
- clearTimeout(this.timeoutId); // Clear setTimeout
13502
- window.removeEventListener("message", this.windowListener, false); // Remove 'No extension' listener
13503
- this.extensionId = request.extensionId;
13504
- this.extensionVersion = request.body.version;
13505
- this.logger.verbose(`NativeMessageHandler - Received HandshakeResponse from extension: ${this.extensionId}`);
13506
- this.handshakeEvent.end({
13507
- extensionInstalled: true,
13603
+ // continue with a native call for any and all errors
13604
+ this.logger.info("MSAL internal Cache does not contain tokens, proceed to make a native call");
13605
+ }
13606
+ const validatedResponse = await this.platformAuthProvider.sendMessage(nativeRequest);
13607
+ return await this.handleNativeResponse(validatedResponse, nativeRequest, reqTimestamp)
13608
+ .then((result) => {
13609
+ nativeATMeasurement.end({
13508
13610
  success: true,
13611
+ isNativeBroker: true,
13612
+ requestId: result.requestId,
13509
13613
  });
13510
- handshakeResolver.resolve();
13511
- this.handshakeResolvers.delete(request.responseId);
13512
- }
13513
- // Do nothing if method is not Response or HandshakeResponse
13614
+ serverTelemetryManager.clearNativeBrokerErrorCode();
13615
+ return result;
13616
+ })
13617
+ .catch((error) => {
13618
+ nativeATMeasurement.end({
13619
+ success: false,
13620
+ errorCode: error.errorCode,
13621
+ subErrorCode: error.subError,
13622
+ isNativeBroker: true,
13623
+ });
13624
+ throw error;
13625
+ });
13514
13626
  }
13515
- catch (err) {
13516
- this.logger.error("Error parsing response from WAM Extension");
13517
- this.logger.errorPii(`Error parsing response from WAM Extension: ${err}`);
13518
- this.logger.errorPii(`Unable to parse ${event}`);
13519
- if (resolver) {
13520
- resolver.reject(err);
13521
- }
13522
- else if (handshakeResolver) {
13523
- handshakeResolver.reject(err);
13627
+ catch (e) {
13628
+ if (e instanceof NativeAuthError) {
13629
+ serverTelemetryManager.setNativeBrokerErrorCode(e.errorCode);
13524
13630
  }
13631
+ throw e;
13525
13632
  }
13526
13633
  }
13527
13634
  /**
13528
- * Returns the Id for the browser extension this handler is communicating with
13529
- * @returns
13635
+ * Creates silent flow request
13636
+ * @param request
13637
+ * @param cachedAccount
13638
+ * @returns CommonSilentFlowRequest
13530
13639
  */
13531
- getExtensionId() {
13532
- return this.extensionId;
13640
+ createSilentCacheRequest(request, cachedAccount) {
13641
+ return {
13642
+ authority: request.authority,
13643
+ correlationId: this.correlationId,
13644
+ scopes: ScopeSet.fromString(request.scope).asArray(),
13645
+ account: cachedAccount,
13646
+ forceRefresh: false,
13647
+ };
13533
13648
  }
13534
13649
  /**
13535
- * Returns the version for the browser extension this handler is communicating with
13536
- * @returns
13650
+ * Fetches the tokens from the cache if un-expired
13651
+ * @param nativeAccountId
13652
+ * @param request
13653
+ * @returns authenticationResult
13537
13654
  */
13538
- getExtensionVersion() {
13539
- return this.extensionVersion;
13655
+ async acquireTokensFromCache(nativeAccountId, request) {
13656
+ if (!nativeAccountId) {
13657
+ this.logger.warning("NativeInteractionClient:acquireTokensFromCache - No nativeAccountId provided");
13658
+ throw createClientAuthError(noAccountFound);
13659
+ }
13660
+ // fetch the account from browser cache
13661
+ const account = this.browserStorage.getBaseAccountInfo({
13662
+ nativeAccountId,
13663
+ });
13664
+ if (!account) {
13665
+ throw createClientAuthError(noAccountFound);
13666
+ }
13667
+ // leverage silent flow for cached tokens retrieval
13668
+ try {
13669
+ const silentRequest = this.createSilentCacheRequest(request, account);
13670
+ const result = await this.silentCacheClient.acquireToken(silentRequest);
13671
+ const fullAccount = {
13672
+ ...account,
13673
+ idTokenClaims: result?.idTokenClaims,
13674
+ idToken: result?.idToken,
13675
+ };
13676
+ return {
13677
+ ...result,
13678
+ account: fullAccount,
13679
+ };
13680
+ }
13681
+ catch (e) {
13682
+ throw e;
13683
+ }
13540
13684
  }
13541
13685
  /**
13542
- * Returns boolean indicating whether or not the request should attempt to use native broker
13543
- * @param logger
13544
- * @param config
13545
- * @param nativeExtensionProvider
13546
- * @param authenticationScheme
13686
+ * Acquires a token from native platform then redirects to the redirectUri instead of returning the response
13687
+ * @param {RedirectRequest} request
13688
+ * @param {InProgressPerformanceEvent} rootMeasurement
13547
13689
  */
13548
- static isPlatformBrokerAvailable(config, logger, nativeExtensionProvider, authenticationScheme) {
13549
- logger.trace("isPlatformBrokerAvailable called");
13550
- if (!config.system.allowPlatformBroker) {
13551
- logger.trace("isPlatformBrokerAvailable: allowPlatformBroker is not enabled, returning false");
13552
- // Developer disabled WAM
13553
- return false;
13554
- }
13555
- if (!nativeExtensionProvider) {
13556
- logger.trace("isPlatformBrokerAvailable: Platform extension provider is not initialized, returning false");
13557
- // Extension is not available
13558
- return false;
13690
+ async acquireTokenRedirect(request, rootMeasurement) {
13691
+ this.logger.trace("NativeInteractionClient - acquireTokenRedirect called.");
13692
+ const { ...remainingParameters } = request;
13693
+ delete remainingParameters.onRedirectNavigate;
13694
+ const nativeRequest = await this.initializeNativeRequest(remainingParameters);
13695
+ try {
13696
+ await this.platformAuthProvider.sendMessage(nativeRequest);
13559
13697
  }
13560
- if (authenticationScheme) {
13561
- switch (authenticationScheme) {
13562
- case AuthenticationScheme.BEARER:
13563
- case AuthenticationScheme.POP:
13564
- logger.trace("isPlatformBrokerAvailable: authenticationScheme is supported, returning true");
13565
- return true;
13566
- default:
13567
- logger.trace("isPlatformBrokerAvailable: authenticationScheme is not supported, returning false");
13568
- return false;
13698
+ catch (e) {
13699
+ // Only throw fatal errors here to allow application to fallback to regular redirect. Otherwise proceed and the error will be thrown in handleRedirectPromise
13700
+ if (e instanceof NativeAuthError) {
13701
+ const serverTelemetryManager = this.initializeServerTelemetryManager(this.apiId);
13702
+ serverTelemetryManager.setNativeBrokerErrorCode(e.errorCode);
13703
+ if (isFatalNativeAuthError(e)) {
13704
+ throw e;
13705
+ }
13569
13706
  }
13570
13707
  }
13571
- return true;
13572
- }
13573
- }
13574
-
13575
- /*
13576
- * Copyright (c) Microsoft Corporation. All rights reserved.
13577
- * Licensed under the MIT License.
13578
- */
13579
- /**
13580
- * Extracts the BrowserStateObject from the state string.
13581
- * @param browserCrypto
13582
- * @param state
13583
- */
13584
- function extractBrowserRequestState(browserCrypto, state) {
13585
- if (!state) {
13586
- return null;
13587
- }
13588
- try {
13589
- const requestStateObj = ProtocolUtils.parseRequestState(browserCrypto, state);
13590
- return requestStateObj.libraryState.meta;
13591
- }
13592
- catch (e) {
13593
- throw createClientAuthError(invalidState);
13594
- }
13595
- }
13596
-
13597
- /*
13598
- * Copyright (c) Microsoft Corporation. All rights reserved.
13599
- * Licensed under the MIT License.
13600
- */
13601
- function deserializeResponse(responseString, responseLocation, logger) {
13602
- // Deserialize hash fragment response parameters.
13603
- const serverParams = getDeserializedResponse(responseString);
13604
- if (!serverParams) {
13605
- if (!stripLeadingHashOrQuery(responseString)) {
13606
- // Hash or Query string is empty
13607
- 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.`);
13608
- throw createBrowserAuthError(hashEmptyError);
13609
- }
13610
- else {
13611
- 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.`);
13612
- logger.errorPii(`The ${responseLocation} detected is: ${responseString}`);
13613
- throw createBrowserAuthError(hashDoesNotContainKnownProperties);
13614
- }
13615
- }
13616
- return serverParams;
13617
- }
13618
- /**
13619
- * Returns the interaction type that the response object belongs to
13620
- */
13621
- function validateInteractionType(response, browserCrypto, interactionType) {
13622
- if (!response.state) {
13623
- throw createBrowserAuthError(noStateInHash);
13624
- }
13625
- const platformStateObj = extractBrowserRequestState(browserCrypto, response.state);
13626
- if (!platformStateObj) {
13627
- throw createBrowserAuthError(unableToParseState);
13628
- }
13629
- if (platformStateObj.interactionType !== interactionType) {
13630
- throw createBrowserAuthError(stateInteractionTypeMismatch);
13631
- }
13632
- }
13633
-
13634
- /*
13635
- * Copyright (c) Microsoft Corporation. All rights reserved.
13636
- * Licensed under the MIT License.
13637
- */
13638
- /**
13639
- * Abstract class which defines operations for a browser interaction handling class.
13640
- */
13641
- class InteractionHandler {
13642
- constructor(authCodeModule, storageImpl, authCodeRequest, logger, performanceClient) {
13643
- this.authModule = authCodeModule;
13644
- this.browserStorage = storageImpl;
13645
- this.authCodeRequest = authCodeRequest;
13646
- this.logger = logger;
13647
- this.performanceClient = performanceClient;
13708
+ this.browserStorage.setTemporaryCache(TemporaryCacheKeys.NATIVE_REQUEST, JSON.stringify(nativeRequest), true);
13709
+ const navigationOptions = {
13710
+ apiId: ApiId.acquireTokenRedirect,
13711
+ timeout: this.config.system.redirectNavigationTimeout,
13712
+ noHistory: false,
13713
+ };
13714
+ const redirectUri = this.config.auth.navigateToLoginRequestUrl
13715
+ ? window.location.href
13716
+ : this.getRedirectUri(request.redirectUri);
13717
+ rootMeasurement.end({ success: true });
13718
+ await this.navigationClient.navigateExternal(redirectUri, navigationOptions); // Need to treat this as external to ensure handleRedirectPromise is run again
13648
13719
  }
13649
13720
  /**
13650
- * Function to handle response parameters from hash.
13651
- * @param locationHash
13721
+ * If the previous page called native platform for a token using redirect APIs, send the same request again and return the response
13722
+ * @param performanceClient {IPerformanceClient?}
13723
+ * @param correlationId {string?} correlation identifier
13652
13724
  */
13653
- async handleCodeResponse(response, request) {
13654
- this.performanceClient.addQueueMeasurement(PerformanceEvents.HandleCodeResponse, request.correlationId);
13655
- let authCodeResponse;
13656
- try {
13657
- authCodeResponse = getAuthorizationCodePayload(response, request.state);
13725
+ async handleRedirectPromise(performanceClient, correlationId) {
13726
+ this.logger.trace("NativeInteractionClient - handleRedirectPromise called.");
13727
+ if (!this.browserStorage.isInteractionInProgress(true)) {
13728
+ this.logger.info("handleRedirectPromise called but there is no interaction in progress, returning null.");
13729
+ return null;
13658
13730
  }
13659
- catch (e) {
13660
- if (e instanceof ServerError &&
13661
- e.subError === userCancelled) {
13662
- // Translate server error caused by user closing native prompt to corresponding first class MSAL error
13663
- throw createBrowserAuthError(userCancelled);
13664
- }
13665
- else {
13666
- throw e;
13731
+ // remove prompt from the request to prevent WAM from prompting twice
13732
+ const cachedRequest = this.browserStorage.getCachedNativeRequest();
13733
+ if (!cachedRequest) {
13734
+ this.logger.verbose("NativeInteractionClient - handleRedirectPromise called but there is no cached request, returning null.");
13735
+ if (performanceClient && correlationId) {
13736
+ performanceClient?.addFields({ errorCode: "no_cached_request" }, correlationId);
13667
13737
  }
13738
+ return null;
13668
13739
  }
13669
- return invokeAsync(this.handleCodeResponseFromServer.bind(this), PerformanceEvents.HandleCodeResponseFromServer, this.logger, this.performanceClient, request.correlationId)(authCodeResponse, request);
13670
- }
13671
- /**
13672
- * Process auth code response from AAD
13673
- * @param authCodeResponse
13674
- * @param state
13675
- * @param authority
13676
- * @param networkModule
13677
- * @returns
13678
- */
13679
- async handleCodeResponseFromServer(authCodeResponse, request, validateNonce = true) {
13680
- this.performanceClient.addQueueMeasurement(PerformanceEvents.HandleCodeResponseFromServer, request.correlationId);
13681
- this.logger.trace("InteractionHandler.handleCodeResponseFromServer called");
13682
- // Assign code to request
13683
- this.authCodeRequest.code = authCodeResponse.code;
13684
- // Check for new cloud instance
13685
- if (authCodeResponse.cloud_instance_host_name) {
13686
- await invokeAsync(this.authModule.updateAuthority.bind(this.authModule), PerformanceEvents.UpdateTokenEndpointAuthority, this.logger, this.performanceClient, request.correlationId)(authCodeResponse.cloud_instance_host_name, request.correlationId);
13687
- }
13688
- // Nonce validation not needed when redirect not involved (e.g. hybrid spa, renewing token via rt)
13689
- if (validateNonce) {
13690
- // TODO: Assigning "response nonce" to "request nonce" is confusing. Refactor the function doing validation to accept request nonce directly
13691
- authCodeResponse.nonce = request.nonce || undefined;
13740
+ const { prompt, ...request } = cachedRequest;
13741
+ if (prompt) {
13742
+ 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.");
13692
13743
  }
13693
- authCodeResponse.state = request.state;
13694
- // Add CCS parameters if available
13695
- if (authCodeResponse.client_info) {
13696
- this.authCodeRequest.clientInfo = authCodeResponse.client_info;
13744
+ this.browserStorage.removeItem(this.browserStorage.generateCacheKey(TemporaryCacheKeys.NATIVE_REQUEST));
13745
+ const reqTimestamp = nowSeconds();
13746
+ try {
13747
+ this.logger.verbose("NativeInteractionClient - handleRedirectPromise sending message to native broker.");
13748
+ const response = await this.platformAuthProvider.sendMessage(request);
13749
+ const authResult = await this.handleNativeResponse(response, request, reqTimestamp);
13750
+ const serverTelemetryManager = this.initializeServerTelemetryManager(this.apiId);
13751
+ serverTelemetryManager.clearNativeBrokerErrorCode();
13752
+ return authResult;
13697
13753
  }
13698
- else {
13699
- const ccsCred = this.createCcsCredentials(request);
13700
- if (ccsCred) {
13701
- this.authCodeRequest.ccsCredential = ccsCred;
13702
- }
13754
+ catch (e) {
13755
+ throw e;
13703
13756
  }
13704
- // Acquire token with retrieved code.
13705
- const tokenResponse = (await invokeAsync(this.authModule.acquireToken.bind(this.authModule), PerformanceEvents.AuthClientAcquireToken, this.logger, this.performanceClient, request.correlationId)(this.authCodeRequest, authCodeResponse));
13706
- return tokenResponse;
13707
13757
  }
13708
13758
  /**
13709
- * Build ccs creds if available
13759
+ * Logout from native platform via browser extension
13760
+ * @param request
13710
13761
  */
13711
- createCcsCredentials(request) {
13712
- if (request.account) {
13713
- return {
13714
- credential: request.account.homeAccountId,
13715
- type: CcsCredentialType.HOME_ACCOUNT_ID,
13716
- };
13717
- }
13718
- else if (request.loginHint) {
13719
- return {
13720
- credential: request.loginHint,
13721
- type: CcsCredentialType.UPN,
13722
- };
13723
- }
13724
- return null;
13762
+ logout() {
13763
+ this.logger.trace("NativeInteractionClient - logout called.");
13764
+ return Promise.reject("Logout not implemented yet");
13725
13765
  }
13726
- }
13727
-
13728
- /*
13729
- * Copyright (c) Microsoft Corporation. All rights reserved.
13730
- * Licensed under the MIT License.
13731
- */
13732
- class SilentCacheClient extends StandardInteractionClient {
13733
13766
  /**
13734
- * Returns unexpired tokens from the cache, if available
13735
- * @param silentRequest
13767
+ * Transform response from native platform into AuthenticationResult object which will be returned to the end user
13768
+ * @param response
13769
+ * @param request
13770
+ * @param reqTimestamp
13736
13771
  */
13737
- async acquireToken(silentRequest) {
13738
- this.performanceClient.addQueueMeasurement(PerformanceEvents.SilentCacheClientAcquireToken, silentRequest.correlationId);
13739
- // Telemetry manager only used to increment cacheHits here
13740
- const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenSilent_silentFlow);
13741
- const clientConfig = await invokeAsync(this.getClientConfiguration.bind(this), PerformanceEvents.StandardInteractionClientGetClientConfiguration, this.logger, this.performanceClient, this.correlationId)({
13742
- serverTelemetryManager,
13743
- requestAuthority: silentRequest.authority,
13744
- requestAzureCloudOptions: silentRequest.azureCloudOptions,
13745
- account: silentRequest.account,
13746
- });
13747
- const silentAuthClient = new SilentFlowClient(clientConfig, this.performanceClient);
13748
- this.logger.verbose("Silent auth client created");
13749
- try {
13750
- const response = await invokeAsync(silentAuthClient.acquireCachedToken.bind(silentAuthClient), PerformanceEvents.SilentFlowClientAcquireCachedToken, this.logger, this.performanceClient, silentRequest.correlationId)(silentRequest);
13751
- const authResponse = response[0];
13752
- this.performanceClient.addFields({
13753
- fromCache: true,
13754
- }, silentRequest.correlationId);
13755
- return authResponse;
13772
+ async handleNativeResponse(response, request, reqTimestamp) {
13773
+ this.logger.trace("NativeInteractionClient - handleNativeResponse called.");
13774
+ // generate identifiers
13775
+ const idTokenClaims = extractTokenClaims(response.id_token, base64Decode);
13776
+ const homeAccountIdentifier = this.createHomeAccountIdentifier(response, idTokenClaims);
13777
+ const cachedhomeAccountId = this.browserStorage.getAccountInfoFilteredBy({
13778
+ nativeAccountId: request.accountId,
13779
+ })?.homeAccountId;
13780
+ // add exception for double brokering, please note this is temporary and will be fortified in future
13781
+ if (request.extraParameters?.child_client_id &&
13782
+ response.account.id !== request.accountId) {
13783
+ this.logger.info("handleNativeServerResponse: Double broker flow detected, ignoring accountId mismatch");
13756
13784
  }
13757
- catch (error) {
13758
- if (error instanceof BrowserAuthError &&
13759
- error.errorCode === cryptoKeyNotFound) {
13760
- this.logger.verbose("Signing keypair for bound access token not found. Refreshing bound access token and generating a new crypto keypair.");
13761
- }
13762
- throw error;
13785
+ else if (homeAccountIdentifier !== cachedhomeAccountId &&
13786
+ response.account.id !== request.accountId) {
13787
+ // 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
13788
+ throw createNativeAuthError(userSwitch);
13763
13789
  }
13790
+ // Get the preferred_cache domain for the given authority
13791
+ const authority = await this.getDiscoveredAuthority({
13792
+ requestAuthority: request.authority,
13793
+ });
13794
+ const baseAccount = buildAccountToCache(this.browserStorage, authority, homeAccountIdentifier, base64Decode, idTokenClaims, response.client_info, undefined, // environment
13795
+ idTokenClaims.tid, undefined, // auth code payload
13796
+ response.account.id, this.logger);
13797
+ // Ensure expires_in is in number format
13798
+ response.expires_in = Number(response.expires_in);
13799
+ // generate authenticationResult
13800
+ const result = await this.generateAuthenticationResult(response, request, idTokenClaims, baseAccount, authority.canonicalAuthority, reqTimestamp);
13801
+ // cache accounts and tokens in the appropriate storage
13802
+ await this.cacheAccount(baseAccount);
13803
+ await this.cacheNativeTokens(response, request, homeAccountIdentifier, idTokenClaims, response.access_token, result.tenantId, reqTimestamp);
13804
+ return result;
13764
13805
  }
13765
13806
  /**
13766
- * API to silenty clear the browser cache.
13767
- * @param logoutRequest
13807
+ * creates an homeAccountIdentifier for the account
13808
+ * @param response
13809
+ * @param idTokenObj
13810
+ * @returns
13768
13811
  */
13769
- logout(logoutRequest) {
13770
- this.logger.verbose("logoutRedirect called");
13771
- const validLogoutRequest = this.initializeLogoutRequest(logoutRequest);
13772
- return this.clearCacheOnLogout(validLogoutRequest?.account);
13773
- }
13774
- }
13775
-
13776
- /*
13777
- * Copyright (c) Microsoft Corporation. All rights reserved.
13778
- * Licensed under the MIT License.
13779
- */
13780
- class NativeInteractionClient extends BaseInteractionClient {
13781
- constructor(config, browserStorage, browserCrypto, logger, eventHandler, navigationClient, apiId, performanceClient, provider, accountId, nativeStorageImpl, correlationId) {
13782
- super(config, browserStorage, browserCrypto, logger, eventHandler, navigationClient, performanceClient, provider, correlationId);
13783
- this.apiId = apiId;
13784
- this.accountId = accountId;
13785
- this.nativeMessageHandler = provider;
13786
- this.nativeStorageManager = nativeStorageImpl;
13787
- this.silentCacheClient = new SilentCacheClient(config, this.nativeStorageManager, browserCrypto, logger, eventHandler, navigationClient, performanceClient, provider, correlationId);
13788
- const extensionName = this.nativeMessageHandler.getExtensionId() ===
13789
- NativeConstants.PREFERRED_EXTENSION_ID
13790
- ? "chrome"
13791
- : this.nativeMessageHandler.getExtensionId()?.length
13792
- ? "unknown"
13793
- : undefined;
13794
- this.skus = ServerTelemetryManager.makeExtraSkuString({
13795
- libraryName: BrowserConstants.MSAL_SKU,
13796
- libraryVersion: version,
13797
- extensionName: extensionName,
13798
- extensionVersion: this.nativeMessageHandler.getExtensionVersion(),
13799
- });
13812
+ createHomeAccountIdentifier(response, idTokenClaims) {
13813
+ // Save account in browser storage
13814
+ const homeAccountIdentifier = AccountEntity.generateHomeAccountId(response.client_info || Constants.EMPTY_STRING, AuthorityType.Default, this.logger, this.browserCrypto, idTokenClaims);
13815
+ return homeAccountIdentifier;
13800
13816
  }
13801
13817
  /**
13802
- * Adds SKUs to request extra query parameters
13803
- * @param request {NativeTokenRequest}
13804
- * @private
13818
+ * Helper to generate scopes
13819
+ * @param response
13820
+ * @param request
13821
+ * @returns
13805
13822
  */
13806
- addRequestSKUs(request) {
13807
- request.extraParameters = {
13808
- ...request.extraParameters,
13809
- [X_CLIENT_EXTRA_SKU]: this.skus,
13810
- };
13823
+ generateScopes(requestScopes, responseScopes) {
13824
+ return responseScopes
13825
+ ? ScopeSet.fromString(responseScopes)
13826
+ : ScopeSet.fromString(requestScopes);
13811
13827
  }
13812
13828
  /**
13813
- * Acquire token from native platform via browser extension
13829
+ * If PoP token is requesred, records the PoP token if returned from the WAM, else generates one in the browser
13814
13830
  * @param request
13831
+ * @param response
13815
13832
  */
13816
- async acquireToken(request, cacheLookupPolicy) {
13817
- this.performanceClient.addQueueMeasurement(PerformanceEvents.NativeInteractionClientAcquireToken, request.correlationId);
13818
- this.logger.trace("NativeInteractionClient - acquireToken called.");
13819
- // start the perf measurement
13820
- const nativeATMeasurement = this.performanceClient.startMeasurement(PerformanceEvents.NativeInteractionClientAcquireToken, request.correlationId);
13821
- const reqTimestamp = nowSeconds();
13822
- const serverTelemetryManager = this.initializeServerTelemetryManager(this.apiId);
13823
- try {
13824
- // initialize native request
13825
- const nativeRequest = await this.initializeNativeRequest(request);
13826
- // check if the tokens can be retrieved from internal cache
13827
- try {
13828
- const result = await this.acquireTokensFromCache(this.accountId, nativeRequest);
13829
- nativeATMeasurement.end({
13830
- success: true,
13831
- isNativeBroker: false,
13832
- fromCache: true,
13833
- });
13834
- return result;
13835
- }
13836
- catch (e) {
13837
- if (cacheLookupPolicy === CacheLookupPolicy.AccessToken) {
13838
- this.logger.info("MSAL internal Cache does not contain tokens, return error as per cache policy");
13839
- throw e;
13840
- }
13841
- // continue with a native call for any and all errors
13842
- this.logger.info("MSAL internal Cache does not contain tokens, proceed to make a native call");
13833
+ async generatePopAccessToken(response, request) {
13834
+ if (request.tokenType === AuthenticationScheme.POP &&
13835
+ request.signPopToken) {
13836
+ /**
13837
+ * This code prioritizes SHR returned from the native layer. In case of error/SHR not calculated from WAM and the AT
13838
+ * is still received, SHR is calculated locally
13839
+ */
13840
+ // Check if native layer returned an SHR token
13841
+ if (response.shr) {
13842
+ this.logger.trace("handleNativeServerResponse: SHR is enabled in native layer");
13843
+ return response.shr;
13843
13844
  }
13844
- const { ...nativeTokenRequest } = nativeRequest;
13845
- // fall back to native calls
13846
- const messageBody = {
13847
- method: NativeExtensionMethod.GetToken,
13848
- request: nativeTokenRequest,
13845
+ // Generate SHR in msal js if WAM does not compute it when POP is enabled
13846
+ const popTokenGenerator = new PopTokenGenerator(this.browserCrypto);
13847
+ const shrParameters = {
13848
+ resourceRequestMethod: request.resourceRequestMethod,
13849
+ resourceRequestUri: request.resourceRequestUri,
13850
+ shrClaims: request.shrClaims,
13851
+ shrNonce: request.shrNonce,
13849
13852
  };
13850
- const response = await this.nativeMessageHandler.sendMessage(messageBody);
13851
- const validatedResponse = this.validateNativeResponse(response);
13852
- return await this.handleNativeResponse(validatedResponse, nativeRequest, reqTimestamp)
13853
- .then((result) => {
13854
- nativeATMeasurement.end({
13855
- success: true,
13856
- isNativeBroker: true,
13857
- requestId: result.requestId,
13858
- });
13859
- serverTelemetryManager.clearNativeBrokerErrorCode();
13860
- return result;
13861
- })
13862
- .catch((error) => {
13863
- nativeATMeasurement.end({
13864
- success: false,
13865
- errorCode: error.errorCode,
13866
- subErrorCode: error.subError,
13867
- isNativeBroker: true,
13868
- });
13869
- throw error;
13870
- });
13871
- }
13872
- catch (e) {
13873
- if (e instanceof NativeAuthError) {
13874
- serverTelemetryManager.setNativeBrokerErrorCode(e.errorCode);
13853
+ /**
13854
+ * KeyID must be present in the native request from when the PoP key was generated in order for
13855
+ * PopTokenGenerator to query the full key for signing
13856
+ */
13857
+ if (!request.keyId) {
13858
+ throw createClientAuthError(keyIdMissing);
13875
13859
  }
13876
- throw e;
13860
+ return popTokenGenerator.signPopToken(response.access_token, request.keyId, shrParameters);
13861
+ }
13862
+ else {
13863
+ return response.access_token;
13877
13864
  }
13878
13865
  }
13879
13866
  /**
13880
- * Creates silent flow request
13867
+ * Generates authentication result
13868
+ * @param response
13881
13869
  * @param request
13882
- * @param cachedAccount
13883
- * @returns CommonSilentFlowRequest
13870
+ * @param idTokenObj
13871
+ * @param accountEntity
13872
+ * @param authority
13873
+ * @param reqTimestamp
13874
+ * @returns
13884
13875
  */
13885
- createSilentCacheRequest(request, cachedAccount) {
13886
- return {
13887
- authority: request.authority,
13876
+ async generateAuthenticationResult(response, request, idTokenClaims, accountEntity, authority, reqTimestamp) {
13877
+ // Add Native Broker fields to Telemetry
13878
+ const mats = this.addTelemetryFromNativeResponse(response.properties.MATS);
13879
+ // If scopes not returned in server response, use request scopes
13880
+ const responseScopes = this.generateScopes(request.scope, response.scope);
13881
+ const accountProperties = response.account.properties || {};
13882
+ const uid = accountProperties["UID"] ||
13883
+ idTokenClaims.oid ||
13884
+ idTokenClaims.sub ||
13885
+ Constants.EMPTY_STRING;
13886
+ const tid = accountProperties["TenantId"] ||
13887
+ idTokenClaims.tid ||
13888
+ Constants.EMPTY_STRING;
13889
+ const accountInfo = updateAccountTenantProfileData(accountEntity.getAccountInfo(), undefined, // tenantProfile optional
13890
+ idTokenClaims, response.id_token);
13891
+ /**
13892
+ * In pairwise broker flows, this check prevents the broker's native account id
13893
+ * from being returned over the embedded app's account id.
13894
+ */
13895
+ if (accountInfo.nativeAccountId !== response.account.id) {
13896
+ accountInfo.nativeAccountId = response.account.id;
13897
+ }
13898
+ // generate PoP token as needed
13899
+ const responseAccessToken = await this.generatePopAccessToken(response, request);
13900
+ const tokenType = request.tokenType === AuthenticationScheme.POP
13901
+ ? AuthenticationScheme.POP
13902
+ : AuthenticationScheme.BEARER;
13903
+ const result = {
13904
+ authority: authority,
13905
+ uniqueId: uid,
13906
+ tenantId: tid,
13907
+ scopes: responseScopes.asArray(),
13908
+ account: accountInfo,
13909
+ idToken: response.id_token,
13910
+ idTokenClaims: idTokenClaims,
13911
+ accessToken: responseAccessToken,
13912
+ fromCache: mats ? this.isResponseFromCache(mats) : false,
13913
+ // Request timestamp and NativeResponse expires_in are in seconds, converting to Date for AuthenticationResult
13914
+ expiresOn: toDateFromSeconds(reqTimestamp + response.expires_in),
13915
+ tokenType: tokenType,
13888
13916
  correlationId: this.correlationId,
13889
- scopes: ScopeSet.fromString(request.scope).asArray(),
13890
- account: cachedAccount,
13891
- forceRefresh: false,
13917
+ state: response.state,
13918
+ fromNativeBroker: true,
13892
13919
  };
13920
+ return result;
13893
13921
  }
13894
13922
  /**
13895
- * Fetches the tokens from the cache if un-expired
13896
- * @param nativeAccountId
13897
- * @param request
13898
- * @returns authenticationResult
13923
+ * cache the account entity in browser storage
13924
+ * @param accountEntity
13899
13925
  */
13900
- async acquireTokensFromCache(nativeAccountId, request) {
13901
- if (!nativeAccountId) {
13902
- this.logger.warning("NativeInteractionClient:acquireTokensFromCache - No nativeAccountId provided");
13903
- throw createClientAuthError(noAccountFound);
13904
- }
13905
- // fetch the account from browser cache
13906
- const account = this.browserStorage.getBaseAccountInfo({
13907
- nativeAccountId,
13926
+ async cacheAccount(accountEntity) {
13927
+ // Store the account info and hence `nativeAccountId` in browser cache
13928
+ await this.browserStorage.setAccount(accountEntity, this.correlationId);
13929
+ // Remove any existing cached tokens for this account in browser storage
13930
+ this.browserStorage.removeAccountContext(accountEntity).catch((e) => {
13931
+ this.logger.error(`Error occurred while removing account context from browser storage. ${e}`);
13908
13932
  });
13909
- if (!account) {
13910
- throw createClientAuthError(noAccountFound);
13911
- }
13912
- // leverage silent flow for cached tokens retrieval
13913
- try {
13914
- const silentRequest = this.createSilentCacheRequest(request, account);
13915
- const result = await this.silentCacheClient.acquireToken(silentRequest);
13916
- const fullAccount = {
13917
- ...account,
13918
- idTokenClaims: result?.idTokenClaims,
13919
- idToken: result?.idToken,
13920
- };
13921
- return {
13922
- ...result,
13923
- account: fullAccount,
13924
- };
13925
- }
13926
- catch (e) {
13927
- throw e;
13928
- }
13929
13933
  }
13930
13934
  /**
13931
- * Acquires a token from native platform then redirects to the redirectUri instead of returning the response
13932
- * @param {RedirectRequest} request
13933
- * @param {InProgressPerformanceEvent} rootMeasurement
13935
+ * Stores the access_token and id_token in inmemory storage
13936
+ * @param response
13937
+ * @param request
13938
+ * @param homeAccountIdentifier
13939
+ * @param idTokenObj
13940
+ * @param responseAccessToken
13941
+ * @param tenantId
13942
+ * @param reqTimestamp
13934
13943
  */
13935
- async acquireTokenRedirect(request, rootMeasurement) {
13936
- this.logger.trace("NativeInteractionClient - acquireTokenRedirect called.");
13937
- const { ...remainingParameters } = request;
13938
- delete remainingParameters.onRedirectNavigate;
13939
- const nativeRequest = await this.initializeNativeRequest(remainingParameters);
13940
- const messageBody = {
13941
- method: NativeExtensionMethod.GetToken,
13942
- request: nativeRequest,
13944
+ cacheNativeTokens(response, request, homeAccountIdentifier, idTokenClaims, responseAccessToken, tenantId, reqTimestamp) {
13945
+ const cachedIdToken = createIdTokenEntity(homeAccountIdentifier, request.authority, response.id_token || "", request.clientId, idTokenClaims.tid || "");
13946
+ // cache accessToken in inmemory storage
13947
+ const expiresIn = request.tokenType === AuthenticationScheme.POP
13948
+ ? Constants.SHR_NONCE_VALIDITY
13949
+ : (typeof response.expires_in === "string"
13950
+ ? parseInt(response.expires_in, 10)
13951
+ : response.expires_in) || 0;
13952
+ const tokenExpirationSeconds = reqTimestamp + expiresIn;
13953
+ const responseScopes = this.generateScopes(response.scope, request.scope);
13954
+ const cachedAccessToken = createAccessTokenEntity(homeAccountIdentifier, request.authority, responseAccessToken, request.clientId, idTokenClaims.tid || tenantId, responseScopes.printScopes(), tokenExpirationSeconds, 0, base64Decode, undefined, request.tokenType, undefined, request.keyId);
13955
+ const nativeCacheRecord = {
13956
+ idToken: cachedIdToken,
13957
+ accessToken: cachedAccessToken,
13943
13958
  };
13944
- try {
13945
- const response = await this.nativeMessageHandler.sendMessage(messageBody);
13946
- this.validateNativeResponse(response);
13959
+ return this.nativeStorageManager.saveCacheRecord(nativeCacheRecord, this.correlationId, request.storeInCache);
13960
+ }
13961
+ getExpiresInValue(tokenType, expiresIn) {
13962
+ return tokenType === AuthenticationScheme.POP
13963
+ ? Constants.SHR_NONCE_VALIDITY
13964
+ : (typeof expiresIn === "string"
13965
+ ? parseInt(expiresIn, 10)
13966
+ : expiresIn) || 0;
13967
+ }
13968
+ addTelemetryFromNativeResponse(matsResponse) {
13969
+ const mats = this.getMATSFromResponse(matsResponse);
13970
+ if (!mats) {
13971
+ return null;
13947
13972
  }
13948
- catch (e) {
13949
- // Only throw fatal errors here to allow application to fallback to regular redirect. Otherwise proceed and the error will be thrown in handleRedirectPromise
13950
- if (e instanceof NativeAuthError) {
13951
- const serverTelemetryManager = this.initializeServerTelemetryManager(this.apiId);
13952
- serverTelemetryManager.setNativeBrokerErrorCode(e.errorCode);
13953
- if (isFatalNativeAuthError(e)) {
13954
- throw e;
13955
- }
13956
- }
13957
- }
13958
- this.browserStorage.setTemporaryCache(TemporaryCacheKeys.NATIVE_REQUEST, JSON.stringify(nativeRequest), true);
13959
- const navigationOptions = {
13960
- apiId: ApiId.acquireTokenRedirect,
13961
- timeout: this.config.system.redirectNavigationTimeout,
13962
- noHistory: false,
13963
- };
13964
- const redirectUri = this.config.auth.navigateToLoginRequestUrl
13965
- ? window.location.href
13966
- : this.getRedirectUri(request.redirectUri);
13967
- rootMeasurement.end({ success: true });
13968
- await this.navigationClient.navigateExternal(redirectUri, navigationOptions); // Need to treat this as external to ensure handleRedirectPromise is run again
13969
- }
13970
- /**
13971
- * If the previous page called native platform for a token using redirect APIs, send the same request again and return the response
13972
- * @param performanceClient {IPerformanceClient?}
13973
- * @param correlationId {string?} correlation identifier
13974
- */
13975
- async handleRedirectPromise(performanceClient, correlationId) {
13976
- this.logger.trace("NativeInteractionClient - handleRedirectPromise called.");
13977
- if (!this.browserStorage.isInteractionInProgress(true)) {
13978
- this.logger.info("handleRedirectPromise called but there is no interaction in progress, returning null.");
13979
- return null;
13980
- }
13981
- // remove prompt from the request to prevent WAM from prompting twice
13982
- const cachedRequest = this.browserStorage.getCachedNativeRequest();
13983
- if (!cachedRequest) {
13984
- this.logger.verbose("NativeInteractionClient - handleRedirectPromise called but there is no cached request, returning null.");
13985
- if (performanceClient && correlationId) {
13986
- performanceClient?.addFields({ errorCode: "no_cached_request" }, correlationId);
13987
- }
13988
- return null;
13989
- }
13990
- const { prompt, ...request } = cachedRequest;
13991
- if (prompt) {
13992
- 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.");
13993
- }
13994
- this.browserStorage.removeItem(this.browserStorage.generateCacheKey(TemporaryCacheKeys.NATIVE_REQUEST));
13995
- const messageBody = {
13996
- method: NativeExtensionMethod.GetToken,
13997
- request: request,
13998
- };
13999
- const reqTimestamp = nowSeconds();
14000
- try {
14001
- this.logger.verbose("NativeInteractionClient - handleRedirectPromise sending message to native broker.");
14002
- const response = await this.nativeMessageHandler.sendMessage(messageBody);
14003
- this.validateNativeResponse(response);
14004
- const result = this.handleNativeResponse(response, request, reqTimestamp);
14005
- const res = await result;
14006
- const serverTelemetryManager = this.initializeServerTelemetryManager(this.apiId);
14007
- serverTelemetryManager.clearNativeBrokerErrorCode();
14008
- return res;
14009
- }
14010
- catch (e) {
14011
- throw e;
14012
- }
14013
- }
14014
- /**
14015
- * Logout from native platform via browser extension
14016
- * @param request
14017
- */
14018
- logout() {
14019
- this.logger.trace("NativeInteractionClient - logout called.");
14020
- return Promise.reject("Logout not implemented yet");
14021
- }
14022
- /**
14023
- * Transform response from native platform into AuthenticationResult object which will be returned to the end user
14024
- * @param response
14025
- * @param request
14026
- * @param reqTimestamp
14027
- */
14028
- async handleNativeResponse(response, request, reqTimestamp) {
14029
- this.logger.trace("NativeInteractionClient - handleNativeResponse called.");
14030
- // generate identifiers
14031
- const idTokenClaims = extractTokenClaims(response.id_token, base64Decode);
14032
- const homeAccountIdentifier = this.createHomeAccountIdentifier(response, idTokenClaims);
14033
- const cachedhomeAccountId = this.browserStorage.getAccountInfoFilteredBy({
14034
- nativeAccountId: request.accountId,
14035
- })?.homeAccountId;
14036
- // add exception for double brokering, please note this is temporary and will be fortified in future
14037
- if (request.extraParameters?.child_client_id &&
14038
- response.account.id !== request.accountId) {
14039
- this.logger.info("handleNativeServerResponse: Double broker flow detected, ignoring accountId mismatch");
14040
- }
14041
- else if (homeAccountIdentifier !== cachedhomeAccountId &&
14042
- response.account.id !== request.accountId) {
14043
- // 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
14044
- throw createNativeAuthError(userSwitch);
14045
- }
14046
- // Get the preferred_cache domain for the given authority
14047
- const authority = await this.getDiscoveredAuthority({
14048
- requestAuthority: request.authority,
14049
- });
14050
- const baseAccount = buildAccountToCache(this.browserStorage, authority, homeAccountIdentifier, base64Decode, idTokenClaims, response.client_info, undefined, // environment
14051
- idTokenClaims.tid, undefined, // auth code payload
14052
- response.account.id, this.logger);
14053
- // Ensure expires_in is in number format
14054
- response.expires_in = Number(response.expires_in);
14055
- // generate authenticationResult
14056
- const result = await this.generateAuthenticationResult(response, request, idTokenClaims, baseAccount, authority.canonicalAuthority, reqTimestamp);
14057
- // cache accounts and tokens in the appropriate storage
14058
- await this.cacheAccount(baseAccount);
14059
- await this.cacheNativeTokens(response, request, homeAccountIdentifier, idTokenClaims, response.access_token, result.tenantId, reqTimestamp);
14060
- return result;
13973
+ this.performanceClient.addFields({
13974
+ extensionId: this.platformAuthProvider.getExtensionId(),
13975
+ extensionVersion: this.platformAuthProvider.getExtensionVersion(),
13976
+ matsBrokerVersion: mats.broker_version,
13977
+ matsAccountJoinOnStart: mats.account_join_on_start,
13978
+ matsAccountJoinOnEnd: mats.account_join_on_end,
13979
+ matsDeviceJoin: mats.device_join,
13980
+ matsPromptBehavior: mats.prompt_behavior,
13981
+ matsApiErrorCode: mats.api_error_code,
13982
+ matsUiVisible: mats.ui_visible,
13983
+ matsSilentCode: mats.silent_code,
13984
+ matsSilentBiSubCode: mats.silent_bi_sub_code,
13985
+ matsSilentMessage: mats.silent_message,
13986
+ matsSilentStatus: mats.silent_status,
13987
+ matsHttpStatus: mats.http_status,
13988
+ matsHttpEventCount: mats.http_event_count,
13989
+ }, this.correlationId);
13990
+ return mats;
14061
13991
  }
14062
13992
  /**
14063
- * creates an homeAccountIdentifier for the account
13993
+ * Gets MATS telemetry from native response
14064
13994
  * @param response
14065
- * @param idTokenObj
14066
13995
  * @returns
14067
13996
  */
14068
- createHomeAccountIdentifier(response, idTokenClaims) {
14069
- // Save account in browser storage
14070
- const homeAccountIdentifier = AccountEntity.generateHomeAccountId(response.client_info || Constants.EMPTY_STRING, AuthorityType.Default, this.logger, this.browserCrypto, idTokenClaims);
14071
- return homeAccountIdentifier;
13997
+ getMATSFromResponse(matsResponse) {
13998
+ if (matsResponse) {
13999
+ try {
14000
+ return JSON.parse(matsResponse);
14001
+ }
14002
+ catch (e) {
14003
+ this.logger.error("NativeInteractionClient - Error parsing MATS telemetry, returning null instead");
14004
+ }
14005
+ }
14006
+ return null;
14072
14007
  }
14073
14008
  /**
14074
- * Helper to generate scopes
14009
+ * Returns whether or not response came from native cache
14075
14010
  * @param response
14076
- * @param request
14077
14011
  * @returns
14078
14012
  */
14079
- generateScopes(response, request) {
14080
- return response.scope
14081
- ? ScopeSet.fromString(response.scope)
14082
- : ScopeSet.fromString(request.scope);
14013
+ isResponseFromCache(mats) {
14014
+ if (typeof mats.is_cached === "undefined") {
14015
+ this.logger.verbose("NativeInteractionClient - MATS telemetry does not contain field indicating if response was served from cache. Returning false.");
14016
+ return false;
14017
+ }
14018
+ return !!mats.is_cached;
14083
14019
  }
14084
14020
  /**
14085
- * If PoP token is requesred, records the PoP token if returned from the WAM, else generates one in the browser
14021
+ * Translates developer provided request object into NativeRequest object
14086
14022
  * @param request
14087
- * @param response
14088
14023
  */
14089
- async generatePopAccessToken(response, request) {
14090
- if (request.tokenType === AuthenticationScheme.POP &&
14091
- request.signPopToken) {
14092
- /**
14093
- * This code prioritizes SHR returned from the native layer. In case of error/SHR not calculated from WAM and the AT
14094
- * is still received, SHR is calculated locally
14095
- */
14096
- // Check if native layer returned an SHR token
14097
- if (response.shr) {
14098
- this.logger.trace("handleNativeServerResponse: SHR is enabled in native layer");
14099
- return response.shr;
14100
- }
14101
- // Generate SHR in msal js if WAM does not compute it when POP is enabled
14102
- const popTokenGenerator = new PopTokenGenerator(this.browserCrypto);
14024
+ async initializeNativeRequest(request) {
14025
+ this.logger.trace("NativeInteractionClient - initializeNativeRequest called");
14026
+ const canonicalAuthority = await this.getCanonicalAuthority(request);
14027
+ // 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.
14028
+ const { scopes, ...remainingProperties } = request;
14029
+ const scopeSet = new ScopeSet(scopes || []);
14030
+ scopeSet.appendScopes(OIDC_DEFAULT_SCOPES);
14031
+ const validatedRequest = {
14032
+ ...remainingProperties,
14033
+ accountId: this.accountId,
14034
+ clientId: this.config.auth.clientId,
14035
+ authority: canonicalAuthority.urlString,
14036
+ scope: scopeSet.printScopes(),
14037
+ redirectUri: this.getRedirectUri(request.redirectUri),
14038
+ prompt: this.getPrompt(request.prompt),
14039
+ correlationId: this.correlationId,
14040
+ tokenType: request.authenticationScheme,
14041
+ windowTitleSubstring: document.title,
14042
+ extraParameters: {
14043
+ ...request.extraQueryParameters,
14044
+ ...request.tokenQueryParameters,
14045
+ },
14046
+ extendedExpiryToken: false,
14047
+ keyId: request.popKid,
14048
+ };
14049
+ // Check for PoP token requests: signPopToken should only be set to true if popKid is not set
14050
+ if (validatedRequest.signPopToken && !!request.popKid) {
14051
+ throw createBrowserAuthError(invalidPopTokenRequest);
14052
+ }
14053
+ this.handleExtraBrokerParams(validatedRequest);
14054
+ validatedRequest.extraParameters =
14055
+ validatedRequest.extraParameters || {};
14056
+ validatedRequest.extraParameters.telemetry =
14057
+ PlatformAuthConstants.MATS_TELEMETRY;
14058
+ if (request.authenticationScheme === AuthenticationScheme.POP) {
14059
+ // add POP request type
14103
14060
  const shrParameters = {
14104
- resourceRequestMethod: request.resourceRequestMethod,
14105
14061
  resourceRequestUri: request.resourceRequestUri,
14062
+ resourceRequestMethod: request.resourceRequestMethod,
14106
14063
  shrClaims: request.shrClaims,
14107
14064
  shrNonce: request.shrNonce,
14108
14065
  };
14109
- /**
14110
- * KeyID must be present in the native request from when the PoP key was generated in order for
14111
- * PopTokenGenerator to query the full key for signing
14112
- */
14113
- if (!request.keyId) {
14114
- throw createClientAuthError(keyIdMissing);
14066
+ const popTokenGenerator = new PopTokenGenerator(this.browserCrypto);
14067
+ // generate reqCnf if not provided in the request
14068
+ let reqCnfData;
14069
+ if (!validatedRequest.keyId) {
14070
+ const generatedReqCnfData = await invokeAsync(popTokenGenerator.generateCnf.bind(popTokenGenerator), PerformanceEvents.PopTokenGenerateCnf, this.logger, this.performanceClient, request.correlationId)(shrParameters, this.logger);
14071
+ reqCnfData = generatedReqCnfData.reqCnfString;
14072
+ validatedRequest.keyId = generatedReqCnfData.kid;
14073
+ validatedRequest.signPopToken = true;
14115
14074
  }
14116
- return popTokenGenerator.signPopToken(response.access_token, request.keyId, shrParameters);
14075
+ else {
14076
+ reqCnfData = this.browserCrypto.base64UrlEncode(JSON.stringify({ kid: validatedRequest.keyId }));
14077
+ validatedRequest.signPopToken = false;
14078
+ }
14079
+ // SPAs require whole string to be passed to broker
14080
+ validatedRequest.reqCnf = reqCnfData;
14117
14081
  }
14118
- else {
14119
- return response.access_token;
14082
+ this.addRequestSKUs(validatedRequest);
14083
+ return validatedRequest;
14084
+ }
14085
+ async getCanonicalAuthority(request) {
14086
+ const requestAuthority = request.authority || this.config.auth.authority;
14087
+ if (request.account) {
14088
+ // validate authority
14089
+ await this.getDiscoveredAuthority({
14090
+ requestAuthority,
14091
+ requestAzureCloudOptions: request.azureCloudOptions,
14092
+ account: request.account,
14093
+ });
14094
+ }
14095
+ const canonicalAuthority = new UrlString(requestAuthority);
14096
+ canonicalAuthority.validateAsUri();
14097
+ return canonicalAuthority;
14098
+ }
14099
+ getPrompt(prompt) {
14100
+ // If request is silent, prompt is always none
14101
+ switch (this.apiId) {
14102
+ case ApiId.ssoSilent:
14103
+ case ApiId.acquireTokenSilent_silentFlow:
14104
+ this.logger.trace("initializeNativeRequest: silent request sets prompt to none");
14105
+ return PromptValue.NONE;
14106
+ }
14107
+ // Prompt not provided, request may proceed and native broker decides if it needs to prompt
14108
+ if (!prompt) {
14109
+ this.logger.trace("initializeNativeRequest: prompt was not provided");
14110
+ return undefined;
14111
+ }
14112
+ // If request is interactive, check if prompt provided is allowed to go directly to native broker
14113
+ switch (prompt) {
14114
+ case PromptValue.NONE:
14115
+ case PromptValue.CONSENT:
14116
+ case PromptValue.LOGIN:
14117
+ this.logger.trace("initializeNativeRequest: prompt is compatible with native flow");
14118
+ return prompt;
14119
+ default:
14120
+ this.logger.trace(`initializeNativeRequest: prompt = ${prompt} is not compatible with native flow`);
14121
+ throw createBrowserAuthError(nativePromptNotSupported);
14120
14122
  }
14121
14123
  }
14122
14124
  /**
14123
- * Generates authentication result
14124
- * @param response
14125
- * @param request
14126
- * @param idTokenObj
14127
- * @param accountEntity
14128
- * @param authority
14129
- * @param reqTimestamp
14130
- * @returns
14125
+ * Handles extra broker request parameters
14126
+ * @param request {PlatformAuthRequest}
14127
+ * @private
14131
14128
  */
14132
- async generateAuthenticationResult(response, request, idTokenClaims, accountEntity, authority, reqTimestamp) {
14133
- // Add Native Broker fields to Telemetry
14134
- const mats = this.addTelemetryFromNativeResponse(response);
14135
- // If scopes not returned in server response, use request scopes
14136
- const responseScopes = response.scope
14137
- ? ScopeSet.fromString(response.scope)
14138
- : ScopeSet.fromString(request.scope);
14139
- const accountProperties = response.account.properties || {};
14140
- const uid = accountProperties["UID"] ||
14141
- idTokenClaims.oid ||
14142
- idTokenClaims.sub ||
14143
- Constants.EMPTY_STRING;
14144
- const tid = accountProperties["TenantId"] ||
14145
- idTokenClaims.tid ||
14146
- Constants.EMPTY_STRING;
14147
- const accountInfo = updateAccountTenantProfileData(accountEntity.getAccountInfo(), undefined, // tenantProfile optional
14148
- idTokenClaims, response.id_token);
14149
- /**
14150
- * In pairwise broker flows, this check prevents the broker's native account id
14151
- * from being returned over the embedded app's account id.
14152
- */
14153
- if (accountInfo.nativeAccountId !== response.account.id) {
14154
- accountInfo.nativeAccountId = response.account.id;
14129
+ handleExtraBrokerParams(request) {
14130
+ const hasExtraBrokerParams = request.extraParameters &&
14131
+ request.extraParameters.hasOwnProperty(BROKER_CLIENT_ID) &&
14132
+ request.extraParameters.hasOwnProperty(BROKER_REDIRECT_URI) &&
14133
+ request.extraParameters.hasOwnProperty(CLIENT_ID);
14134
+ if (!request.embeddedClientId && !hasExtraBrokerParams) {
14135
+ return;
14155
14136
  }
14156
- // generate PoP token as needed
14157
- const responseAccessToken = await this.generatePopAccessToken(response, request);
14158
- const tokenType = request.tokenType === AuthenticationScheme.POP
14159
- ? AuthenticationScheme.POP
14160
- : AuthenticationScheme.BEARER;
14161
- const result = {
14162
- authority: authority,
14163
- uniqueId: uid,
14164
- tenantId: tid,
14165
- scopes: responseScopes.asArray(),
14166
- account: accountInfo,
14167
- idToken: response.id_token,
14168
- idTokenClaims: idTokenClaims,
14169
- accessToken: responseAccessToken,
14170
- fromCache: mats ? this.isResponseFromCache(mats) : false,
14171
- // Request timestamp and NativeResponse expires_in are in seconds, converting to Date for AuthenticationResult
14172
- expiresOn: toDateFromSeconds(reqTimestamp + response.expires_in),
14173
- tokenType: tokenType,
14174
- correlationId: this.correlationId,
14175
- state: response.state,
14176
- fromNativeBroker: true,
14137
+ let child_client_id = "";
14138
+ const child_redirect_uri = request.redirectUri;
14139
+ if (request.embeddedClientId) {
14140
+ request.redirectUri = this.config.auth.redirectUri;
14141
+ child_client_id = request.embeddedClientId;
14142
+ }
14143
+ else if (request.extraParameters) {
14144
+ request.redirectUri =
14145
+ request.extraParameters[BROKER_REDIRECT_URI];
14146
+ child_client_id =
14147
+ request.extraParameters[CLIENT_ID];
14148
+ }
14149
+ request.extraParameters = {
14150
+ child_client_id,
14151
+ child_redirect_uri,
14177
14152
  };
14178
- return result;
14153
+ this.performanceClient?.addFields({
14154
+ embeddedClientId: child_client_id,
14155
+ embeddedRedirectUri: child_redirect_uri,
14156
+ }, request.correlationId);
14157
+ }
14158
+ }
14159
+
14160
+ /*
14161
+ * Copyright (c) Microsoft Corporation. All rights reserved.
14162
+ * Licensed under the MIT License.
14163
+ */
14164
+ /**
14165
+ * Returns map of parameters that are applicable to all calls to /authorize whether using PKCE or EAR
14166
+ * @param config
14167
+ * @param authority
14168
+ * @param request
14169
+ * @param logger
14170
+ * @param performanceClient
14171
+ * @returns
14172
+ */
14173
+ async function getStandardParameters(config, authority, request, logger, performanceClient) {
14174
+ const parameters = getStandardAuthorizeRequestParameters({ ...config.auth, authority: authority }, request, logger, performanceClient);
14175
+ addLibraryInfo(parameters, {
14176
+ sku: BrowserConstants.MSAL_SKU,
14177
+ version: version,
14178
+ os: "",
14179
+ cpu: "",
14180
+ });
14181
+ if (config.auth.protocolMode !== ProtocolMode.OIDC) {
14182
+ addApplicationTelemetry(parameters, config.telemetry.application);
14183
+ }
14184
+ if (request.platformBroker) {
14185
+ // signal ests that this is a WAM call
14186
+ addNativeBroker(parameters);
14187
+ // pass the req_cnf for POP
14188
+ if (request.authenticationScheme === AuthenticationScheme.POP) {
14189
+ const cryptoOps = new CryptoOps(logger, performanceClient);
14190
+ const popTokenGenerator = new PopTokenGenerator(cryptoOps);
14191
+ // req_cnf is always sent as a string for SPAs
14192
+ let reqCnfData;
14193
+ if (!request.popKid) {
14194
+ const generatedReqCnfData = await invokeAsync(popTokenGenerator.generateCnf.bind(popTokenGenerator), PerformanceEvents.PopTokenGenerateCnf, logger, performanceClient, request.correlationId)(request, logger);
14195
+ reqCnfData = generatedReqCnfData.reqCnfString;
14196
+ }
14197
+ else {
14198
+ reqCnfData = cryptoOps.encodeKid(request.popKid);
14199
+ }
14200
+ addPopToken(parameters, reqCnfData);
14201
+ }
14202
+ }
14203
+ instrumentBrokerParams(parameters, request.correlationId, performanceClient);
14204
+ return parameters;
14205
+ }
14206
+ /**
14207
+ * Gets the full /authorize URL with request parameters when using Auth Code + PKCE
14208
+ * @param config
14209
+ * @param authority
14210
+ * @param request
14211
+ * @param logger
14212
+ * @param performanceClient
14213
+ * @returns
14214
+ */
14215
+ async function getAuthCodeRequestUrl(config, authority, request, logger, performanceClient) {
14216
+ if (!request.codeChallenge) {
14217
+ throw createClientConfigurationError(pkceParamsMissing);
14218
+ }
14219
+ const parameters = await invokeAsync(getStandardParameters, PerformanceEvents.GetStandardParams, logger, performanceClient, request.correlationId)(config, authority, request, logger, performanceClient);
14220
+ addResponseType(parameters, OAuthResponseType.CODE);
14221
+ addCodeChallengeParams(parameters, request.codeChallenge, Constants.S256_CODE_CHALLENGE_METHOD);
14222
+ addExtraQueryParameters(parameters, request.extraQueryParameters || {});
14223
+ return getAuthorizeUrl(authority, parameters, config.auth.encodeExtraQueryParams, request.extraQueryParameters);
14224
+ }
14225
+ /**
14226
+ * Gets the form that will be posted to /authorize with request parameters when using EAR
14227
+ */
14228
+ async function getEARForm(frame, config, authority, request, logger, performanceClient) {
14229
+ if (!request.earJwk) {
14230
+ throw createBrowserAuthError(earJwkEmpty);
14231
+ }
14232
+ const parameters = await getStandardParameters(config, authority, request, logger, performanceClient);
14233
+ addResponseType(parameters, OAuthResponseType.IDTOKEN_TOKEN_REFRESHTOKEN);
14234
+ addEARParameters(parameters, request.earJwk);
14235
+ const queryParams = new Map();
14236
+ addExtraQueryParameters(queryParams, request.extraQueryParameters || {});
14237
+ const url = getAuthorizeUrl(authority, queryParams, config.auth.encodeExtraQueryParams, request.extraQueryParameters);
14238
+ return createForm(frame, url, parameters);
14239
+ }
14240
+ /**
14241
+ * Creates form element in the provided document with auth parameters in the post body
14242
+ * @param frame
14243
+ * @param authorizeUrl
14244
+ * @param parameters
14245
+ * @returns
14246
+ */
14247
+ function createForm(frame, authorizeUrl, parameters) {
14248
+ const form = frame.createElement("form");
14249
+ form.method = "post";
14250
+ form.action = authorizeUrl;
14251
+ parameters.forEach((value, key) => {
14252
+ const param = frame.createElement("input");
14253
+ param.hidden = true;
14254
+ param.name = key;
14255
+ param.value = value;
14256
+ form.appendChild(param);
14257
+ });
14258
+ frame.body.appendChild(form);
14259
+ return form;
14260
+ }
14261
+ /**
14262
+ * Response handler when server returns accountId on the /authorize request
14263
+ * @param request
14264
+ * @param accountId
14265
+ * @param apiId
14266
+ * @param config
14267
+ * @param browserStorage
14268
+ * @param nativeStorage
14269
+ * @param eventHandler
14270
+ * @param logger
14271
+ * @param performanceClient
14272
+ * @param nativeMessageHandler
14273
+ * @returns
14274
+ */
14275
+ async function handleResponsePlatformBroker(request, accountId, apiId, config, browserStorage, nativeStorage, eventHandler, logger, performanceClient, platformAuthProvider) {
14276
+ logger.verbose("Account id found, calling WAM for token");
14277
+ if (!platformAuthProvider) {
14278
+ throw createBrowserAuthError(nativeConnectionNotEstablished);
14279
+ }
14280
+ const browserCrypto = new CryptoOps(logger, performanceClient);
14281
+ const nativeInteractionClient = new PlatformAuthInteractionClient(config, browserStorage, browserCrypto, logger, eventHandler, config.system.navigationClient, apiId, performanceClient, platformAuthProvider, accountId, nativeStorage, request.correlationId);
14282
+ const { userRequestState } = ProtocolUtils.parseRequestState(browserCrypto, request.state);
14283
+ return invokeAsync(nativeInteractionClient.acquireToken.bind(nativeInteractionClient), PerformanceEvents.NativeInteractionClientAcquireToken, logger, performanceClient, request.correlationId)({
14284
+ ...request,
14285
+ state: userRequestState,
14286
+ prompt: undefined, // Server should handle the prompt, ideally native broker can do this part silently
14287
+ });
14288
+ }
14289
+ /**
14290
+ * Response handler when server returns code on the /authorize request
14291
+ * @param request
14292
+ * @param response
14293
+ * @param codeVerifier
14294
+ * @param authClient
14295
+ * @param browserStorage
14296
+ * @param logger
14297
+ * @param performanceClient
14298
+ * @returns
14299
+ */
14300
+ async function handleResponseCode(request, response, codeVerifier, apiId, config, authClient, browserStorage, nativeStorage, eventHandler, logger, performanceClient, platformAuthProvider) {
14301
+ // Remove throttle if it exists
14302
+ ThrottlingUtils.removeThrottle(browserStorage, config.auth.clientId, request);
14303
+ if (response.accountId) {
14304
+ return invokeAsync(handleResponsePlatformBroker, PerformanceEvents.HandleResponsePlatformBroker, logger, performanceClient, request.correlationId)(request, response.accountId, apiId, config, browserStorage, nativeStorage, eventHandler, logger, performanceClient, platformAuthProvider);
14305
+ }
14306
+ const authCodeRequest = {
14307
+ ...request,
14308
+ code: response.code || "",
14309
+ codeVerifier: codeVerifier,
14310
+ };
14311
+ // Create popup interaction handler.
14312
+ const interactionHandler = new InteractionHandler(authClient, browserStorage, authCodeRequest, logger, performanceClient);
14313
+ // Handle response from hash string.
14314
+ const result = await invokeAsync(interactionHandler.handleCodeResponse.bind(interactionHandler), PerformanceEvents.HandleCodeResponse, logger, performanceClient, request.correlationId)(response, request);
14315
+ return result;
14316
+ }
14317
+ /**
14318
+ * Response handler when server returns ear_jwe on the /authorize request
14319
+ * @param request
14320
+ * @param response
14321
+ * @param apiId
14322
+ * @param config
14323
+ * @param authority
14324
+ * @param browserStorage
14325
+ * @param nativeStorage
14326
+ * @param eventHandler
14327
+ * @param logger
14328
+ * @param performanceClient
14329
+ * @param nativeMessageHandler
14330
+ * @returns
14331
+ */
14332
+ async function handleResponseEAR(request, response, apiId, config, authority, browserStorage, nativeStorage, eventHandler, logger, performanceClient, platformAuthProvider) {
14333
+ // Remove throttle if it exists
14334
+ ThrottlingUtils.removeThrottle(browserStorage, config.auth.clientId, request);
14335
+ // Validate state & check response for errors
14336
+ validateAuthorizationResponse(response, request.state);
14337
+ if (!response.ear_jwe) {
14338
+ throw createBrowserAuthError(earJweEmpty);
14339
+ }
14340
+ if (!request.earJwk) {
14341
+ throw createBrowserAuthError(earJwkEmpty);
14342
+ }
14343
+ const decryptedData = JSON.parse(await invokeAsync(decryptEarResponse, PerformanceEvents.DecryptEarResponse, logger, performanceClient, request.correlationId)(request.earJwk, response.ear_jwe));
14344
+ if (decryptedData.accountId) {
14345
+ return invokeAsync(handleResponsePlatformBroker, PerformanceEvents.HandleResponsePlatformBroker, logger, performanceClient, request.correlationId)(request, decryptedData.accountId, apiId, config, browserStorage, nativeStorage, eventHandler, logger, performanceClient, platformAuthProvider);
14346
+ }
14347
+ const responseHandler = new ResponseHandler(config.auth.clientId, browserStorage, new CryptoOps(logger, performanceClient), logger, null, null, performanceClient);
14348
+ // Validate response. This function throws a server error if an error is returned by the server.
14349
+ responseHandler.validateTokenResponse(decryptedData);
14350
+ // Temporary until response handler is refactored to be more flow agnostic.
14351
+ const additionalData = {
14352
+ code: "",
14353
+ state: request.state,
14354
+ nonce: request.nonce,
14355
+ client_info: decryptedData.client_info,
14356
+ cloud_graph_host_name: decryptedData.cloud_graph_host_name,
14357
+ cloud_instance_host_name: decryptedData.cloud_instance_host_name,
14358
+ cloud_instance_name: decryptedData.cloud_instance_name,
14359
+ msgraph_host: decryptedData.msgraph_host,
14360
+ };
14361
+ return (await invokeAsync(responseHandler.handleServerTokenResponse.bind(responseHandler), PerformanceEvents.HandleServerTokenResponse, logger, performanceClient, request.correlationId)(decryptedData, authority, nowSeconds(), request, additionalData, undefined, undefined, undefined, undefined));
14362
+ }
14363
+
14364
+ /*
14365
+ * Copyright (c) Microsoft Corporation. All rights reserved.
14366
+ * Licensed under the MIT License.
14367
+ */
14368
+ // Constant byte array length
14369
+ const RANDOM_BYTE_ARR_LENGTH = 32;
14370
+ /**
14371
+ * This file defines APIs to generate PKCE codes and code verifiers.
14372
+ */
14373
+ /**
14374
+ * Generates PKCE Codes. See the RFC for more information: https://tools.ietf.org/html/rfc7636
14375
+ */
14376
+ async function generatePkceCodes(performanceClient, logger, correlationId) {
14377
+ performanceClient.addQueueMeasurement(PerformanceEvents.GeneratePkceCodes, correlationId);
14378
+ const codeVerifier = invoke(generateCodeVerifier, PerformanceEvents.GenerateCodeVerifier, logger, performanceClient, correlationId)(performanceClient, logger, correlationId);
14379
+ const codeChallenge = await invokeAsync(generateCodeChallengeFromVerifier, PerformanceEvents.GenerateCodeChallengeFromVerifier, logger, performanceClient, correlationId)(codeVerifier, performanceClient, logger, correlationId);
14380
+ return {
14381
+ verifier: codeVerifier,
14382
+ challenge: codeChallenge,
14383
+ };
14384
+ }
14385
+ /**
14386
+ * Generates a random 32 byte buffer and returns the base64
14387
+ * encoded string to be used as a PKCE Code Verifier
14388
+ */
14389
+ function generateCodeVerifier(performanceClient, logger, correlationId) {
14390
+ try {
14391
+ // Generate random values as utf-8
14392
+ const buffer = new Uint8Array(RANDOM_BYTE_ARR_LENGTH);
14393
+ invoke(getRandomValues, PerformanceEvents.GetRandomValues, logger, performanceClient, correlationId)(buffer);
14394
+ // encode verifier as base64
14395
+ const pkceCodeVerifierB64 = urlEncodeArr(buffer);
14396
+ return pkceCodeVerifierB64;
14397
+ }
14398
+ catch (e) {
14399
+ throw createBrowserAuthError(pkceNotCreated);
14400
+ }
14401
+ }
14402
+ /**
14403
+ * Creates a base64 encoded PKCE Code Challenge string from the
14404
+ * hash created from the PKCE Code Verifier supplied
14405
+ */
14406
+ async function generateCodeChallengeFromVerifier(pkceCodeVerifier, performanceClient, logger, correlationId) {
14407
+ performanceClient.addQueueMeasurement(PerformanceEvents.GenerateCodeChallengeFromVerifier, correlationId);
14408
+ try {
14409
+ // hashed verifier
14410
+ const pkceHashedCodeVerifier = await invokeAsync(sha256Digest, PerformanceEvents.Sha256Digest, logger, performanceClient, correlationId)(pkceCodeVerifier, performanceClient, correlationId);
14411
+ // encode hash as base64
14412
+ return urlEncodeArr(new Uint8Array(pkceHashedCodeVerifier));
14413
+ }
14414
+ catch (e) {
14415
+ throw createBrowserAuthError(pkceNotCreated);
14416
+ }
14417
+ }
14418
+
14419
+ /*
14420
+ * Copyright (c) Microsoft Corporation. All rights reserved.
14421
+ * Licensed under the MIT License.
14422
+ */
14423
+ class PlatformAuthExtensionHandler {
14424
+ constructor(logger, handshakeTimeoutMs, performanceClient, extensionId) {
14425
+ this.logger = logger;
14426
+ this.handshakeTimeoutMs = handshakeTimeoutMs;
14427
+ this.extensionId = extensionId;
14428
+ this.resolvers = new Map(); // Used for non-handshake messages
14429
+ this.handshakeResolvers = new Map(); // Used for handshake messages
14430
+ this.messageChannel = new MessageChannel();
14431
+ this.windowListener = this.onWindowMessage.bind(this); // Window event callback doesn't have access to 'this' unless it's bound
14432
+ this.performanceClient = performanceClient;
14433
+ this.handshakeEvent = performanceClient.startMeasurement(PerformanceEvents.NativeMessageHandlerHandshake);
14434
+ this.platformAuthType =
14435
+ PlatformAuthConstants.PLATFORM_EXTENSION_PROVIDER;
14179
14436
  }
14180
14437
  /**
14181
- * cache the account entity in browser storage
14182
- * @param accountEntity
14438
+ * Sends a given message to the extension and resolves with the extension response
14439
+ * @param request
14183
14440
  */
14184
- async cacheAccount(accountEntity) {
14185
- // Store the account info and hence `nativeAccountId` in browser cache
14186
- await this.browserStorage.setAccount(accountEntity, this.correlationId);
14187
- // Remove any existing cached tokens for this account in browser storage
14188
- this.browserStorage.removeAccountContext(accountEntity).catch((e) => {
14189
- this.logger.error(`Error occurred while removing account context from browser storage. ${e}`);
14441
+ async sendMessage(request) {
14442
+ this.logger.trace(this.platformAuthType + " - sendMessage called.");
14443
+ // fall back to native calls
14444
+ const messageBody = {
14445
+ method: NativeExtensionMethod.GetToken,
14446
+ request: request,
14447
+ };
14448
+ const req = {
14449
+ channel: PlatformAuthConstants.CHANNEL_ID,
14450
+ extensionId: this.extensionId,
14451
+ responseId: createNewGuid(),
14452
+ body: messageBody,
14453
+ };
14454
+ this.logger.trace(this.platformAuthType + " - Sending request to browser extension");
14455
+ this.logger.tracePii(this.platformAuthType +
14456
+ ` - Sending request to browser extension: ${JSON.stringify(req)}`);
14457
+ this.messageChannel.port1.postMessage(req);
14458
+ const response = await new Promise((resolve, reject) => {
14459
+ this.resolvers.set(req.responseId, { resolve, reject });
14190
14460
  });
14461
+ const validatedResponse = this.validatePlatformBrokerResponse(response);
14462
+ return validatedResponse;
14191
14463
  }
14192
14464
  /**
14193
- * Stores the access_token and id_token in inmemory storage
14194
- * @param response
14195
- * @param request
14196
- * @param homeAccountIdentifier
14197
- * @param idTokenObj
14198
- * @param responseAccessToken
14199
- * @param tenantId
14200
- * @param reqTimestamp
14465
+ * Returns an instance of the MessageHandler that has successfully established a connection with an extension
14466
+ * @param {Logger} logger
14467
+ * @param {number} handshakeTimeoutMs
14468
+ * @param {IPerformanceClient} performanceClient
14469
+ * @param {ICrypto} crypto
14201
14470
  */
14202
- cacheNativeTokens(response, request, homeAccountIdentifier, idTokenClaims, responseAccessToken, tenantId, reqTimestamp) {
14203
- const cachedIdToken = createIdTokenEntity(homeAccountIdentifier, request.authority, response.id_token || "", request.clientId, idTokenClaims.tid || "");
14204
- // cache accessToken in inmemory storage
14205
- const expiresIn = request.tokenType === AuthenticationScheme.POP
14206
- ? Constants.SHR_NONCE_VALIDITY
14207
- : (typeof response.expires_in === "string"
14208
- ? parseInt(response.expires_in, 10)
14209
- : response.expires_in) || 0;
14210
- const tokenExpirationSeconds = reqTimestamp + expiresIn;
14211
- const responseScopes = this.generateScopes(response, request);
14212
- const cachedAccessToken = createAccessTokenEntity(homeAccountIdentifier, request.authority, responseAccessToken, request.clientId, idTokenClaims.tid || tenantId, responseScopes.printScopes(), tokenExpirationSeconds, 0, base64Decode, undefined, request.tokenType, undefined, request.keyId);
14213
- const nativeCacheRecord = {
14214
- idToken: cachedIdToken,
14215
- accessToken: cachedAccessToken,
14471
+ static async createProvider(logger, handshakeTimeoutMs, performanceClient) {
14472
+ logger.trace("PlatformAuthExtensionHandler - createProvider called.");
14473
+ try {
14474
+ const preferredProvider = new PlatformAuthExtensionHandler(logger, handshakeTimeoutMs, performanceClient, PlatformAuthConstants.PREFERRED_EXTENSION_ID);
14475
+ await preferredProvider.sendHandshakeRequest();
14476
+ return preferredProvider;
14477
+ }
14478
+ catch (e) {
14479
+ // If preferred extension fails for whatever reason, fallback to using any installed extension
14480
+ const backupProvider = new PlatformAuthExtensionHandler(logger, handshakeTimeoutMs, performanceClient);
14481
+ await backupProvider.sendHandshakeRequest();
14482
+ return backupProvider;
14483
+ }
14484
+ }
14485
+ /**
14486
+ * Send handshake request helper.
14487
+ */
14488
+ async sendHandshakeRequest() {
14489
+ this.logger.trace(this.platformAuthType + " - sendHandshakeRequest called.");
14490
+ // Register this event listener before sending handshake
14491
+ window.addEventListener("message", this.windowListener, false); // false is important, because content script message processing should work first
14492
+ const req = {
14493
+ channel: PlatformAuthConstants.CHANNEL_ID,
14494
+ extensionId: this.extensionId,
14495
+ responseId: createNewGuid(),
14496
+ body: {
14497
+ method: NativeExtensionMethod.HandshakeRequest,
14498
+ },
14216
14499
  };
14217
- return this.nativeStorageManager.saveCacheRecord(nativeCacheRecord, this.correlationId, request.storeInCache);
14500
+ this.handshakeEvent.add({
14501
+ extensionId: this.extensionId,
14502
+ extensionHandshakeTimeoutMs: this.handshakeTimeoutMs,
14503
+ });
14504
+ this.messageChannel.port1.onmessage = (event) => {
14505
+ this.onChannelMessage(event);
14506
+ };
14507
+ window.postMessage(req, window.origin, [this.messageChannel.port2]);
14508
+ return new Promise((resolve, reject) => {
14509
+ this.handshakeResolvers.set(req.responseId, { resolve, reject });
14510
+ this.timeoutId = window.setTimeout(() => {
14511
+ /*
14512
+ * Throw an error if neither HandshakeResponse nor original Handshake request are received in a reasonable timeframe.
14513
+ * This typically suggests an event handler stopped propagation of the Handshake request but did not respond to it on the MessageChannel port
14514
+ */
14515
+ window.removeEventListener("message", this.windowListener, false);
14516
+ this.messageChannel.port1.close();
14517
+ this.messageChannel.port2.close();
14518
+ this.handshakeEvent.end({
14519
+ extensionHandshakeTimedOut: true,
14520
+ success: false,
14521
+ });
14522
+ reject(createBrowserAuthError(nativeHandshakeTimeout));
14523
+ this.handshakeResolvers.delete(req.responseId);
14524
+ }, this.handshakeTimeoutMs); // Use a reasonable timeout in milliseconds here
14525
+ });
14218
14526
  }
14219
- addTelemetryFromNativeResponse(response) {
14220
- const mats = this.getMATSFromResponse(response);
14221
- if (!mats) {
14222
- return null;
14527
+ /**
14528
+ * Invoked when a message is posted to the window. If a handshake request is received it means the extension is not installed.
14529
+ * @param event
14530
+ */
14531
+ onWindowMessage(event) {
14532
+ this.logger.trace(this.platformAuthType + " - onWindowMessage called");
14533
+ // We only accept messages from ourselves
14534
+ if (event.source !== window) {
14535
+ return;
14536
+ }
14537
+ const request = event.data;
14538
+ if (!request.channel ||
14539
+ request.channel !== PlatformAuthConstants.CHANNEL_ID) {
14540
+ return;
14541
+ }
14542
+ if (request.extensionId && request.extensionId !== this.extensionId) {
14543
+ return;
14544
+ }
14545
+ if (request.body.method === NativeExtensionMethod.HandshakeRequest) {
14546
+ const handshakeResolver = this.handshakeResolvers.get(request.responseId);
14547
+ /*
14548
+ * Filter out responses with no matched resolvers sooner to keep channel ports open while waiting for
14549
+ * the proper response.
14550
+ */
14551
+ if (!handshakeResolver) {
14552
+ this.logger.trace(this.platformAuthType +
14553
+ `.onWindowMessage - resolver can't be found for request ${request.responseId}`);
14554
+ return;
14555
+ }
14556
+ // If we receive this message back it means no extension intercepted the request, meaning no extension supporting handshake protocol is installed
14557
+ this.logger.verbose(request.extensionId
14558
+ ? `Extension with id: ${request.extensionId} not installed`
14559
+ : "No extension installed");
14560
+ clearTimeout(this.timeoutId);
14561
+ this.messageChannel.port1.close();
14562
+ this.messageChannel.port2.close();
14563
+ window.removeEventListener("message", this.windowListener, false);
14564
+ this.handshakeEvent.end({
14565
+ success: false,
14566
+ extensionInstalled: false,
14567
+ });
14568
+ handshakeResolver.reject(createBrowserAuthError(nativeExtensionNotInstalled));
14569
+ }
14570
+ }
14571
+ /**
14572
+ * Invoked when a message is received from the extension on the MessageChannel port
14573
+ * @param event
14574
+ */
14575
+ onChannelMessage(event) {
14576
+ this.logger.trace(this.platformAuthType + " - onChannelMessage called.");
14577
+ const request = event.data;
14578
+ const resolver = this.resolvers.get(request.responseId);
14579
+ const handshakeResolver = this.handshakeResolvers.get(request.responseId);
14580
+ try {
14581
+ const method = request.body.method;
14582
+ if (method === NativeExtensionMethod.Response) {
14583
+ if (!resolver) {
14584
+ return;
14585
+ }
14586
+ const response = request.body.response;
14587
+ this.logger.trace(this.platformAuthType +
14588
+ " - Received response from browser extension");
14589
+ this.logger.tracePii(this.platformAuthType +
14590
+ ` - Received response from browser extension: ${JSON.stringify(response)}`);
14591
+ if (response.status !== "Success") {
14592
+ resolver.reject(createNativeAuthError(response.code, response.description, response.ext));
14593
+ }
14594
+ else if (response.result) {
14595
+ if (response.result["code"] &&
14596
+ response.result["description"]) {
14597
+ resolver.reject(createNativeAuthError(response.result["code"], response.result["description"], response.result["ext"]));
14598
+ }
14599
+ else {
14600
+ resolver.resolve(response.result);
14601
+ }
14602
+ }
14603
+ else {
14604
+ throw createAuthError(unexpectedError, "Event does not contain result.");
14605
+ }
14606
+ this.resolvers.delete(request.responseId);
14607
+ }
14608
+ else if (method === NativeExtensionMethod.HandshakeResponse) {
14609
+ if (!handshakeResolver) {
14610
+ this.logger.trace(this.platformAuthType +
14611
+ `.onChannelMessage - resolver can't be found for request ${request.responseId}`);
14612
+ return;
14613
+ }
14614
+ clearTimeout(this.timeoutId); // Clear setTimeout
14615
+ window.removeEventListener("message", this.windowListener, false); // Remove 'No extension' listener
14616
+ this.extensionId = request.extensionId;
14617
+ this.extensionVersion = request.body.version;
14618
+ this.logger.verbose(this.platformAuthType +
14619
+ ` - Received HandshakeResponse from extension: ${this.extensionId}`);
14620
+ this.handshakeEvent.end({
14621
+ extensionInstalled: true,
14622
+ success: true,
14623
+ });
14624
+ handshakeResolver.resolve();
14625
+ this.handshakeResolvers.delete(request.responseId);
14626
+ }
14627
+ // Do nothing if method is not Response or HandshakeResponse
14628
+ }
14629
+ catch (err) {
14630
+ this.logger.error("Error parsing response from WAM Extension");
14631
+ this.logger.errorPii(`Error parsing response from WAM Extension: ${err}`);
14632
+ this.logger.errorPii(`Unable to parse ${event}`);
14633
+ if (resolver) {
14634
+ resolver.reject(err);
14635
+ }
14636
+ else if (handshakeResolver) {
14637
+ handshakeResolver.reject(err);
14638
+ }
14223
14639
  }
14224
- this.performanceClient.addFields({
14225
- extensionId: this.nativeMessageHandler.getExtensionId(),
14226
- extensionVersion: this.nativeMessageHandler.getExtensionVersion(),
14227
- matsBrokerVersion: mats.broker_version,
14228
- matsAccountJoinOnStart: mats.account_join_on_start,
14229
- matsAccountJoinOnEnd: mats.account_join_on_end,
14230
- matsDeviceJoin: mats.device_join,
14231
- matsPromptBehavior: mats.prompt_behavior,
14232
- matsApiErrorCode: mats.api_error_code,
14233
- matsUiVisible: mats.ui_visible,
14234
- matsSilentCode: mats.silent_code,
14235
- matsSilentBiSubCode: mats.silent_bi_sub_code,
14236
- matsSilentMessage: mats.silent_message,
14237
- matsSilentStatus: mats.silent_status,
14238
- matsHttpStatus: mats.http_status,
14239
- matsHttpEventCount: mats.http_event_count,
14240
- }, this.correlationId);
14241
- return mats;
14242
14640
  }
14243
14641
  /**
14244
14642
  * Validates native platform response before processing
14245
14643
  * @param response
14246
14644
  */
14247
- validateNativeResponse(response) {
14645
+ validatePlatformBrokerResponse(response) {
14248
14646
  if (response.hasOwnProperty("access_token") &&
14249
14647
  response.hasOwnProperty("id_token") &&
14250
14648
  response.hasOwnProperty("client_info") &&
@@ -14258,425 +14656,258 @@ class NativeInteractionClient extends BaseInteractionClient {
14258
14656
  }
14259
14657
  }
14260
14658
  /**
14261
- * Gets MATS telemetry from native response
14262
- * @param response
14263
- * @returns
14264
- */
14265
- getMATSFromResponse(response) {
14266
- if (response.properties.MATS) {
14267
- try {
14268
- return JSON.parse(response.properties.MATS);
14269
- }
14270
- catch (e) {
14271
- this.logger.error("NativeInteractionClient - Error parsing MATS telemetry, returning null instead");
14272
- }
14273
- }
14274
- return null;
14275
- }
14276
- /**
14277
- * Returns whether or not response came from native cache
14278
- * @param response
14659
+ * Returns the Id for the browser extension this handler is communicating with
14279
14660
  * @returns
14280
14661
  */
14281
- isResponseFromCache(mats) {
14282
- if (typeof mats.is_cached === "undefined") {
14283
- this.logger.verbose("NativeInteractionClient - MATS telemetry does not contain field indicating if response was served from cache. Returning false.");
14284
- return false;
14285
- }
14286
- return !!mats.is_cached;
14287
- }
14288
- /**
14289
- * Translates developer provided request object into NativeRequest object
14290
- * @param request
14291
- */
14292
- async initializeNativeRequest(request) {
14293
- this.logger.trace("NativeInteractionClient - initializeNativeRequest called");
14294
- const requestAuthority = request.authority || this.config.auth.authority;
14295
- if (request.account) {
14296
- // validate authority
14297
- await this.getDiscoveredAuthority({
14298
- requestAuthority,
14299
- requestAzureCloudOptions: request.azureCloudOptions,
14300
- account: request.account,
14301
- });
14302
- }
14303
- const canonicalAuthority = new UrlString(requestAuthority);
14304
- canonicalAuthority.validateAsUri();
14305
- // 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.
14306
- const { scopes, ...remainingProperties } = request;
14307
- const scopeSet = new ScopeSet(scopes || []);
14308
- scopeSet.appendScopes(OIDC_DEFAULT_SCOPES);
14309
- const getPrompt = () => {
14310
- // If request is silent, prompt is always none
14311
- switch (this.apiId) {
14312
- case ApiId.ssoSilent:
14313
- case ApiId.acquireTokenSilent_silentFlow:
14314
- this.logger.trace("initializeNativeRequest: silent request sets prompt to none");
14315
- return PromptValue.NONE;
14316
- }
14317
- // Prompt not provided, request may proceed and native broker decides if it needs to prompt
14318
- if (!request.prompt) {
14319
- this.logger.trace("initializeNativeRequest: prompt was not provided");
14320
- return undefined;
14321
- }
14322
- // If request is interactive, check if prompt provided is allowed to go directly to native broker
14323
- switch (request.prompt) {
14324
- case PromptValue.NONE:
14325
- case PromptValue.CONSENT:
14326
- case PromptValue.LOGIN:
14327
- this.logger.trace("initializeNativeRequest: prompt is compatible with native flow");
14328
- return request.prompt;
14329
- default:
14330
- this.logger.trace(`initializeNativeRequest: prompt = ${request.prompt} is not compatible with native flow`);
14331
- throw createBrowserAuthError(nativePromptNotSupported);
14332
- }
14333
- };
14334
- const validatedRequest = {
14335
- ...remainingProperties,
14336
- accountId: this.accountId,
14337
- clientId: this.config.auth.clientId,
14338
- authority: canonicalAuthority.urlString,
14339
- scope: scopeSet.printScopes(),
14340
- redirectUri: this.getRedirectUri(request.redirectUri),
14341
- prompt: getPrompt(),
14342
- correlationId: this.correlationId,
14343
- tokenType: request.authenticationScheme,
14344
- windowTitleSubstring: document.title,
14345
- extraParameters: {
14346
- ...request.extraQueryParameters,
14347
- ...request.tokenQueryParameters,
14348
- },
14349
- extendedExpiryToken: false,
14350
- keyId: request.popKid,
14351
- };
14352
- // Check for PoP token requests: signPopToken should only be set to true if popKid is not set
14353
- if (validatedRequest.signPopToken && !!request.popKid) {
14354
- throw createBrowserAuthError(invalidPopTokenRequest);
14355
- }
14356
- this.handleExtraBrokerParams(validatedRequest);
14357
- validatedRequest.extraParameters =
14358
- validatedRequest.extraParameters || {};
14359
- validatedRequest.extraParameters.telemetry =
14360
- NativeConstants.MATS_TELEMETRY;
14361
- if (request.authenticationScheme === AuthenticationScheme.POP) {
14362
- // add POP request type
14363
- const shrParameters = {
14364
- resourceRequestUri: request.resourceRequestUri,
14365
- resourceRequestMethod: request.resourceRequestMethod,
14366
- shrClaims: request.shrClaims,
14367
- shrNonce: request.shrNonce,
14368
- };
14369
- const popTokenGenerator = new PopTokenGenerator(this.browserCrypto);
14370
- // generate reqCnf if not provided in the request
14371
- let reqCnfData;
14372
- if (!validatedRequest.keyId) {
14373
- const generatedReqCnfData = await invokeAsync(popTokenGenerator.generateCnf.bind(popTokenGenerator), PerformanceEvents.PopTokenGenerateCnf, this.logger, this.performanceClient, request.correlationId)(shrParameters, this.logger);
14374
- reqCnfData = generatedReqCnfData.reqCnfString;
14375
- validatedRequest.keyId = generatedReqCnfData.kid;
14376
- validatedRequest.signPopToken = true;
14377
- }
14378
- else {
14379
- reqCnfData = this.browserCrypto.base64UrlEncode(JSON.stringify({ kid: validatedRequest.keyId }));
14380
- validatedRequest.signPopToken = false;
14381
- }
14382
- // SPAs require whole string to be passed to broker
14383
- validatedRequest.reqCnf = reqCnfData;
14384
- }
14385
- this.addRequestSKUs(validatedRequest);
14386
- return validatedRequest;
14387
- }
14388
- /**
14389
- * Handles extra broker request parameters
14390
- * @param request {NativeTokenRequest}
14391
- * @private
14392
- */
14393
- handleExtraBrokerParams(request) {
14394
- const hasExtraBrokerParams = request.extraParameters &&
14395
- request.extraParameters.hasOwnProperty(BROKER_CLIENT_ID) &&
14396
- request.extraParameters.hasOwnProperty(BROKER_REDIRECT_URI) &&
14397
- request.extraParameters.hasOwnProperty(CLIENT_ID);
14398
- if (!request.embeddedClientId && !hasExtraBrokerParams) {
14399
- return;
14400
- }
14401
- let child_client_id = "";
14402
- const child_redirect_uri = request.redirectUri;
14403
- if (request.embeddedClientId) {
14404
- request.redirectUri = this.config.auth.redirectUri;
14405
- child_client_id = request.embeddedClientId;
14406
- }
14407
- else if (request.extraParameters) {
14408
- request.redirectUri =
14409
- request.extraParameters[BROKER_REDIRECT_URI];
14410
- child_client_id =
14411
- request.extraParameters[CLIENT_ID];
14412
- }
14413
- request.extraParameters = {
14414
- child_client_id,
14415
- child_redirect_uri,
14416
- };
14417
- this.performanceClient?.addFields({
14418
- embeddedClientId: child_client_id,
14419
- embeddedRedirectUri: child_redirect_uri,
14420
- }, request.correlationId);
14421
- }
14422
- }
14423
-
14424
- /*
14425
- * Copyright (c) Microsoft Corporation. All rights reserved.
14426
- * Licensed under the MIT License.
14427
- */
14428
- /**
14429
- * Returns map of parameters that are applicable to all calls to /authorize whether using PKCE or EAR
14430
- * @param config
14431
- * @param authority
14432
- * @param request
14433
- * @param logger
14434
- * @param performanceClient
14435
- * @returns
14436
- */
14437
- async function getStandardParameters(config, authority, request, logger, performanceClient) {
14438
- const parameters = getStandardAuthorizeRequestParameters({ ...config.auth, authority: authority }, request, logger, performanceClient);
14439
- addLibraryInfo(parameters, {
14440
- sku: BrowserConstants.MSAL_SKU,
14441
- version: version,
14442
- os: "",
14443
- cpu: "",
14444
- });
14445
- if (config.auth.protocolMode !== ProtocolMode.OIDC) {
14446
- addApplicationTelemetry(parameters, config.telemetry.application);
14447
- }
14448
- if (request.platformBroker) {
14449
- // signal ests that this is a WAM call
14450
- addNativeBroker(parameters);
14451
- // pass the req_cnf for POP
14452
- if (request.authenticationScheme === AuthenticationScheme.POP) {
14453
- const cryptoOps = new CryptoOps(logger, performanceClient);
14454
- const popTokenGenerator = new PopTokenGenerator(cryptoOps);
14455
- // req_cnf is always sent as a string for SPAs
14456
- let reqCnfData;
14457
- if (!request.popKid) {
14458
- const generatedReqCnfData = await invokeAsync(popTokenGenerator.generateCnf.bind(popTokenGenerator), PerformanceEvents.PopTokenGenerateCnf, logger, performanceClient, request.correlationId)(request, logger);
14459
- reqCnfData = generatedReqCnfData.reqCnfString;
14460
- }
14461
- else {
14462
- reqCnfData = cryptoOps.encodeKid(request.popKid);
14463
- }
14464
- addPopToken(parameters, reqCnfData);
14465
- }
14662
+ getExtensionId() {
14663
+ return this.extensionId;
14466
14664
  }
14467
- instrumentBrokerParams(parameters, request.correlationId, performanceClient);
14468
- return parameters;
14469
- }
14470
- /**
14471
- * Gets the full /authorize URL with request parameters when using Auth Code + PKCE
14472
- * @param config
14473
- * @param authority
14474
- * @param request
14475
- * @param logger
14476
- * @param performanceClient
14477
- * @returns
14478
- */
14479
- async function getAuthCodeRequestUrl(config, authority, request, logger, performanceClient) {
14480
- if (!request.codeChallenge) {
14481
- throw createClientConfigurationError(pkceParamsMissing);
14665
+ /**
14666
+ * Returns the version for the browser extension this handler is communicating with
14667
+ * @returns
14668
+ */
14669
+ getExtensionVersion() {
14670
+ return this.extensionVersion;
14482
14671
  }
14483
- const parameters = await invokeAsync(getStandardParameters, PerformanceEvents.GetStandardParams, logger, performanceClient, request.correlationId)(config, authority, request, logger, performanceClient);
14484
- addResponseType(parameters, OAuthResponseType.CODE);
14485
- addCodeChallengeParams(parameters, request.codeChallenge, Constants.S256_CODE_CHALLENGE_METHOD);
14486
- addExtraQueryParameters(parameters, request.extraQueryParameters || {});
14487
- return getAuthorizeUrl(authority, parameters, config.auth.encodeExtraQueryParams, request.extraQueryParameters);
14488
- }
14489
- /**
14490
- * Gets the form that will be posted to /authorize with request parameters when using EAR
14491
- */
14492
- async function getEARForm(frame, config, authority, request, logger, performanceClient) {
14493
- if (!request.earJwk) {
14494
- throw createBrowserAuthError(earJwkEmpty);
14672
+ getExtensionName() {
14673
+ return this.getExtensionId() ===
14674
+ PlatformAuthConstants.PREFERRED_EXTENSION_ID
14675
+ ? "chrome"
14676
+ : this.getExtensionId()?.length
14677
+ ? "unknown"
14678
+ : undefined;
14495
14679
  }
14496
- const parameters = await getStandardParameters(config, authority, request, logger, performanceClient);
14497
- addResponseType(parameters, OAuthResponseType.IDTOKEN_TOKEN_REFRESHTOKEN);
14498
- addEARParameters(parameters, request.earJwk);
14499
- const queryParams = new Map();
14500
- addExtraQueryParameters(queryParams, request.extraQueryParameters || {});
14501
- const url = getAuthorizeUrl(authority, queryParams, config.auth.encodeExtraQueryParams, request.extraQueryParameters);
14502
- return createForm(frame, url, parameters);
14503
- }
14504
- /**
14505
- * Creates form element in the provided document with auth parameters in the post body
14506
- * @param frame
14507
- * @param authorizeUrl
14508
- * @param parameters
14509
- * @returns
14510
- */
14511
- function createForm(frame, authorizeUrl, parameters) {
14512
- const form = frame.createElement("form");
14513
- form.method = "post";
14514
- form.action = authorizeUrl;
14515
- parameters.forEach((value, key) => {
14516
- const param = frame.createElement("input");
14517
- param.hidden = true;
14518
- param.name = key;
14519
- param.value = value;
14520
- form.appendChild(param);
14521
- });
14522
- frame.body.appendChild(form);
14523
- return form;
14524
- }
14525
- /**
14526
- * Response handler when server returns accountId on the /authorize request
14527
- * @param request
14528
- * @param accountId
14529
- * @param apiId
14530
- * @param config
14531
- * @param browserStorage
14532
- * @param nativeStorage
14533
- * @param eventHandler
14534
- * @param logger
14535
- * @param performanceClient
14536
- * @param nativeMessageHandler
14537
- * @returns
14680
+ }
14681
+
14682
+ /*
14683
+ * Copyright (c) Microsoft Corporation. All rights reserved.
14684
+ * Licensed under the MIT License.
14538
14685
  */
14539
- async function handleResponsePlatformBroker(request, accountId, apiId, config, browserStorage, nativeStorage, eventHandler, logger, performanceClient, nativeMessageHandler) {
14540
- if (!nativeMessageHandler) {
14541
- throw createBrowserAuthError(nativeConnectionNotEstablished);
14686
+ class PlatformAuthDOMHandler {
14687
+ constructor(logger, performanceClient, correlationId) {
14688
+ this.logger = logger;
14689
+ this.performanceClient = performanceClient;
14690
+ this.correlationId = correlationId;
14691
+ this.platformAuthType = PlatformAuthConstants.PLATFORM_DOM_PROVIDER;
14542
14692
  }
14543
- const browserCrypto = new CryptoOps(logger, performanceClient);
14544
- const nativeInteractionClient = new NativeInteractionClient(config, browserStorage, browserCrypto, logger, eventHandler, config.system.navigationClient, apiId, performanceClient, nativeMessageHandler, accountId, nativeStorage, request.correlationId);
14545
- const { userRequestState } = ProtocolUtils.parseRequestState(browserCrypto, request.state);
14546
- return invokeAsync(nativeInteractionClient.acquireToken.bind(nativeInteractionClient), PerformanceEvents.NativeInteractionClientAcquireToken, logger, performanceClient, request.correlationId)({
14547
- ...request,
14548
- state: userRequestState,
14549
- prompt: undefined, // Server should handle the prompt, ideally native broker can do this part silently
14550
- });
14551
- }
14552
- /**
14553
- * Response handler when server returns code on the /authorize request
14554
- * @param request
14555
- * @param response
14556
- * @param codeVerifier
14557
- * @param authClient
14558
- * @param browserStorage
14559
- * @param logger
14560
- * @param performanceClient
14561
- * @returns
14562
- */
14563
- async function handleResponseCode(request, response, codeVerifier, apiId, config, authClient, browserStorage, nativeStorage, eventHandler, logger, performanceClient, nativeMessageHandler) {
14564
- // Remove throttle if it exists
14565
- ThrottlingUtils.removeThrottle(browserStorage, config.auth.clientId, request);
14566
- if (response.accountId) {
14567
- return invokeAsync(handleResponsePlatformBroker, PerformanceEvents.HandleResponsePlatformBroker, logger, performanceClient, request.correlationId)(request, response.accountId, apiId, config, browserStorage, nativeStorage, eventHandler, logger, performanceClient, nativeMessageHandler);
14693
+ static async createProvider(logger, performanceClient, correlationId) {
14694
+ logger.trace("PlatformAuthDOMHandler: createProvider called");
14695
+ // @ts-ignore
14696
+ if (window.navigator?.platformAuthentication) {
14697
+ const supportedContracts =
14698
+ // @ts-ignore
14699
+ await window.navigator.platformAuthentication.getSupportedContracts(PlatformAuthConstants.MICROSOFT_ENTRA_BROKERID);
14700
+ if (supportedContracts?.includes(PlatformAuthConstants.PLATFORM_DOM_APIS)) {
14701
+ logger.trace("Platform auth api available in DOM");
14702
+ return new PlatformAuthDOMHandler(logger, performanceClient, correlationId);
14703
+ }
14704
+ }
14705
+ return undefined;
14568
14706
  }
14569
- const authCodeRequest = {
14570
- ...request,
14571
- code: response.code || "",
14572
- codeVerifier: codeVerifier,
14573
- };
14574
- // Create popup interaction handler.
14575
- const interactionHandler = new InteractionHandler(authClient, browserStorage, authCodeRequest, logger, performanceClient);
14576
- // Handle response from hash string.
14577
- const result = await invokeAsync(interactionHandler.handleCodeResponse.bind(interactionHandler), PerformanceEvents.HandleCodeResponse, logger, performanceClient, request.correlationId)(response, request);
14578
- return result;
14579
- }
14580
- /**
14581
- * Response handler when server returns ear_jwe on the /authorize request
14582
- * @param request
14583
- * @param response
14584
- * @param apiId
14585
- * @param config
14586
- * @param authority
14587
- * @param browserStorage
14588
- * @param nativeStorage
14589
- * @param eventHandler
14590
- * @param logger
14591
- * @param performanceClient
14592
- * @param nativeMessageHandler
14593
- * @returns
14594
- */
14595
- async function handleResponseEAR(request, response, apiId, config, authority, browserStorage, nativeStorage, eventHandler, logger, performanceClient, nativeMessageHandler) {
14596
- // Remove throttle if it exists
14597
- ThrottlingUtils.removeThrottle(browserStorage, config.auth.clientId, request);
14598
- // Validate state & check response for errors
14599
- validateAuthorizationResponse(response, request.state);
14600
- if (!response.ear_jwe) {
14601
- throw createBrowserAuthError(earJweEmpty);
14707
+ /**
14708
+ * Returns the Id for the broker extension this handler is communicating with
14709
+ * @returns
14710
+ */
14711
+ getExtensionId() {
14712
+ return PlatformAuthConstants.MICROSOFT_ENTRA_BROKERID;
14602
14713
  }
14603
- if (!request.earJwk) {
14604
- throw createBrowserAuthError(earJwkEmpty);
14714
+ getExtensionVersion() {
14715
+ return "";
14605
14716
  }
14606
- const decryptedData = JSON.parse(await invokeAsync(decryptEarResponse, PerformanceEvents.DecryptEarResponse, logger, performanceClient, request.correlationId)(request.earJwk, response.ear_jwe));
14607
- if (decryptedData.accountId) {
14608
- return invokeAsync(handleResponsePlatformBroker, PerformanceEvents.HandleResponsePlatformBroker, logger, performanceClient, request.correlationId)(request, decryptedData.accountId, apiId, config, browserStorage, nativeStorage, eventHandler, logger, performanceClient, nativeMessageHandler);
14717
+ getExtensionName() {
14718
+ return PlatformAuthConstants.DOM_API_NAME;
14719
+ }
14720
+ /**
14721
+ * Send token request to platform broker via browser DOM API
14722
+ * @param request
14723
+ * @returns
14724
+ */
14725
+ async sendMessage(request) {
14726
+ this.logger.trace(this.platformAuthType + " - Sending request to browser DOM API");
14727
+ try {
14728
+ const platformDOMRequest = this.initializePlatformDOMRequest(request);
14729
+ const response =
14730
+ // @ts-ignore
14731
+ await window.navigator.platformAuthentication.executeGetToken(platformDOMRequest);
14732
+ return this.validatePlatformBrokerResponse(response);
14733
+ }
14734
+ catch (e) {
14735
+ this.logger.error(this.platformAuthType + " - executeGetToken DOM API error");
14736
+ throw e;
14737
+ }
14738
+ }
14739
+ initializePlatformDOMRequest(request) {
14740
+ this.logger.trace(this.platformAuthType + " - initializeNativeDOMRequest called");
14741
+ const { accountId, clientId, authority, scope, redirectUri, correlationId, state, storeInCache, embeddedClientId, extraParameters, ...remainingProperties } = request;
14742
+ const validExtraParameters = this.getDOMExtraParams(remainingProperties);
14743
+ const platformDOMRequest = {
14744
+ accountId: accountId,
14745
+ brokerId: this.getExtensionId(),
14746
+ authority: authority,
14747
+ clientId: clientId,
14748
+ correlationId: correlationId || this.correlationId,
14749
+ extraParameters: { ...extraParameters, ...validExtraParameters },
14750
+ isSecurityTokenService: false,
14751
+ redirectUri: redirectUri,
14752
+ scope: scope,
14753
+ state: state,
14754
+ storeInCache: storeInCache,
14755
+ embeddedClientId: embeddedClientId,
14756
+ };
14757
+ return platformDOMRequest;
14758
+ }
14759
+ validatePlatformBrokerResponse(response) {
14760
+ if (response.hasOwnProperty("isSuccess")) {
14761
+ if (response.hasOwnProperty("accessToken") &&
14762
+ response.hasOwnProperty("idToken") &&
14763
+ response.hasOwnProperty("clientInfo") &&
14764
+ response.hasOwnProperty("account") &&
14765
+ response.hasOwnProperty("scopes") &&
14766
+ response.hasOwnProperty("expiresIn")) {
14767
+ this.logger.trace(this.platformAuthType +
14768
+ " - platform broker returned successful and valid response");
14769
+ return this.convertToPlatformBrokerResponse(response);
14770
+ }
14771
+ else if (response.hasOwnProperty("error")) {
14772
+ const errorResponse = response;
14773
+ if (errorResponse.isSuccess === false &&
14774
+ errorResponse.error &&
14775
+ errorResponse.error.code) {
14776
+ this.logger.trace(this.platformAuthType +
14777
+ " - platform broker returned error response");
14778
+ throw createNativeAuthError(errorResponse.error.code, errorResponse.error.description, {
14779
+ error: parseInt(errorResponse.error.errorCode),
14780
+ protocol_error: errorResponse.error.protocolError,
14781
+ status: errorResponse.error.status,
14782
+ properties: errorResponse.error.properties,
14783
+ });
14784
+ }
14785
+ }
14786
+ }
14787
+ throw createAuthError(unexpectedError, "Response missing expected properties.");
14788
+ }
14789
+ convertToPlatformBrokerResponse(response) {
14790
+ this.logger.trace(this.platformAuthType + " - convertToNativeResponse called");
14791
+ const nativeResponse = {
14792
+ access_token: response.accessToken,
14793
+ id_token: response.idToken,
14794
+ client_info: response.clientInfo,
14795
+ account: response.account,
14796
+ expires_in: response.expiresIn,
14797
+ scope: response.scopes,
14798
+ state: response.state || "",
14799
+ properties: response.properties || {},
14800
+ extendedLifetimeToken: response.extendedLifetimeToken ?? false,
14801
+ shr: response.proofOfPossessionPayload,
14802
+ };
14803
+ return nativeResponse;
14804
+ }
14805
+ getDOMExtraParams(extraParameters) {
14806
+ const stringifiedParams = Object.entries(extraParameters).reduce((record, [key, value]) => {
14807
+ record[key] = String(value);
14808
+ return record;
14809
+ }, {});
14810
+ const validExtraParams = {
14811
+ ...stringifiedParams,
14812
+ };
14813
+ return validExtraParams;
14609
14814
  }
14610
- const responseHandler = new ResponseHandler(config.auth.clientId, browserStorage, new CryptoOps(logger, performanceClient), logger, null, null, performanceClient);
14611
- // Validate response. This function throws a server error if an error is returned by the server.
14612
- responseHandler.validateTokenResponse(decryptedData);
14613
- // Temporary until response handler is refactored to be more flow agnostic.
14614
- const additionalData = {
14615
- code: "",
14616
- state: request.state,
14617
- nonce: request.nonce,
14618
- client_info: decryptedData.client_info,
14619
- cloud_graph_host_name: decryptedData.cloud_graph_host_name,
14620
- cloud_instance_host_name: decryptedData.cloud_instance_host_name,
14621
- cloud_instance_name: decryptedData.cloud_instance_name,
14622
- msgraph_host: decryptedData.msgraph_host,
14623
- };
14624
- return (await invokeAsync(responseHandler.handleServerTokenResponse.bind(responseHandler), PerformanceEvents.HandleServerTokenResponse, logger, performanceClient, request.correlationId)(decryptedData, authority, nowSeconds(), request, additionalData, undefined, undefined, undefined, undefined));
14625
14815
  }
14626
14816
 
14627
14817
  /*
14628
14818
  * Copyright (c) Microsoft Corporation. All rights reserved.
14629
14819
  * Licensed under the MIT License.
14630
14820
  */
14631
- // Constant byte array length
14632
- const RANDOM_BYTE_ARR_LENGTH = 32;
14633
- /**
14634
- * This file defines APIs to generate PKCE codes and code verifiers.
14635
- */
14636
14821
  /**
14637
- * Generates PKCE Codes. See the RFC for more information: https://tools.ietf.org/html/rfc7636
14822
+ * Checks if the platform broker is available in the current environment.
14823
+ * @param loggerOptions
14824
+ * @param perfClient
14825
+ * @returns
14638
14826
  */
14639
- async function generatePkceCodes(performanceClient, logger, correlationId) {
14640
- performanceClient.addQueueMeasurement(PerformanceEvents.GeneratePkceCodes, correlationId);
14641
- const codeVerifier = invoke(generateCodeVerifier, PerformanceEvents.GenerateCodeVerifier, logger, performanceClient, correlationId)(performanceClient, logger, correlationId);
14642
- const codeChallenge = await invokeAsync(generateCodeChallengeFromVerifier, PerformanceEvents.GenerateCodeChallengeFromVerifier, logger, performanceClient, correlationId)(codeVerifier, performanceClient, logger, correlationId);
14643
- return {
14644
- verifier: codeVerifier,
14645
- challenge: codeChallenge,
14646
- };
14827
+ async function isPlatformBrokerAvailable(loggerOptions, perfClient, correlationId) {
14828
+ const logger = new Logger(loggerOptions || {}, name, version);
14829
+ logger.trace("isPlatformBrokerAvailable called");
14830
+ const performanceClient = perfClient || new StubPerformanceClient();
14831
+ if (typeof window === "undefined") {
14832
+ logger.trace("Non-browser environment detected, returning false");
14833
+ return false;
14834
+ }
14835
+ return !!(await getPlatformAuthProvider(logger, performanceClient, correlationId || createNewGuid()));
14647
14836
  }
14648
- /**
14649
- * Generates a random 32 byte buffer and returns the base64
14650
- * encoded string to be used as a PKCE Code Verifier
14651
- */
14652
- function generateCodeVerifier(performanceClient, logger, correlationId) {
14837
+ async function getPlatformAuthProvider(logger, performanceClient, correlationId, nativeBrokerHandshakeTimeout) {
14838
+ logger.trace("getPlatformAuthProvider called", correlationId);
14839
+ const enablePlatformBrokerDOMSupport = isDomEnabledForPlatformAuth();
14840
+ logger.trace("Has client allowed platform auth via DOM API: " +
14841
+ enablePlatformBrokerDOMSupport);
14842
+ let platformAuthProvider;
14653
14843
  try {
14654
- // Generate random values as utf-8
14655
- const buffer = new Uint8Array(RANDOM_BYTE_ARR_LENGTH);
14656
- invoke(getRandomValues, PerformanceEvents.GetRandomValues, logger, performanceClient, correlationId)(buffer);
14657
- // encode verifier as base64
14658
- const pkceCodeVerifierB64 = urlEncodeArr(buffer);
14659
- return pkceCodeVerifierB64;
14844
+ if (enablePlatformBrokerDOMSupport) {
14845
+ // Check if DOM platform API is supported first
14846
+ platformAuthProvider = await PlatformAuthDOMHandler.createProvider(logger, performanceClient, correlationId);
14847
+ }
14848
+ if (!platformAuthProvider) {
14849
+ logger.trace("Platform auth via DOM API not available, checking for extension");
14850
+ /*
14851
+ * If DOM APIs are not available, check if browser extension is available.
14852
+ * Platform authentication via DOM APIs is preferred over extension APIs.
14853
+ */
14854
+ platformAuthProvider =
14855
+ await PlatformAuthExtensionHandler.createProvider(logger, nativeBrokerHandshakeTimeout ||
14856
+ DEFAULT_NATIVE_BROKER_HANDSHAKE_TIMEOUT_MS, performanceClient);
14857
+ }
14660
14858
  }
14661
14859
  catch (e) {
14662
- throw createBrowserAuthError(pkceNotCreated);
14860
+ logger.trace("Platform auth not available", e);
14663
14861
  }
14862
+ return platformAuthProvider;
14664
14863
  }
14665
14864
  /**
14666
- * Creates a base64 encoded PKCE Code Challenge string from the
14667
- * hash created from the PKCE Code Verifier supplied
14865
+ * Returns true if the DOM API support for platform auth is enabled in session storage
14866
+ * @returns boolean
14867
+ * @deprecated
14668
14868
  */
14669
- async function generateCodeChallengeFromVerifier(pkceCodeVerifier, performanceClient, logger, correlationId) {
14670
- performanceClient.addQueueMeasurement(PerformanceEvents.GenerateCodeChallengeFromVerifier, correlationId);
14869
+ function isDomEnabledForPlatformAuth() {
14870
+ let sessionStorage;
14671
14871
  try {
14672
- // hashed verifier
14673
- const pkceHashedCodeVerifier = await invokeAsync(sha256Digest, PerformanceEvents.Sha256Digest, logger, performanceClient, correlationId)(pkceCodeVerifier, performanceClient, correlationId);
14674
- // encode hash as base64
14675
- return urlEncodeArr(new Uint8Array(pkceHashedCodeVerifier));
14872
+ sessionStorage = window[BrowserCacheLocation.SessionStorage];
14873
+ // Mute errors if it's a non-browser environment or cookies are blocked.
14874
+ return sessionStorage?.getItem(PLATFORM_AUTH_DOM_SUPPORT) === "true";
14676
14875
  }
14677
14876
  catch (e) {
14678
- throw createBrowserAuthError(pkceNotCreated);
14877
+ return false;
14878
+ }
14879
+ }
14880
+ /**
14881
+ * Returns boolean indicating whether or not the request should attempt to use native broker
14882
+ * @param logger
14883
+ * @param config
14884
+ * @param platformAuthProvider
14885
+ * @param authenticationScheme
14886
+ */
14887
+ function isPlatformAuthAllowed(config, logger, platformAuthProvider, authenticationScheme) {
14888
+ logger.trace("isBrokerAvailable called");
14889
+ if (!config.system.allowPlatformBroker) {
14890
+ logger.trace("isBrokerAvailable: allowPlatformBroker is not enabled, returning false");
14891
+ // Developer disabled WAM
14892
+ return false;
14893
+ }
14894
+ if (!platformAuthProvider) {
14895
+ logger.trace("isBrokerAvailable: Platform auth provider is not initialized, returning false");
14896
+ // Platform broker auth providers are not available
14897
+ return false;
14898
+ }
14899
+ if (authenticationScheme) {
14900
+ switch (authenticationScheme) {
14901
+ case AuthenticationScheme.BEARER:
14902
+ case AuthenticationScheme.POP:
14903
+ logger.trace("isBrokerAvailable: authenticationScheme is supported, returning true");
14904
+ return true;
14905
+ default:
14906
+ logger.trace("isBrokerAvailable: authenticationScheme is not supported, returning false");
14907
+ return false;
14908
+ }
14679
14909
  }
14910
+ return true;
14680
14911
  }
14681
14912
 
14682
14913
  /*
@@ -14684,8 +14915,8 @@ async function generateCodeChallengeFromVerifier(pkceCodeVerifier, performanceCl
14684
14915
  * Licensed under the MIT License.
14685
14916
  */
14686
14917
  class PopupClient extends StandardInteractionClient {
14687
- constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeStorageImpl, nativeMessageHandler, correlationId) {
14688
- super(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeMessageHandler, correlationId);
14918
+ constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeStorageImpl, platformAuthHandler, correlationId) {
14919
+ super(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, platformAuthHandler, correlationId);
14689
14920
  // Properly sets this reference for the unload event.
14690
14921
  this.unloadWindow = this.unloadWindow.bind(this);
14691
14922
  this.nativeStorage = nativeStorageImpl;
@@ -14773,7 +15004,7 @@ class PopupClient extends StandardInteractionClient {
14773
15004
  if (popupParams.popup) {
14774
15005
  preconnect(validRequest.authority);
14775
15006
  }
14776
- const isPlatformBroker = NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeMessageHandler, request.authenticationScheme);
15007
+ const isPlatformBroker = isPlatformAuthAllowed(this.config, this.logger, this.platformAuthProvider, request.authenticationScheme);
14777
15008
  validRequest.platformBroker = isPlatformBroker;
14778
15009
  if (this.config.auth.protocolMode === ProtocolMode.EAR) {
14779
15010
  return this.executeEarFlow(validRequest, popupParams);
@@ -14815,7 +15046,7 @@ class PopupClient extends StandardInteractionClient {
14815
15046
  // Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
14816
15047
  const responseString = await this.monitorPopupForHash(popupWindow, popupParams.popupWindowParent);
14817
15048
  const serverParams = invoke(deserializeResponse, PerformanceEvents.DeserializeResponse, this.logger, this.performanceClient, this.correlationId)(responseString, this.config.auth.OIDCOptions.serverResponseType, this.logger);
14818
- 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);
15049
+ 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);
14819
15050
  }
14820
15051
  catch (e) {
14821
15052
  // Close the synchronous popup if an error is thrown before the window unload event is registered
@@ -14851,7 +15082,7 @@ class PopupClient extends StandardInteractionClient {
14851
15082
  // Monitor the popup for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
14852
15083
  const responseString = await invokeAsync(this.monitorPopupForHash.bind(this), PerformanceEvents.SilentHandlerMonitorIframeForHash, this.logger, this.performanceClient, correlationId)(popupWindow, popupParams.popupWindowParent);
14853
15084
  const serverParams = invoke(deserializeResponse, PerformanceEvents.DeserializeResponse, this.logger, this.performanceClient, this.correlationId)(responseString, this.config.auth.OIDCOptions.serverResponseType, this.logger);
14854
- 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);
15085
+ 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);
14855
15086
  }
14856
15087
  /**
14857
15088
  *
@@ -15148,8 +15379,8 @@ function getNavigationType() {
15148
15379
  return navigation?.type;
15149
15380
  }
15150
15381
  class RedirectClient extends StandardInteractionClient {
15151
- constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeStorageImpl, nativeMessageHandler, correlationId) {
15152
- super(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeMessageHandler, correlationId);
15382
+ constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeStorageImpl, platformAuthHandler, correlationId) {
15383
+ super(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, platformAuthHandler, correlationId);
15153
15384
  this.nativeStorage = nativeStorageImpl;
15154
15385
  }
15155
15386
  /**
@@ -15158,8 +15389,7 @@ class RedirectClient extends StandardInteractionClient {
15158
15389
  */
15159
15390
  async acquireToken(request) {
15160
15391
  const validRequest = await invokeAsync(this.initializeAuthorizationRequest.bind(this), PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest, this.logger, this.performanceClient, this.correlationId)(request, exports.InteractionType.Redirect);
15161
- validRequest.platformBroker =
15162
- NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeMessageHandler, request.authenticationScheme);
15392
+ validRequest.platformBroker = isPlatformAuthAllowed(this.config, this.logger, this.platformAuthProvider, request.authenticationScheme);
15163
15393
  const handleBackButton = (event) => {
15164
15394
  // Clear temporary cache if the back button is clicked during the redirect flow.
15165
15395
  if (event.persisted) {
@@ -15399,10 +15629,10 @@ class RedirectClient extends StandardInteractionClient {
15399
15629
  requestExtraQueryParameters: request.extraQueryParameters,
15400
15630
  account: request.account,
15401
15631
  });
15402
- 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);
15632
+ 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);
15403
15633
  }
15404
15634
  const authClient = await invokeAsync(this.createAuthCodeClient.bind(this), PerformanceEvents.StandardInteractionClientCreateAuthCodeClient, this.logger, this.performanceClient, this.correlationId)({ serverTelemetryManager, requestAuthority: request.authority });
15405
- 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);
15635
+ 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);
15406
15636
  }
15407
15637
  /**
15408
15638
  * Redirects window to given URL.
@@ -15686,8 +15916,8 @@ function removeHiddenIframe(iframe) {
15686
15916
  * Licensed under the MIT License.
15687
15917
  */
15688
15918
  class SilentIframeClient extends StandardInteractionClient {
15689
- constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, apiId, performanceClient, nativeStorageImpl, nativeMessageHandler, correlationId) {
15690
- super(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeMessageHandler, correlationId);
15919
+ constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, apiId, performanceClient, nativeStorageImpl, platformAuthProvider, correlationId) {
15920
+ super(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, platformAuthProvider, correlationId);
15691
15921
  this.apiId = apiId;
15692
15922
  this.nativeStorage = nativeStorageImpl;
15693
15923
  }
@@ -15717,8 +15947,7 @@ class SilentIframeClient extends StandardInteractionClient {
15717
15947
  }
15718
15948
  // Create silent request
15719
15949
  const silentRequest = await invokeAsync(this.initializeAuthorizationRequest.bind(this), PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest, this.logger, this.performanceClient, request.correlationId)(inputRequest, exports.InteractionType.Silent);
15720
- silentRequest.platformBroker =
15721
- NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeMessageHandler, silentRequest.authenticationScheme);
15950
+ silentRequest.platformBroker = isPlatformAuthAllowed(this.config, this.logger, this.platformAuthProvider, silentRequest.authenticationScheme);
15722
15951
  preconnect(silentRequest.authority);
15723
15952
  if (this.config.auth.protocolMode === ProtocolMode.EAR) {
15724
15953
  return this.executeEarFlow(silentRequest);
@@ -15784,7 +16013,7 @@ class SilentIframeClient extends StandardInteractionClient {
15784
16013
  // Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
15785
16014
  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);
15786
16015
  const serverParams = invoke(deserializeResponse, PerformanceEvents.DeserializeResponse, this.logger, this.performanceClient, correlationId)(responseString, responseType, this.logger);
15787
- 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);
16016
+ 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);
15788
16017
  }
15789
16018
  /**
15790
16019
  * Currently Unsupported
@@ -15815,7 +16044,7 @@ class SilentIframeClient extends StandardInteractionClient {
15815
16044
  // Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
15816
16045
  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);
15817
16046
  const serverParams = invoke(deserializeResponse, PerformanceEvents.DeserializeResponse, this.logger, this.performanceClient, correlationId)(responseString, responseType, this.logger);
15818
- 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);
16047
+ 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);
15819
16048
  }
15820
16049
  }
15821
16050
 
@@ -16096,8 +16325,8 @@ class HybridSpaAuthorizationCodeClient extends AuthorizationCodeClient {
16096
16325
  * Licensed under the MIT License.
16097
16326
  */
16098
16327
  class SilentAuthCodeClient extends StandardInteractionClient {
16099
- constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, apiId, performanceClient, nativeMessageHandler, correlationId) {
16100
- super(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, nativeMessageHandler, correlationId);
16328
+ constructor(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, apiId, performanceClient, platformAuthProvider, correlationId) {
16329
+ super(config, storageImpl, browserCrypto, logger, eventHandler, navigationClient, performanceClient, platformAuthProvider, correlationId);
16101
16330
  this.apiId = apiId;
16102
16331
  }
16103
16332
  /**
@@ -16155,6 +16384,25 @@ class SilentAuthCodeClient extends StandardInteractionClient {
16155
16384
  }
16156
16385
  }
16157
16386
 
16387
+ /*
16388
+ * Copyright (c) Microsoft Corporation. All rights reserved.
16389
+ * Licensed under the MIT License.
16390
+ */
16391
+ function collectInstanceStats(currentClientId, performanceEvent, logger) {
16392
+ const frameInstances =
16393
+ // @ts-ignore
16394
+ window.msal?.clientIds || [];
16395
+ const msalInstanceCount = frameInstances.length;
16396
+ const sameClientIdInstanceCount = frameInstances.filter((i) => i === currentClientId).length;
16397
+ if (sameClientIdInstanceCount > 1) {
16398
+ logger.warning("There is already an instance of MSAL.js in the window with the same client id.");
16399
+ }
16400
+ performanceEvent.add({
16401
+ msalInstanceCount: msalInstanceCount,
16402
+ sameClientIdInstanceCount: sameClientIdInstanceCount,
16403
+ });
16404
+ }
16405
+
16158
16406
  /*
16159
16407
  * Copyright (c) Microsoft Corporation. All rights reserved.
16160
16408
  * Licensed under the MIT License.
@@ -16266,7 +16514,7 @@ class StandardController {
16266
16514
  * Initializer function to perform async startup tasks such as connecting to WAM extension
16267
16515
  * @param request {?InitializeApplicationRequest} correlation id
16268
16516
  */
16269
- async initialize(request) {
16517
+ async initialize(request, isBroker) {
16270
16518
  this.logger.trace("initialize called");
16271
16519
  if (this.initialized) {
16272
16520
  this.logger.info("initialize has already been called, exiting early.");
@@ -16282,11 +16530,18 @@ class StandardController {
16282
16530
  const allowPlatformBroker = this.config.system.allowPlatformBroker;
16283
16531
  const initMeasurement = this.performanceClient.startMeasurement(PerformanceEvents.InitializeClientApplication, initCorrelationId);
16284
16532
  this.eventHandler.emitEvent(EventType.INITIALIZE_START);
16533
+ // Broker applications are initialized twice, so we avoid double-counting it
16534
+ if (!isBroker) {
16535
+ try {
16536
+ this.logMultipleInstances(initMeasurement);
16537
+ }
16538
+ catch { }
16539
+ }
16285
16540
  await invokeAsync(this.browserStorage.initialize.bind(this.browserStorage), PerformanceEvents.InitializeCache, this.logger, this.performanceClient, initCorrelationId)(initCorrelationId);
16286
16541
  if (allowPlatformBroker) {
16287
16542
  try {
16288
- this.nativeExtensionProvider =
16289
- await NativeMessageHandler.createProvider(this.logger, this.config.system.nativeBrokerHandshakeTimeout, this.performanceClient);
16543
+ // check if platform authentication is available via DOM or browser extension and create relevant handlers
16544
+ this.platformAuthProvider = await getPlatformAuthProvider(this.logger, this.performanceClient, initCorrelationId, this.config.system.nativeBrokerHandshakeTimeout);
16290
16545
  }
16291
16546
  catch (e) {
16292
16547
  this.logger.verbose(e);
@@ -16356,18 +16611,15 @@ class StandardController {
16356
16611
  }
16357
16612
  const loggedInAccounts = this.getAllAccounts();
16358
16613
  const platformBrokerRequest = this.browserStorage.getCachedNativeRequest();
16359
- const useNative = platformBrokerRequest &&
16360
- NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeExtensionProvider) &&
16361
- this.nativeExtensionProvider &&
16362
- !hash;
16614
+ const useNative = platformBrokerRequest && this.platformAuthProvider && !hash;
16363
16615
  let rootMeasurement;
16364
16616
  this.eventHandler.emitEvent(EventType.HANDLE_REDIRECT_START, exports.InteractionType.Redirect);
16365
16617
  let redirectResponse;
16366
16618
  try {
16367
- if (useNative && this.nativeExtensionProvider) {
16619
+ if (useNative && this.platformAuthProvider) {
16368
16620
  rootMeasurement = this.performanceClient.startMeasurement(PerformanceEvents.AcquireTokenRedirect, platformBrokerRequest?.correlationId || "");
16369
16621
  this.logger.trace("handleRedirectPromise - acquiring token from native platform");
16370
- 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);
16622
+ 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);
16371
16623
  redirectResponse = invokeAsync(nativeClient.handleRedirectPromise.bind(nativeClient), PerformanceEvents.HandleNativeRedirectPromiseMeasurement, this.logger, this.performanceClient, rootMeasurement.event.correlationId)(this.performanceClient, rootMeasurement.event.correlationId);
16372
16624
  }
16373
16625
  else {
@@ -16496,15 +16748,15 @@ class StandardController {
16496
16748
  this.eventHandler.emitEvent(EventType.LOGIN_START, exports.InteractionType.Redirect, request);
16497
16749
  }
16498
16750
  let result;
16499
- if (this.nativeExtensionProvider &&
16751
+ if (this.platformAuthProvider &&
16500
16752
  this.canUsePlatformBroker(request)) {
16501
- 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);
16753
+ 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);
16502
16754
  result = nativeClient
16503
16755
  .acquireTokenRedirect(request, atrMeasurement)
16504
16756
  .catch((e) => {
16505
16757
  if (e instanceof NativeAuthError &&
16506
16758
  isFatalNativeAuthError(e)) {
16507
- this.nativeExtensionProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
16759
+ this.platformAuthProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
16508
16760
  const redirectClient = this.createRedirectClient(correlationId);
16509
16761
  return redirectClient.acquireToken(request);
16510
16762
  }
@@ -16585,7 +16837,7 @@ class StandardController {
16585
16837
  .catch((e) => {
16586
16838
  if (e instanceof NativeAuthError &&
16587
16839
  isFatalNativeAuthError(e)) {
16588
- this.nativeExtensionProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
16840
+ this.platformAuthProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
16589
16841
  const popupClient = this.createPopupClient(correlationId);
16590
16842
  return popupClient.acquireToken(request, pkce);
16591
16843
  }
@@ -16694,7 +16946,7 @@ class StandardController {
16694
16946
  result = this.acquireTokenNative(validRequest, ApiId.ssoSilent).catch((e) => {
16695
16947
  // If native token acquisition fails for availability reasons fallback to standard flow
16696
16948
  if (e instanceof NativeAuthError && isFatalNativeAuthError(e)) {
16697
- this.nativeExtensionProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
16949
+ this.platformAuthProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
16698
16950
  const silentIframeClient = this.createSilentIframeClient(validRequest.correlationId);
16699
16951
  return silentIframeClient.acquireToken(validRequest);
16700
16952
  }
@@ -16796,7 +17048,7 @@ class StandardController {
16796
17048
  // If native token acquisition fails for availability reasons fallback to standard flow
16797
17049
  if (e instanceof NativeAuthError &&
16798
17050
  isFatalNativeAuthError(e)) {
16799
- this.nativeExtensionProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
17051
+ this.platformAuthProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
16800
17052
  }
16801
17053
  throw e;
16802
17054
  });
@@ -17054,10 +17306,10 @@ class StandardController {
17054
17306
  */
17055
17307
  async acquireTokenNative(request, apiId, accountId, cacheLookupPolicy) {
17056
17308
  this.logger.trace("acquireTokenNative called");
17057
- if (!this.nativeExtensionProvider) {
17309
+ if (!this.platformAuthProvider) {
17058
17310
  throw createBrowserAuthError(nativeConnectionNotEstablished);
17059
17311
  }
17060
- 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);
17312
+ 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);
17061
17313
  return nativeClient.acquireToken(request, cacheLookupPolicy);
17062
17314
  }
17063
17315
  /**
@@ -17066,8 +17318,12 @@ class StandardController {
17066
17318
  */
17067
17319
  canUsePlatformBroker(request, accountId) {
17068
17320
  this.logger.trace("canUsePlatformBroker called");
17069
- if (!NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeExtensionProvider, request.authenticationScheme)) {
17070
- this.logger.trace("canUsePlatformBroker: isPlatformBrokerAvailable returned false, returning false");
17321
+ if (!this.platformAuthProvider) {
17322
+ this.logger.trace("canUsePlatformBroker: platform broker unavilable, returning false");
17323
+ return false;
17324
+ }
17325
+ if (!isPlatformAuthAllowed(this.config, this.logger, this.platformAuthProvider, request.authenticationScheme)) {
17326
+ this.logger.trace("canUsePlatformBroker: isBrokerAvailable returned false, returning false");
17071
17327
  return false;
17072
17328
  }
17073
17329
  if (request.prompt) {
@@ -17107,39 +17363,39 @@ class StandardController {
17107
17363
  * @param correlationId
17108
17364
  */
17109
17365
  createPopupClient(correlationId) {
17110
- return new PopupClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, this.performanceClient, this.nativeInternalStorage, this.nativeExtensionProvider, correlationId);
17366
+ return new PopupClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, this.performanceClient, this.nativeInternalStorage, this.platformAuthProvider, correlationId);
17111
17367
  }
17112
17368
  /**
17113
17369
  * Returns new instance of the Redirect Interaction Client
17114
17370
  * @param correlationId
17115
17371
  */
17116
17372
  createRedirectClient(correlationId) {
17117
- return new RedirectClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, this.performanceClient, this.nativeInternalStorage, this.nativeExtensionProvider, correlationId);
17373
+ return new RedirectClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, this.performanceClient, this.nativeInternalStorage, this.platformAuthProvider, correlationId);
17118
17374
  }
17119
17375
  /**
17120
17376
  * Returns new instance of the Silent Iframe Interaction Client
17121
17377
  * @param correlationId
17122
17378
  */
17123
17379
  createSilentIframeClient(correlationId) {
17124
- return new SilentIframeClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, ApiId.ssoSilent, this.performanceClient, this.nativeInternalStorage, this.nativeExtensionProvider, correlationId);
17380
+ return new SilentIframeClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, ApiId.ssoSilent, this.performanceClient, this.nativeInternalStorage, this.platformAuthProvider, correlationId);
17125
17381
  }
17126
17382
  /**
17127
17383
  * Returns new instance of the Silent Cache Interaction Client
17128
17384
  */
17129
17385
  createSilentCacheClient(correlationId) {
17130
- return new SilentCacheClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, this.performanceClient, this.nativeExtensionProvider, correlationId);
17386
+ return new SilentCacheClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, this.performanceClient, this.platformAuthProvider, correlationId);
17131
17387
  }
17132
17388
  /**
17133
17389
  * Returns new instance of the Silent Refresh Interaction Client
17134
17390
  */
17135
17391
  createSilentRefreshClient(correlationId) {
17136
- return new SilentRefreshClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, this.performanceClient, this.nativeExtensionProvider, correlationId);
17392
+ return new SilentRefreshClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, this.performanceClient, this.platformAuthProvider, correlationId);
17137
17393
  }
17138
17394
  /**
17139
17395
  * Returns new instance of the Silent AuthCode Interaction Client
17140
17396
  */
17141
17397
  createSilentAuthCodeClient(correlationId) {
17142
- return new SilentAuthCodeClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, ApiId.acquireTokenByCode, this.performanceClient, this.nativeExtensionProvider, correlationId);
17398
+ return new SilentAuthCodeClient(this.config, this.browserStorage, this.browserCrypto, this.logger, this.eventHandler, this.navigationClient, ApiId.acquireTokenByCode, this.performanceClient, this.platformAuthProvider, correlationId);
17143
17399
  }
17144
17400
  /**
17145
17401
  * Adds event callbacks to array
@@ -17485,14 +17741,14 @@ class StandardController {
17485
17741
  */
17486
17742
  async acquireTokenSilentNoIframe(silentRequest, cacheLookupPolicy) {
17487
17743
  // if the cache policy is set to access_token only, we should not be hitting the native layer yet
17488
- if (NativeMessageHandler.isPlatformBrokerAvailable(this.config, this.logger, this.nativeExtensionProvider, silentRequest.authenticationScheme) &&
17744
+ if (isPlatformAuthAllowed(this.config, this.logger, this.platformAuthProvider, silentRequest.authenticationScheme) &&
17489
17745
  silentRequest.account.nativeAccountId) {
17490
17746
  this.logger.verbose("acquireTokenSilent - attempting to acquire token from native platform");
17491
17747
  return this.acquireTokenNative(silentRequest, ApiId.acquireTokenSilent_silentFlow, silentRequest.account.nativeAccountId, cacheLookupPolicy).catch(async (e) => {
17492
17748
  // If native token acquisition fails for availability reasons fallback to web flow
17493
17749
  if (e instanceof NativeAuthError && isFatalNativeAuthError(e)) {
17494
17750
  this.logger.verbose("acquireTokenSilent - native platform unavailable, falling back to web flow");
17495
- this.nativeExtensionProvider = undefined; // Prevent future requests from continuing to attempt
17751
+ this.platformAuthProvider = undefined; // Prevent future requests from continuing to attempt
17496
17752
  // Cache will not contain tokens, given that previous WAM requests succeeded. Skip cache and RT renewal and go straight to iframe renewal
17497
17753
  throw createClientAuthError(tokenRefreshRequired);
17498
17754
  }
@@ -17535,6 +17791,23 @@ class StandardController {
17535
17791
  this.performanceClient.addFields({ usePreGeneratedPkce: !!res }, correlationId);
17536
17792
  return res;
17537
17793
  }
17794
+ logMultipleInstances(performanceEvent) {
17795
+ const clientId = this.config.auth.clientId;
17796
+ if (!window)
17797
+ return;
17798
+ // @ts-ignore
17799
+ window.msal = window.msal || {};
17800
+ // @ts-ignore
17801
+ window.msal.clientIds = window.msal.clientIds || [];
17802
+ // @ts-ignore
17803
+ const clientIds = window.msal.clientIds;
17804
+ if (clientIds.length > 0) {
17805
+ this.logger.verbose("There is already an instance of MSAL.js in the window.");
17806
+ }
17807
+ // @ts-ignore
17808
+ window.msal.clientIds.push(clientId);
17809
+ collectInstanceStats(clientId, performanceEvent, this.logger);
17810
+ }
17538
17811
  }
17539
17812
  /**
17540
17813
  * Determines whether an error thrown by the refresh token endpoint can be resolved without interaction
@@ -17821,7 +18094,9 @@ class NestedAppAuthController {
17821
18094
  * Specific implementation of initialize function for NestedAppAuthController
17822
18095
  * @returns
17823
18096
  */
17824
- async initialize(request) {
18097
+ async initialize(request,
18098
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
18099
+ isBroker) {
17825
18100
  const initCorrelationId = request?.correlationId || createNewGuid();
17826
18101
  await this.browserStorage.initialize(initCorrelationId);
17827
18102
  return Promise.resolve();
@@ -18343,6 +18618,7 @@ class PublicClientApplication {
18343
18618
  * @param IController Optional parameter to explictly set the controller. (Will be removed when we remove public constructor)
18344
18619
  */
18345
18620
  constructor(configuration, controller) {
18621
+ this.isBroker = false;
18346
18622
  this.controller =
18347
18623
  controller ||
18348
18624
  new StandardController(new StandardOperatingContext(configuration));
@@ -18352,7 +18628,7 @@ class PublicClientApplication {
18352
18628
  * @param request {?InitializeApplicationRequest}
18353
18629
  */
18354
18630
  async initialize(request) {
18355
- return this.controller.initialize(request);
18631
+ return this.controller.initialize(request, this.isBroker);
18356
18632
  }
18357
18633
  /**
18358
18634
  * Use when you want to obtain an access_token for your API via opening a popup window in the user's browser
@@ -19855,6 +20131,7 @@ exports.UrlString = UrlString;
19855
20131
  exports.WrapperSKU = WrapperSKU;
19856
20132
  exports.createNestablePublicClientApplication = createNestablePublicClientApplication;
19857
20133
  exports.createStandardPublicClientApplication = createStandardPublicClientApplication;
20134
+ exports.isPlatformBrokerAvailable = isPlatformBrokerAvailable;
19858
20135
  exports.stubbedPublicClientApplication = stubbedPublicClientApplication;
19859
20136
  exports.version = version;
19860
20137
  //# sourceMappingURL=msal-browser.cjs.map