@azure/msal-browser 4.12.0 → 4.13.1

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