@azure/msal-browser 3.5.1-beta.1 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (290) hide show
  1. package/dist/app/IPublicClientApplication.d.ts +51 -51
  2. package/dist/app/IPublicClientApplication.mjs +102 -102
  3. package/dist/app/IPublicClientApplication.mjs.map +1 -1
  4. package/dist/app/PublicClientApplication.d.ts +269 -268
  5. package/dist/app/PublicClientApplication.d.ts.map +1 -1
  6. package/dist/app/PublicClientApplication.mjs +333 -333
  7. package/dist/app/PublicClientApplication.mjs.map +1 -1
  8. package/dist/app/PublicClientNext.d.ts +273 -273
  9. package/dist/app/PublicClientNext.mjs +351 -351
  10. package/dist/app/PublicClientNext.mjs.map +1 -1
  11. package/dist/broker/nativeBroker/NativeMessageHandler.d.ts +62 -62
  12. package/dist/broker/nativeBroker/NativeMessageHandler.mjs +254 -254
  13. package/dist/broker/nativeBroker/NativeMessageHandler.mjs.map +1 -1
  14. package/dist/broker/nativeBroker/NativeRequest.d.ts +44 -44
  15. package/dist/broker/nativeBroker/NativeResponse.d.ts +48 -48
  16. package/dist/broker/nativeBroker/NativeStatusCodes.d.ts +7 -7
  17. package/dist/broker/nativeBroker/NativeStatusCodes.mjs +11 -11
  18. package/dist/broker/nativeBroker/NativeStatusCodes.mjs.map +1 -1
  19. package/dist/cache/AsyncMemoryStorage.d.ts +51 -51
  20. package/dist/cache/AsyncMemoryStorage.mjs +132 -132
  21. package/dist/cache/AsyncMemoryStorage.mjs.map +1 -1
  22. package/dist/cache/BrowserCacheManager.d.ts +395 -383
  23. package/dist/cache/BrowserCacheManager.d.ts.map +1 -1
  24. package/dist/cache/BrowserCacheManager.mjs +1283 -1263
  25. package/dist/cache/BrowserCacheManager.mjs.map +1 -1
  26. package/dist/cache/BrowserStorage.d.ts +11 -11
  27. package/dist/cache/BrowserStorage.mjs +32 -32
  28. package/dist/cache/BrowserStorage.mjs.map +1 -1
  29. package/dist/cache/CryptoKeyStore.d.ts +18 -18
  30. package/dist/cache/CryptoKeyStore.mjs +40 -40
  31. package/dist/cache/CryptoKeyStore.mjs.map +1 -1
  32. package/dist/cache/DatabaseStorage.d.ts +56 -56
  33. package/dist/cache/DatabaseStorage.mjs +190 -190
  34. package/dist/cache/DatabaseStorage.mjs.map +1 -1
  35. package/dist/cache/IAsyncMemoryStorage.d.ts +27 -27
  36. package/dist/cache/ITokenCache.d.ts +11 -11
  37. package/dist/cache/IWindowStorage.d.ts +27 -27
  38. package/dist/cache/MemoryStorage.d.ts +11 -11
  39. package/dist/cache/MemoryStorage.mjs +31 -31
  40. package/dist/cache/MemoryStorage.mjs.map +1 -1
  41. package/dist/cache/TokenCache.d.ts +77 -77
  42. package/dist/cache/TokenCache.d.ts.map +1 -1
  43. package/dist/cache/TokenCache.mjs +223 -225
  44. package/dist/cache/TokenCache.mjs.map +1 -1
  45. package/dist/config/Configuration.d.ts +206 -206
  46. package/dist/config/Configuration.d.ts.map +1 -1
  47. package/dist/config/Configuration.mjs +128 -128
  48. package/dist/config/Configuration.mjs.map +1 -1
  49. package/dist/controllers/ControllerFactory.d.ts +4 -4
  50. package/dist/controllers/ControllerFactory.d.ts.map +1 -1
  51. package/dist/controllers/ControllerFactory.mjs +29 -29
  52. package/dist/controllers/ControllerFactory.mjs.map +1 -1
  53. package/dist/controllers/IController.d.ts +61 -61
  54. package/dist/controllers/NestedAppAuthController.d.ts +95 -95
  55. package/dist/controllers/NestedAppAuthController.mjs +334 -334
  56. package/dist/controllers/NestedAppAuthController.mjs.map +1 -1
  57. package/dist/controllers/StandardController.d.ts +407 -407
  58. package/dist/controllers/StandardController.d.ts.map +1 -1
  59. package/dist/controllers/StandardController.mjs +1307 -1294
  60. package/dist/controllers/StandardController.mjs.map +1 -1
  61. package/dist/controllers/UnknownOperatingContextController.d.ts +87 -87
  62. package/dist/controllers/UnknownOperatingContextController.mjs +264 -264
  63. package/dist/controllers/UnknownOperatingContextController.mjs.map +1 -1
  64. package/dist/crypto/BrowserCrypto.d.ts +44 -44
  65. package/dist/crypto/BrowserCrypto.mjs +93 -93
  66. package/dist/crypto/BrowserCrypto.mjs.map +1 -1
  67. package/dist/crypto/CryptoOps.d.ts +63 -63
  68. package/dist/crypto/CryptoOps.mjs +145 -145
  69. package/dist/crypto/CryptoOps.mjs.map +1 -1
  70. package/dist/crypto/PkceGenerator.d.ts +8 -8
  71. package/dist/crypto/PkceGenerator.mjs +54 -54
  72. package/dist/crypto/PkceGenerator.mjs.map +1 -1
  73. package/dist/crypto/SignedHttpRequest.d.ts +30 -30
  74. package/dist/crypto/SignedHttpRequest.mjs +39 -39
  75. package/dist/crypto/SignedHttpRequest.mjs.map +1 -1
  76. package/dist/encode/Base64Decode.d.ts +9 -9
  77. package/dist/encode/Base64Decode.mjs +36 -36
  78. package/dist/encode/Base64Decode.mjs.map +1 -1
  79. package/dist/encode/Base64Encode.d.ts +19 -19
  80. package/dist/encode/Base64Encode.mjs +43 -43
  81. package/dist/encode/Base64Encode.mjs.map +1 -1
  82. package/dist/error/BrowserAuthError.d.ts +250 -250
  83. package/dist/error/BrowserAuthError.mjs +258 -258
  84. package/dist/error/BrowserAuthError.mjs.map +1 -1
  85. package/dist/error/BrowserAuthErrorCodes.d.ts +45 -45
  86. package/dist/error/BrowserAuthErrorCodes.mjs +49 -49
  87. package/dist/error/BrowserAuthErrorCodes.mjs.map +1 -1
  88. package/dist/error/BrowserConfigurationAuthError.d.ts +33 -33
  89. package/dist/error/BrowserConfigurationAuthError.mjs +40 -40
  90. package/dist/error/BrowserConfigurationAuthError.mjs.map +1 -1
  91. package/dist/error/BrowserConfigurationAuthErrorCodes.d.ts +3 -3
  92. package/dist/error/BrowserConfigurationAuthErrorCodes.mjs +7 -7
  93. package/dist/error/BrowserConfigurationAuthErrorCodes.mjs.map +1 -1
  94. package/dist/error/NativeAuthError.d.ts +29 -29
  95. package/dist/error/NativeAuthError.mjs +60 -60
  96. package/dist/error/NativeAuthError.mjs.map +1 -1
  97. package/dist/error/NativeAuthErrorCodes.d.ts +2 -2
  98. package/dist/error/NativeAuthErrorCodes.mjs +6 -6
  99. package/dist/error/NativeAuthErrorCodes.mjs.map +1 -1
  100. package/dist/error/NestedAppAuthError.d.ts +14 -14
  101. package/dist/error/NestedAppAuthError.mjs +23 -23
  102. package/dist/error/NestedAppAuthError.mjs.map +1 -1
  103. package/dist/event/EventHandler.d.ts +41 -41
  104. package/dist/event/EventHandler.mjs +119 -119
  105. package/dist/event/EventHandler.mjs.map +1 -1
  106. package/dist/event/EventMessage.d.ts +25 -25
  107. package/dist/event/EventMessage.mjs +68 -68
  108. package/dist/event/EventMessage.mjs.map +1 -1
  109. package/dist/event/EventType.d.ts +28 -28
  110. package/dist/event/EventType.mjs +31 -31
  111. package/dist/event/EventType.mjs.map +1 -1
  112. package/dist/index.d.ts +39 -39
  113. package/dist/index.d.ts.map +1 -1
  114. package/dist/index.mjs +1 -1
  115. package/dist/interaction_client/BaseInteractionClient.d.ts +54 -54
  116. package/dist/interaction_client/BaseInteractionClient.mjs +152 -152
  117. package/dist/interaction_client/BaseInteractionClient.mjs.map +1 -1
  118. package/dist/interaction_client/HybridSpaAuthorizationCodeClient.d.ts +4 -4
  119. package/dist/interaction_client/HybridSpaAuthorizationCodeClient.mjs +10 -10
  120. package/dist/interaction_client/HybridSpaAuthorizationCodeClient.mjs.map +1 -1
  121. package/dist/interaction_client/NativeInteractionClient.d.ts +140 -140
  122. package/dist/interaction_client/NativeInteractionClient.d.ts.map +1 -1
  123. package/dist/interaction_client/NativeInteractionClient.mjs +541 -549
  124. package/dist/interaction_client/NativeInteractionClient.mjs.map +1 -1
  125. package/dist/interaction_client/PopupClient.d.ts +105 -105
  126. package/dist/interaction_client/PopupClient.mjs +432 -432
  127. package/dist/interaction_client/PopupClient.mjs.map +1 -1
  128. package/dist/interaction_client/RedirectClient.d.ts +49 -49
  129. package/dist/interaction_client/RedirectClient.mjs +311 -311
  130. package/dist/interaction_client/RedirectClient.mjs.map +1 -1
  131. package/dist/interaction_client/SilentAuthCodeClient.d.ts +23 -23
  132. package/dist/interaction_client/SilentAuthCodeClient.mjs +57 -57
  133. package/dist/interaction_client/SilentAuthCodeClient.mjs.map +1 -1
  134. package/dist/interaction_client/SilentCacheClient.d.ts +24 -24
  135. package/dist/interaction_client/SilentCacheClient.mjs +61 -61
  136. package/dist/interaction_client/SilentCacheClient.mjs.map +1 -1
  137. package/dist/interaction_client/SilentIframeClient.d.ts +32 -32
  138. package/dist/interaction_client/SilentIframeClient.mjs +96 -96
  139. package/dist/interaction_client/SilentIframeClient.mjs.map +1 -1
  140. package/dist/interaction_client/SilentRefreshClient.d.ts +20 -20
  141. package/dist/interaction_client/SilentRefreshClient.d.ts.map +1 -1
  142. package/dist/interaction_client/SilentRefreshClient.mjs +47 -43
  143. package/dist/interaction_client/SilentRefreshClient.mjs.map +1 -1
  144. package/dist/interaction_client/StandardInteractionClient.d.ts +54 -54
  145. package/dist/interaction_client/StandardInteractionClient.mjs +222 -222
  146. package/dist/interaction_client/StandardInteractionClient.mjs.map +1 -1
  147. package/dist/interaction_handler/InteractionHandler.d.ts +33 -33
  148. package/dist/interaction_handler/InteractionHandler.mjs +93 -93
  149. package/dist/interaction_handler/InteractionHandler.mjs.map +1 -1
  150. package/dist/interaction_handler/RedirectHandler.d.ts +32 -32
  151. package/dist/interaction_handler/RedirectHandler.mjs +134 -134
  152. package/dist/interaction_handler/RedirectHandler.mjs.map +1 -1
  153. package/dist/interaction_handler/SilentHandler.d.ts +13 -13
  154. package/dist/interaction_handler/SilentHandler.mjs +133 -133
  155. package/dist/interaction_handler/SilentHandler.mjs.map +1 -1
  156. package/dist/naa/AccountInfo.d.ts +11 -11
  157. package/dist/naa/AuthBridge.d.ts +8 -5
  158. package/dist/naa/AuthBridge.d.ts.map +1 -1
  159. package/dist/naa/AuthResult.d.ts +7 -0
  160. package/dist/naa/AuthResult.d.ts.map +1 -0
  161. package/dist/naa/BridgeCapabilities.d.ts +3 -3
  162. package/dist/naa/BridgeError.d.ts +9 -9
  163. package/dist/naa/BridgeError.mjs +7 -7
  164. package/dist/naa/BridgeError.mjs.map +1 -1
  165. package/dist/naa/BridgeProxy.d.ts +68 -72
  166. package/dist/naa/BridgeProxy.d.ts.map +1 -1
  167. package/dist/naa/BridgeProxy.mjs +155 -152
  168. package/dist/naa/BridgeProxy.mjs.map +1 -1
  169. package/dist/naa/BridgeRequest.d.ts +7 -6
  170. package/dist/naa/BridgeRequest.d.ts.map +1 -1
  171. package/dist/naa/BridgeRequestEnvelope.d.ts +12 -13
  172. package/dist/naa/BridgeRequestEnvelope.d.ts.map +1 -1
  173. package/dist/naa/BridgeResponseEnvelope.d.ts +13 -10
  174. package/dist/naa/BridgeResponseEnvelope.d.ts.map +1 -1
  175. package/dist/naa/BridgeStatusCode.d.ts +11 -10
  176. package/dist/naa/BridgeStatusCode.d.ts.map +1 -1
  177. package/dist/naa/BridgeStatusCode.mjs +15 -16
  178. package/dist/naa/BridgeStatusCode.mjs.map +1 -1
  179. package/dist/naa/IBridgeProxy.d.ts +10 -12
  180. package/dist/naa/IBridgeProxy.d.ts.map +1 -1
  181. package/dist/naa/{InitializeBridgeResponse.d.ts → InitContext.d.ts} +7 -7
  182. package/dist/naa/InitContext.d.ts.map +1 -0
  183. package/dist/naa/TokenRequest.d.ts +18 -19
  184. package/dist/naa/TokenRequest.d.ts.map +1 -1
  185. package/dist/naa/TokenResponse.d.ts +13 -15
  186. package/dist/naa/TokenResponse.d.ts.map +1 -1
  187. package/dist/naa/mapping/NestedAppAuthAdapter.d.ts +23 -23
  188. package/dist/naa/mapping/NestedAppAuthAdapter.d.ts.map +1 -1
  189. package/dist/naa/mapping/NestedAppAuthAdapter.mjs +141 -141
  190. package/dist/naa/mapping/NestedAppAuthAdapter.mjs.map +1 -1
  191. package/dist/navigation/INavigationClient.d.ts +16 -16
  192. package/dist/navigation/NavigationClient.d.ts +22 -22
  193. package/dist/navigation/NavigationClient.mjs +40 -40
  194. package/dist/navigation/NavigationClient.mjs.map +1 -1
  195. package/dist/navigation/NavigationOptions.d.ts +12 -12
  196. package/dist/network/FetchClient.d.ts +26 -26
  197. package/dist/network/FetchClient.mjs +99 -99
  198. package/dist/network/FetchClient.mjs.map +1 -1
  199. package/dist/operatingcontext/BaseOperatingContext.d.ts +41 -40
  200. package/dist/operatingcontext/BaseOperatingContext.d.ts.map +1 -1
  201. package/dist/operatingcontext/BaseOperatingContext.mjs +96 -45
  202. package/dist/operatingcontext/BaseOperatingContext.mjs.map +1 -1
  203. package/dist/operatingcontext/StandardOperatingContext.d.ts +25 -25
  204. package/dist/operatingcontext/StandardOperatingContext.mjs +43 -43
  205. package/dist/operatingcontext/StandardOperatingContext.mjs.map +1 -1
  206. package/dist/operatingcontext/TeamsAppOperatingContext.d.ts +32 -32
  207. package/dist/operatingcontext/TeamsAppOperatingContext.mjs +85 -85
  208. package/dist/operatingcontext/TeamsAppOperatingContext.mjs.map +1 -1
  209. package/dist/operatingcontext/UnknownOperatingContext.d.ts +25 -25
  210. package/dist/operatingcontext/UnknownOperatingContext.mjs +42 -42
  211. package/dist/operatingcontext/UnknownOperatingContext.mjs.map +1 -1
  212. package/dist/packageMetadata.d.ts +2 -2
  213. package/dist/packageMetadata.d.ts.map +1 -1
  214. package/dist/packageMetadata.mjs +4 -4
  215. package/dist/packageMetadata.mjs.map +1 -1
  216. package/dist/request/AuthorizationCodeRequest.d.ts +8 -8
  217. package/dist/request/AuthorizationUrlRequest.d.ts +8 -8
  218. package/dist/request/ClearCacheRequest.d.ts +10 -10
  219. package/dist/request/EndSessionPopupRequest.d.ts +18 -18
  220. package/dist/request/EndSessionRequest.d.ts +15 -15
  221. package/dist/request/PopupRequest.d.ts +34 -34
  222. package/dist/request/PopupWindowAttributes.d.ts +15 -15
  223. package/dist/request/RedirectRequest.d.ts +35 -35
  224. package/dist/request/SilentRequest.d.ts +32 -32
  225. package/dist/request/SsoSilentRequest.d.ts +29 -29
  226. package/dist/response/AuthenticationResult.d.ts +4 -4
  227. package/dist/response/ResponseHandler.d.ts +7 -7
  228. package/dist/response/ResponseHandler.mjs +36 -36
  229. package/dist/response/ResponseHandler.mjs.map +1 -1
  230. package/dist/telemetry/BrowserPerformanceClient.d.ts +34 -36
  231. package/dist/telemetry/BrowserPerformanceClient.d.ts.map +1 -1
  232. package/dist/telemetry/BrowserPerformanceClient.mjs +163 -126
  233. package/dist/telemetry/BrowserPerformanceClient.mjs.map +1 -1
  234. package/dist/telemetry/BrowserPerformanceMeasurement.d.ts +21 -21
  235. package/dist/telemetry/BrowserPerformanceMeasurement.mjs +92 -92
  236. package/dist/telemetry/BrowserPerformanceMeasurement.mjs.map +1 -1
  237. package/dist/utils/BrowserConstants.d.ts +180 -176
  238. package/dist/utils/BrowserConstants.d.ts.map +1 -1
  239. package/dist/utils/BrowserConstants.mjs +213 -205
  240. package/dist/utils/BrowserConstants.mjs.map +1 -1
  241. package/dist/utils/BrowserProtocolUtils.d.ts +11 -11
  242. package/dist/utils/BrowserProtocolUtils.mjs +21 -21
  243. package/dist/utils/BrowserProtocolUtils.mjs.map +1 -1
  244. package/dist/utils/BrowserUtils.d.ts +56 -56
  245. package/dist/utils/BrowserUtils.mjs +125 -125
  246. package/dist/utils/BrowserUtils.mjs.map +1 -1
  247. package/lib/msal-browser.cjs +18304 -17929
  248. package/lib/msal-browser.cjs.map +1 -1
  249. package/lib/msal-browser.js +18304 -17929
  250. package/lib/msal-browser.js.map +1 -1
  251. package/lib/msal-browser.min.js +66 -68
  252. package/package.json +103 -102
  253. package/src/app/PublicClientApplication.ts +2 -1
  254. package/src/cache/BrowserCacheManager.ts +38 -23
  255. package/src/cache/DatabaseStorage.ts +1 -1
  256. package/src/cache/TokenCache.ts +34 -29
  257. package/src/config/Configuration.ts +1 -1
  258. package/src/controllers/ControllerFactory.ts +3 -5
  259. package/src/controllers/StandardController.ts +53 -26
  260. package/src/crypto/CryptoOps.ts +1 -1
  261. package/src/crypto/SignedHttpRequest.ts +1 -1
  262. package/src/index.ts +1 -0
  263. package/src/interaction_client/BaseInteractionClient.ts +2 -2
  264. package/src/interaction_client/NativeInteractionClient.ts +24 -20
  265. package/src/interaction_client/PopupClient.ts +1 -1
  266. package/src/interaction_client/RedirectClient.ts +3 -3
  267. package/src/interaction_client/SilentAuthCodeClient.ts +1 -1
  268. package/src/interaction_client/SilentRefreshClient.ts +8 -0
  269. package/src/interaction_client/StandardInteractionClient.ts +1 -1
  270. package/src/interaction_handler/SilentHandler.ts +2 -2
  271. package/src/naa/AuthBridge.ts +3 -2
  272. package/src/naa/AuthResult.ts +12 -0
  273. package/src/naa/BridgeProxy.ts +64 -71
  274. package/src/naa/BridgeRequest.ts +6 -2
  275. package/src/naa/BridgeRequestEnvelope.ts +1 -13
  276. package/src/naa/BridgeResponseEnvelope.ts +5 -7
  277. package/src/naa/BridgeStatusCode.ts +12 -10
  278. package/src/naa/IBridgeProxy.ts +3 -14
  279. package/src/naa/{InitializeBridgeResponse.ts → InitContext.ts} +1 -1
  280. package/src/naa/TokenRequest.ts +1 -2
  281. package/src/naa/TokenResponse.ts +1 -4
  282. package/src/naa/mapping/NestedAppAuthAdapter.ts +19 -19
  283. package/src/operatingcontext/BaseOperatingContext.ts +64 -7
  284. package/src/packageMetadata.ts +1 -1
  285. package/src/telemetry/BrowserPerformanceClient.ts +95 -42
  286. package/src/utils/BrowserConstants.ts +11 -0
  287. package/dist/naa/AccountRequests.d.ts +0 -10
  288. package/dist/naa/AccountRequests.d.ts.map +0 -1
  289. package/dist/naa/InitializeBridgeResponse.d.ts.map +0 -1
  290. package/src/naa/AccountRequests.ts +0 -16
@@ -1,6 +1,6 @@
1
- /*! @azure/msal-browser v3.5.1-beta.1 2023-11-14 */
1
+ /*! @azure/msal-browser v3.7.0 2024-01-09 */
2
2
  'use strict';
3
- import { PerformanceEvents, TimeUtils, ScopeSet, createClientAuthError, ClientAuthErrorCodes, AuthToken, AccountEntity, Constants, AuthorityType, AuthenticationScheme, PopTokenGenerator, CacheHelpers, CacheRecord, createAuthError, AuthErrorCodes, UrlString, OIDC_DEFAULT_SCOPES, invokeAsync, AADServerParamKeys, PromptValue } from '@azure/msal-common';
3
+ import { PerformanceEvents, TimeUtils, ScopeSet, createClientAuthError, ClientAuthErrorCodes, AuthToken, buildAccountToCache, AccountEntity, Constants, AuthorityType, AuthenticationScheme, PopTokenGenerator, updateAccountTenantProfileData, CacheHelpers, CacheRecord, createAuthError, AuthErrorCodes, UrlString, OIDC_DEFAULT_SCOPES, invokeAsync, AADServerParamKeys, PromptValue } from '@azure/msal-common';
4
4
  import { BaseInteractionClient } from './BaseInteractionClient.mjs';
5
5
  import { TemporaryCacheKeys, NativeConstants, NativeExtensionMethod, ApiId } from '../utils/BrowserConstants.mjs';
6
6
  import { NativeAuthError, isFatalNativeAuthError, createNativeAuthError } from '../error/NativeAuthError.mjs';
@@ -10,553 +10,545 @@ import { base64Decode } from '../encode/Base64Decode.mjs';
10
10
  import { userSwitch } from '../error/NativeAuthErrorCodes.mjs';
11
11
  import { nativePromptNotSupported } from '../error/BrowserAuthErrorCodes.mjs';
12
12
 
13
- /*
14
- * Copyright (c) Microsoft Corporation. All rights reserved.
15
- * Licensed under the MIT License.
16
- */
17
- const BrokerServerParamKeys = {
18
- BROKER_CLIENT_ID: "brk_client_id",
19
- BROKER_REDIRECT_URI: "brk_redirect_uri",
20
- };
21
- class NativeInteractionClient extends BaseInteractionClient {
22
- constructor(config, browserStorage, browserCrypto, logger, eventHandler, navigationClient, apiId, performanceClient, provider, accountId, nativeStorageImpl, correlationId) {
23
- super(config, browserStorage, browserCrypto, logger, eventHandler, navigationClient, performanceClient, provider, correlationId);
24
- this.apiId = apiId;
25
- this.accountId = accountId;
26
- this.nativeMessageHandler = provider;
27
- this.nativeStorageManager = nativeStorageImpl;
28
- this.silentCacheClient = new SilentCacheClient(config, this.nativeStorageManager, browserCrypto, logger, eventHandler, navigationClient, performanceClient, provider, correlationId);
29
- }
30
- /**
31
- * Acquire token from native platform via browser extension
32
- * @param request
33
- */
34
- async acquireToken(request) {
35
- this.performanceClient.addQueueMeasurement(PerformanceEvents.NativeInteractionClientAcquireToken, request.correlationId);
36
- this.logger.trace("NativeInteractionClient - acquireToken called.");
37
- // start the perf measurement
38
- const nativeATMeasurement = this.performanceClient.startMeasurement(PerformanceEvents.NativeInteractionClientAcquireToken, request.correlationId);
39
- const reqTimestamp = TimeUtils.nowSeconds();
40
- // initialize native request
41
- const nativeRequest = await this.initializeNativeRequest(request);
42
- // check if the tokens can be retrieved from internal cache
43
- try {
44
- const result = await this.acquireTokensFromCache(this.accountId, nativeRequest);
45
- nativeATMeasurement.end({
46
- success: true,
47
- isNativeBroker: false,
48
- fromCache: true,
49
- });
50
- return result;
51
- }
52
- catch (e) {
53
- // continue with a native call for any and all errors
54
- this.logger.info("MSAL internal Cache does not contain tokens, proceed to make a native call");
55
- }
56
- // fall back to native calls
57
- const messageBody = {
58
- method: NativeExtensionMethod.GetToken,
59
- request: nativeRequest,
60
- };
61
- const response = await this.nativeMessageHandler.sendMessage(messageBody);
62
- const validatedResponse = this.validateNativeResponse(response);
63
- return this.handleNativeResponse(validatedResponse, nativeRequest, reqTimestamp)
64
- .then((result) => {
65
- nativeATMeasurement.end({
66
- success: true,
67
- isNativeBroker: true,
68
- requestId: result.requestId,
69
- });
70
- return result;
71
- })
72
- .catch((error) => {
73
- nativeATMeasurement.end({
74
- success: false,
75
- errorCode: error.errorCode,
76
- subErrorCode: error.subError,
77
- isNativeBroker: true,
78
- });
79
- throw error;
80
- });
81
- }
82
- /**
83
- * Creates silent flow request
84
- * @param request
85
- * @param cachedAccount
86
- * @returns CommonSilentFlowRequest
87
- */
88
- createSilentCacheRequest(request, cachedAccount) {
89
- return {
90
- authority: request.authority,
91
- correlationId: this.correlationId,
92
- scopes: ScopeSet.fromString(request.scope).asArray(),
93
- account: cachedAccount,
94
- forceRefresh: false,
95
- };
96
- }
97
- /**
98
- * Fetches the tokens from the cache if un-expired
99
- * @param nativeAccountId
100
- * @param request
101
- * @returns authenticationResult
102
- */
103
- async acquireTokensFromCache(nativeAccountId, request) {
104
- if (!nativeAccountId) {
105
- this.logger.warning("NativeInteractionClient:acquireTokensFromCache - No nativeAccountId provided");
106
- throw createClientAuthError(ClientAuthErrorCodes.noAccountFound);
107
- }
108
- // fetch the account from browser cache
109
- const account = this.browserStorage.getBaseAccountInfo({
110
- nativeAccountId,
111
- });
112
- if (!account) {
113
- throw createClientAuthError(ClientAuthErrorCodes.noAccountFound);
114
- }
115
- // leverage silent flow for cached tokens retrieval
116
- try {
117
- const silentRequest = this.createSilentCacheRequest(request, account);
118
- const result = await this.silentCacheClient.acquireToken(silentRequest);
119
- const fullAccount = {
120
- ...account,
121
- idTokenClaims: result?.idTokenClaims,
122
- };
123
- return {
124
- ...result,
125
- account: fullAccount,
126
- };
127
- }
128
- catch (e) {
129
- throw e;
130
- }
131
- }
132
- /**
133
- * Acquires a token from native platform then redirects to the redirectUri instead of returning the response
134
- * @param request
135
- */
136
- async acquireTokenRedirect(request) {
137
- this.logger.trace("NativeInteractionClient - acquireTokenRedirect called.");
138
- const nativeRequest = await this.initializeNativeRequest(request);
139
- const messageBody = {
140
- method: NativeExtensionMethod.GetToken,
141
- request: nativeRequest,
142
- };
143
- try {
144
- const response = await this.nativeMessageHandler.sendMessage(messageBody);
145
- this.validateNativeResponse(response);
146
- }
147
- catch (e) {
148
- // Only throw fatal errors here to allow application to fallback to regular redirect. Otherwise proceed and the error will be thrown in handleRedirectPromise
149
- if (e instanceof NativeAuthError && isFatalNativeAuthError(e)) {
150
- throw e;
151
- }
152
- }
153
- this.browserStorage.setTemporaryCache(TemporaryCacheKeys.NATIVE_REQUEST, JSON.stringify(nativeRequest), true);
154
- const navigationOptions = {
155
- apiId: ApiId.acquireTokenRedirect,
156
- timeout: this.config.system.redirectNavigationTimeout,
157
- noHistory: false,
158
- };
159
- const redirectUri = this.config.auth.navigateToLoginRequestUrl
160
- ? window.location.href
161
- : this.getRedirectUri(request.redirectUri);
162
- await this.navigationClient.navigateExternal(redirectUri, navigationOptions); // Need to treat this as external to ensure handleRedirectPromise is run again
163
- }
164
- /**
165
- * If the previous page called native platform for a token using redirect APIs, send the same request again and return the response
166
- */
167
- async handleRedirectPromise() {
168
- this.logger.trace("NativeInteractionClient - handleRedirectPromise called.");
169
- if (!this.browserStorage.isInteractionInProgress(true)) {
170
- this.logger.info("handleRedirectPromise called but there is no interaction in progress, returning null.");
171
- return null;
172
- }
173
- // remove prompt from the request to prevent WAM from prompting twice
174
- const cachedRequest = this.browserStorage.getCachedNativeRequest();
175
- if (!cachedRequest) {
176
- this.logger.verbose("NativeInteractionClient - handleRedirectPromise called but there is no cached request, returning null.");
177
- return null;
178
- }
179
- const { prompt, ...request } = cachedRequest;
180
- if (prompt) {
181
- 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.");
182
- }
183
- this.browserStorage.removeItem(this.browserStorage.generateCacheKey(TemporaryCacheKeys.NATIVE_REQUEST));
184
- const messageBody = {
185
- method: NativeExtensionMethod.GetToken,
186
- request: request,
187
- };
188
- const reqTimestamp = TimeUtils.nowSeconds();
189
- try {
190
- this.logger.verbose("NativeInteractionClient - handleRedirectPromise sending message to native broker.");
191
- const response = await this.nativeMessageHandler.sendMessage(messageBody);
192
- this.validateNativeResponse(response);
193
- const result = this.handleNativeResponse(response, request, reqTimestamp);
194
- this.browserStorage.setInteractionInProgress(false);
195
- return result;
196
- }
197
- catch (e) {
198
- this.browserStorage.setInteractionInProgress(false);
199
- throw e;
200
- }
201
- }
202
- /**
203
- * Logout from native platform via browser extension
204
- * @param request
205
- */
206
- logout() {
207
- this.logger.trace("NativeInteractionClient - logout called.");
208
- return Promise.reject("Logout not implemented yet");
209
- }
210
- /**
211
- * Transform response from native platform into AuthenticationResult object which will be returned to the end user
212
- * @param response
213
- * @param request
214
- * @param reqTimestamp
215
- */
216
- async handleNativeResponse(response, request, reqTimestamp) {
217
- this.logger.trace("NativeInteractionClient - handleNativeResponse called.");
218
- if (response.account.id !== request.accountId) {
219
- // 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
220
- throw createNativeAuthError(userSwitch);
221
- }
222
- // Get the preferred_cache domain for the given authority
223
- const authority = await this.getDiscoveredAuthority(request.authority);
224
- // generate identifiers
225
- const idTokenClaims = AuthToken.extractTokenClaims(response.id_token, base64Decode);
226
- const homeAccountIdentifier = this.createHomeAccountIdentifier(response, idTokenClaims);
227
- const accountEntity = AccountEntity.createAccount({
228
- homeAccountId: homeAccountIdentifier,
229
- idTokenClaims: idTokenClaims,
230
- clientInfo: response.client_info,
231
- nativeAccountId: response.account.id,
232
- }, authority);
233
- // generate authenticationResult
234
- const result = await this.generateAuthenticationResult(response, request, idTokenClaims, accountEntity, authority.canonicalAuthority, reqTimestamp);
235
- // cache accounts and tokens in the appropriate storage
236
- this.cacheAccount(accountEntity);
237
- this.cacheNativeTokens(response, request, homeAccountIdentifier, idTokenClaims, result.accessToken, result.tenantId, reqTimestamp);
238
- return result;
239
- }
240
- /**
241
- * creates an homeAccountIdentifier for the account
242
- * @param response
243
- * @param idTokenObj
244
- * @returns
245
- */
246
- createHomeAccountIdentifier(response, idTokenClaims) {
247
- // Save account in browser storage
248
- const homeAccountIdentifier = AccountEntity.generateHomeAccountId(response.client_info || Constants.EMPTY_STRING, AuthorityType.Default, this.logger, this.browserCrypto, idTokenClaims);
249
- return homeAccountIdentifier;
250
- }
251
- /**
252
- * Helper to generate scopes
253
- * @param response
254
- * @param request
255
- * @returns
256
- */
257
- generateScopes(response, request) {
258
- return response.scope
259
- ? ScopeSet.fromString(response.scope)
260
- : ScopeSet.fromString(request.scope);
261
- }
262
- /**
263
- * If PoP token is requesred, records the PoP token if returned from the WAM, else generates one in the browser
264
- * @param request
265
- * @param response
266
- */
267
- async generatePopAccessToken(response, request) {
268
- if (request.tokenType === AuthenticationScheme.POP) {
269
- /**
270
- * This code prioritizes SHR returned from the native layer. In case of error/SHR not calculated from WAM and the AT
271
- * is still received, SHR is calculated locally
272
- */
273
- // Check if native layer returned an SHR token
274
- if (response.shr) {
275
- this.logger.trace("handleNativeServerResponse: SHR is enabled in native layer");
276
- return response.shr;
277
- }
278
- // Generate SHR in msal js if WAM does not compute it when POP is enabled
279
- const popTokenGenerator = new PopTokenGenerator(this.browserCrypto);
280
- const shrParameters = {
281
- resourceRequestMethod: request.resourceRequestMethod,
282
- resourceRequestUri: request.resourceRequestUri,
283
- shrClaims: request.shrClaims,
284
- shrNonce: request.shrNonce,
285
- };
286
- /**
287
- * KeyID must be present in the native request from when the PoP key was generated in order for
288
- * PopTokenGenerator to query the full key for signing
289
- */
290
- if (!request.keyId) {
291
- throw createClientAuthError(ClientAuthErrorCodes.keyIdMissing);
292
- }
293
- return await popTokenGenerator.signPopToken(response.access_token, request.keyId, shrParameters);
294
- }
295
- else {
296
- return response.access_token;
297
- }
298
- }
299
- /**
300
- * Generates authentication result
301
- * @param response
302
- * @param request
303
- * @param idTokenObj
304
- * @param accountEntity
305
- * @param authority
306
- * @param reqTimestamp
307
- * @returns
308
- */
309
- async generateAuthenticationResult(response, request, idTokenClaims, accountEntity, authority, reqTimestamp) {
310
- // Add Native Broker fields to Telemetry
311
- const mats = this.addTelemetryFromNativeResponse(response);
312
- // If scopes not returned in server response, use request scopes
313
- const responseScopes = response.scope
314
- ? ScopeSet.fromString(response.scope)
315
- : ScopeSet.fromString(request.scope);
316
- const accountProperties = response.account.properties || {};
317
- const uid = accountProperties["UID"] ||
318
- idTokenClaims.oid ||
319
- idTokenClaims.sub ||
320
- Constants.EMPTY_STRING;
321
- const tid = accountProperties["TenantId"] ||
322
- idTokenClaims.tid ||
323
- Constants.EMPTY_STRING;
324
- const fullAccountEntity = idTokenClaims
325
- ? Object.assign(new AccountEntity(), {
326
- ...accountEntity,
327
- idTokenClaims: idTokenClaims,
328
- })
329
- : accountEntity;
330
- const accountInfo = fullAccountEntity.getAccountInfo();
331
- // generate PoP token as needed
332
- const responseAccessToken = await this.generatePopAccessToken(response, request);
333
- const tokenType = request.tokenType === AuthenticationScheme.POP
334
- ? AuthenticationScheme.POP
335
- : AuthenticationScheme.BEARER;
336
- const result = {
337
- authority: authority,
338
- uniqueId: uid,
339
- tenantId: tid,
340
- scopes: responseScopes.asArray(),
341
- account: accountInfo,
342
- idToken: response.id_token,
343
- idTokenClaims: idTokenClaims,
344
- accessToken: responseAccessToken,
345
- fromCache: mats ? this.isResponseFromCache(mats) : false,
346
- expiresOn: new Date(Number(reqTimestamp + response.expires_in) * 1000),
347
- tokenType: tokenType,
348
- correlationId: this.correlationId,
349
- state: response.state,
350
- fromNativeBroker: true,
351
- };
352
- return result;
353
- }
354
- /**
355
- * cache the account entity in browser storage
356
- * @param accountEntity
357
- */
358
- cacheAccount(accountEntity) {
359
- // Store the account info and hence `nativeAccountId` in browser cache
360
- this.browserStorage.setAccount(accountEntity);
361
- // Remove any existing cached tokens for this account in browser storage
362
- this.browserStorage.removeAccountContext(accountEntity).catch((e) => {
363
- this.logger.error(`Error occurred while removing account context from browser storage. ${e}`);
364
- });
365
- }
366
- /**
367
- * Stores the access_token and id_token in inmemory storage
368
- * @param response
369
- * @param request
370
- * @param homeAccountIdentifier
371
- * @param idTokenObj
372
- * @param responseAccessToken
373
- * @param tenantId
374
- * @param reqTimestamp
375
- */
376
- cacheNativeTokens(response, request, homeAccountIdentifier, idTokenClaims, responseAccessToken, tenantId, reqTimestamp) {
377
- const cachedIdToken = CacheHelpers.createIdTokenEntity(homeAccountIdentifier, request.authority, response.id_token || "", request.clientId, idTokenClaims.tid || "");
378
- // cache accessToken in inmemory storage
379
- const expiresIn = request.tokenType === AuthenticationScheme.POP
380
- ? Constants.SHR_NONCE_VALIDITY
381
- : (typeof response.expires_in === "string"
382
- ? parseInt(response.expires_in, 10)
383
- : response.expires_in) || 0;
384
- const tokenExpirationSeconds = reqTimestamp + expiresIn;
385
- const responseScopes = this.generateScopes(response, request);
386
- const cachedAccessToken = CacheHelpers.createAccessTokenEntity(homeAccountIdentifier, request.authority, responseAccessToken, request.clientId, idTokenClaims.tid || tenantId, responseScopes.printScopes(), tokenExpirationSeconds, 0, base64Decode);
387
- const nativeCacheRecord = new CacheRecord(undefined, cachedIdToken, cachedAccessToken);
388
- void this.nativeStorageManager.saveCacheRecord(nativeCacheRecord, request.storeInCache);
389
- }
390
- addTelemetryFromNativeResponse(response) {
391
- const mats = this.getMATSFromResponse(response);
392
- if (!mats) {
393
- return null;
394
- }
395
- this.performanceClient.addFields({
396
- extensionId: this.nativeMessageHandler.getExtensionId(),
397
- extensionVersion: this.nativeMessageHandler.getExtensionVersion(),
398
- matsBrokerVersion: mats.broker_version,
399
- matsAccountJoinOnStart: mats.account_join_on_start,
400
- matsAccountJoinOnEnd: mats.account_join_on_end,
401
- matsDeviceJoin: mats.device_join,
402
- matsPromptBehavior: mats.prompt_behavior,
403
- matsApiErrorCode: mats.api_error_code,
404
- matsUiVisible: mats.ui_visible,
405
- matsSilentCode: mats.silent_code,
406
- matsSilentBiSubCode: mats.silent_bi_sub_code,
407
- matsSilentMessage: mats.silent_message,
408
- matsSilentStatus: mats.silent_status,
409
- matsHttpStatus: mats.http_status,
410
- matsHttpEventCount: mats.http_event_count,
411
- }, this.correlationId);
412
- return mats;
413
- }
414
- /**
415
- * Validates native platform response before processing
416
- * @param response
417
- */
418
- validateNativeResponse(response) {
419
- if (response.hasOwnProperty("access_token") &&
420
- response.hasOwnProperty("id_token") &&
421
- response.hasOwnProperty("client_info") &&
422
- response.hasOwnProperty("account") &&
423
- response.hasOwnProperty("scope") &&
424
- response.hasOwnProperty("expires_in")) {
425
- return response;
426
- }
427
- else {
428
- throw createAuthError(AuthErrorCodes.unexpectedError, "Response missing expected properties.");
429
- }
430
- }
431
- /**
432
- * Gets MATS telemetry from native response
433
- * @param response
434
- * @returns
435
- */
436
- getMATSFromResponse(response) {
437
- if (response.properties.MATS) {
438
- try {
439
- return JSON.parse(response.properties.MATS);
440
- }
441
- catch (e) {
442
- this.logger.error("NativeInteractionClient - Error parsing MATS telemetry, returning null instead");
443
- }
444
- }
445
- return null;
446
- }
447
- /**
448
- * Returns whether or not response came from native cache
449
- * @param response
450
- * @returns
451
- */
452
- isResponseFromCache(mats) {
453
- if (typeof mats.is_cached === "undefined") {
454
- this.logger.verbose("NativeInteractionClient - MATS telemetry does not contain field indicating if response was served from cache. Returning false.");
455
- return false;
456
- }
457
- return !!mats.is_cached;
458
- }
459
- /**
460
- * Translates developer provided request object into NativeRequest object
461
- * @param request
462
- */
463
- async initializeNativeRequest(request) {
464
- this.logger.trace("NativeInteractionClient - initializeNativeRequest called");
465
- const authority = request.authority || this.config.auth.authority;
466
- if (request.account) {
467
- await this.validateRequestAuthority(authority, request.account);
468
- }
469
- const canonicalAuthority = new UrlString(authority);
470
- canonicalAuthority.validateAsUri();
471
- // 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.
472
- const { scopes, ...remainingProperties } = request;
473
- const scopeSet = new ScopeSet(scopes || []);
474
- scopeSet.appendScopes(OIDC_DEFAULT_SCOPES);
475
- const getPrompt = () => {
476
- // If request is silent, prompt is always none
477
- switch (this.apiId) {
478
- case ApiId.ssoSilent:
479
- case ApiId.acquireTokenSilent_silentFlow:
480
- this.logger.trace("initializeNativeRequest: silent request sets prompt to none");
481
- return PromptValue.NONE;
482
- }
483
- // Prompt not provided, request may proceed and native broker decides if it needs to prompt
484
- if (!request.prompt) {
485
- this.logger.trace("initializeNativeRequest: prompt was not provided");
486
- return undefined;
487
- }
488
- // If request is interactive, check if prompt provided is allowed to go directly to native broker
489
- switch (request.prompt) {
490
- case PromptValue.NONE:
491
- case PromptValue.CONSENT:
492
- case PromptValue.LOGIN:
493
- this.logger.trace("initializeNativeRequest: prompt is compatible with native flow");
494
- return request.prompt;
495
- default:
496
- this.logger.trace(`initializeNativeRequest: prompt = ${request.prompt} is not compatible with native flow`);
497
- throw createBrowserAuthError(nativePromptNotSupported);
498
- }
499
- };
500
- const validatedRequest = {
501
- ...remainingProperties,
502
- accountId: this.accountId,
503
- clientId: this.config.auth.clientId,
504
- authority: canonicalAuthority.urlString,
505
- scope: scopeSet.printScopes(),
506
- redirectUri: this.getRedirectUri(request.redirectUri),
507
- prompt: getPrompt(),
508
- correlationId: this.correlationId,
509
- tokenType: request.authenticationScheme,
510
- windowTitleSubstring: document.title,
511
- extraParameters: {
512
- ...request.extraQueryParameters,
513
- ...request.tokenQueryParameters,
514
- },
515
- extendedExpiryToken: false, // Make this configurable?
516
- };
517
- this.handleExtraBrokerParams(validatedRequest);
518
- validatedRequest.extraParameters =
519
- validatedRequest.extraParameters || {};
520
- validatedRequest.extraParameters.telemetry =
521
- NativeConstants.MATS_TELEMETRY;
522
- if (request.authenticationScheme === AuthenticationScheme.POP) {
523
- // add POP request type
524
- const shrParameters = {
525
- resourceRequestUri: request.resourceRequestUri,
526
- resourceRequestMethod: request.resourceRequestMethod,
527
- shrClaims: request.shrClaims,
528
- shrNonce: request.shrNonce,
529
- };
530
- const popTokenGenerator = new PopTokenGenerator(this.browserCrypto);
531
- const reqCnfData = await invokeAsync(popTokenGenerator.generateCnf.bind(popTokenGenerator), PerformanceEvents.PopTokenGenerateCnf, this.logger, this.performanceClient, this.correlationId)(shrParameters, this.logger);
532
- // to reduce the URL length, it is recommended to send the hash of the req_cnf instead of the whole string
533
- validatedRequest.reqCnf = reqCnfData.reqCnfHash;
534
- validatedRequest.keyId = reqCnfData.kid;
535
- }
536
- return validatedRequest;
537
- }
538
- /**
539
- * Handles extra broker request parameters
540
- * @param request {NativeTokenRequest}
541
- * @private
542
- */
543
- handleExtraBrokerParams(request) {
544
- if (!request.extraParameters) {
545
- return;
546
- }
547
- if (request.extraParameters.hasOwnProperty(BrokerServerParamKeys.BROKER_CLIENT_ID) &&
548
- request.extraParameters.hasOwnProperty(BrokerServerParamKeys.BROKER_REDIRECT_URI) &&
549
- request.extraParameters.hasOwnProperty(AADServerParamKeys.CLIENT_ID)) {
550
- const child_client_id = request.extraParameters[AADServerParamKeys.CLIENT_ID];
551
- const child_redirect_uri = request.redirectUri;
552
- const brk_redirect_uri = request.extraParameters[BrokerServerParamKeys.BROKER_REDIRECT_URI];
553
- request.extraParameters = {
554
- child_client_id,
555
- child_redirect_uri,
556
- };
557
- request.redirectUri = brk_redirect_uri;
558
- }
559
- }
13
+ /*
14
+ * Copyright (c) Microsoft Corporation. All rights reserved.
15
+ * Licensed under the MIT License.
16
+ */
17
+ const BrokerServerParamKeys = {
18
+ BROKER_CLIENT_ID: "brk_client_id",
19
+ BROKER_REDIRECT_URI: "brk_redirect_uri",
20
+ };
21
+ class NativeInteractionClient extends BaseInteractionClient {
22
+ constructor(config, browserStorage, browserCrypto, logger, eventHandler, navigationClient, apiId, performanceClient, provider, accountId, nativeStorageImpl, correlationId) {
23
+ super(config, browserStorage, browserCrypto, logger, eventHandler, navigationClient, performanceClient, provider, correlationId);
24
+ this.apiId = apiId;
25
+ this.accountId = accountId;
26
+ this.nativeMessageHandler = provider;
27
+ this.nativeStorageManager = nativeStorageImpl;
28
+ this.silentCacheClient = new SilentCacheClient(config, this.nativeStorageManager, browserCrypto, logger, eventHandler, navigationClient, performanceClient, provider, correlationId);
29
+ }
30
+ /**
31
+ * Acquire token from native platform via browser extension
32
+ * @param request
33
+ */
34
+ async acquireToken(request) {
35
+ this.performanceClient.addQueueMeasurement(PerformanceEvents.NativeInteractionClientAcquireToken, request.correlationId);
36
+ this.logger.trace("NativeInteractionClient - acquireToken called.");
37
+ // start the perf measurement
38
+ const nativeATMeasurement = this.performanceClient.startMeasurement(PerformanceEvents.NativeInteractionClientAcquireToken, request.correlationId);
39
+ const reqTimestamp = TimeUtils.nowSeconds();
40
+ // initialize native request
41
+ const nativeRequest = await this.initializeNativeRequest(request);
42
+ // check if the tokens can be retrieved from internal cache
43
+ try {
44
+ const result = await this.acquireTokensFromCache(this.accountId, nativeRequest);
45
+ nativeATMeasurement.end({
46
+ success: true,
47
+ isNativeBroker: false,
48
+ fromCache: true,
49
+ });
50
+ return result;
51
+ }
52
+ catch (e) {
53
+ // continue with a native call for any and all errors
54
+ this.logger.info("MSAL internal Cache does not contain tokens, proceed to make a native call");
55
+ }
56
+ // fall back to native calls
57
+ const messageBody = {
58
+ method: NativeExtensionMethod.GetToken,
59
+ request: nativeRequest,
60
+ };
61
+ const response = await this.nativeMessageHandler.sendMessage(messageBody);
62
+ const validatedResponse = this.validateNativeResponse(response);
63
+ return this.handleNativeResponse(validatedResponse, nativeRequest, reqTimestamp)
64
+ .then((result) => {
65
+ nativeATMeasurement.end({
66
+ success: true,
67
+ isNativeBroker: true,
68
+ requestId: result.requestId,
69
+ });
70
+ return result;
71
+ })
72
+ .catch((error) => {
73
+ nativeATMeasurement.end({
74
+ success: false,
75
+ errorCode: error.errorCode,
76
+ subErrorCode: error.subError,
77
+ isNativeBroker: true,
78
+ });
79
+ throw error;
80
+ });
81
+ }
82
+ /**
83
+ * Creates silent flow request
84
+ * @param request
85
+ * @param cachedAccount
86
+ * @returns CommonSilentFlowRequest
87
+ */
88
+ createSilentCacheRequest(request, cachedAccount) {
89
+ return {
90
+ authority: request.authority,
91
+ correlationId: this.correlationId,
92
+ scopes: ScopeSet.fromString(request.scope).asArray(),
93
+ account: cachedAccount,
94
+ forceRefresh: false,
95
+ };
96
+ }
97
+ /**
98
+ * Fetches the tokens from the cache if un-expired
99
+ * @param nativeAccountId
100
+ * @param request
101
+ * @returns authenticationResult
102
+ */
103
+ async acquireTokensFromCache(nativeAccountId, request) {
104
+ if (!nativeAccountId) {
105
+ this.logger.warning("NativeInteractionClient:acquireTokensFromCache - No nativeAccountId provided");
106
+ throw createClientAuthError(ClientAuthErrorCodes.noAccountFound);
107
+ }
108
+ // fetch the account from browser cache
109
+ const account = this.browserStorage.getBaseAccountInfo({
110
+ nativeAccountId,
111
+ });
112
+ if (!account) {
113
+ throw createClientAuthError(ClientAuthErrorCodes.noAccountFound);
114
+ }
115
+ // leverage silent flow for cached tokens retrieval
116
+ try {
117
+ const silentRequest = this.createSilentCacheRequest(request, account);
118
+ const result = await this.silentCacheClient.acquireToken(silentRequest);
119
+ const fullAccount = {
120
+ ...account,
121
+ idTokenClaims: result?.idTokenClaims,
122
+ };
123
+ return {
124
+ ...result,
125
+ account: fullAccount,
126
+ };
127
+ }
128
+ catch (e) {
129
+ throw e;
130
+ }
131
+ }
132
+ /**
133
+ * Acquires a token from native platform then redirects to the redirectUri instead of returning the response
134
+ * @param request
135
+ */
136
+ async acquireTokenRedirect(request) {
137
+ this.logger.trace("NativeInteractionClient - acquireTokenRedirect called.");
138
+ const nativeRequest = await this.initializeNativeRequest(request);
139
+ const messageBody = {
140
+ method: NativeExtensionMethod.GetToken,
141
+ request: nativeRequest,
142
+ };
143
+ try {
144
+ const response = await this.nativeMessageHandler.sendMessage(messageBody);
145
+ this.validateNativeResponse(response);
146
+ }
147
+ catch (e) {
148
+ // Only throw fatal errors here to allow application to fallback to regular redirect. Otherwise proceed and the error will be thrown in handleRedirectPromise
149
+ if (e instanceof NativeAuthError && isFatalNativeAuthError(e)) {
150
+ throw e;
151
+ }
152
+ }
153
+ this.browserStorage.setTemporaryCache(TemporaryCacheKeys.NATIVE_REQUEST, JSON.stringify(nativeRequest), true);
154
+ const navigationOptions = {
155
+ apiId: ApiId.acquireTokenRedirect,
156
+ timeout: this.config.system.redirectNavigationTimeout,
157
+ noHistory: false,
158
+ };
159
+ const redirectUri = this.config.auth.navigateToLoginRequestUrl
160
+ ? window.location.href
161
+ : this.getRedirectUri(request.redirectUri);
162
+ await this.navigationClient.navigateExternal(redirectUri, navigationOptions); // Need to treat this as external to ensure handleRedirectPromise is run again
163
+ }
164
+ /**
165
+ * If the previous page called native platform for a token using redirect APIs, send the same request again and return the response
166
+ */
167
+ async handleRedirectPromise() {
168
+ this.logger.trace("NativeInteractionClient - handleRedirectPromise called.");
169
+ if (!this.browserStorage.isInteractionInProgress(true)) {
170
+ this.logger.info("handleRedirectPromise called but there is no interaction in progress, returning null.");
171
+ return null;
172
+ }
173
+ // remove prompt from the request to prevent WAM from prompting twice
174
+ const cachedRequest = this.browserStorage.getCachedNativeRequest();
175
+ if (!cachedRequest) {
176
+ this.logger.verbose("NativeInteractionClient - handleRedirectPromise called but there is no cached request, returning null.");
177
+ return null;
178
+ }
179
+ const { prompt, ...request } = cachedRequest;
180
+ if (prompt) {
181
+ 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.");
182
+ }
183
+ this.browserStorage.removeItem(this.browserStorage.generateCacheKey(TemporaryCacheKeys.NATIVE_REQUEST));
184
+ const messageBody = {
185
+ method: NativeExtensionMethod.GetToken,
186
+ request: request,
187
+ };
188
+ const reqTimestamp = TimeUtils.nowSeconds();
189
+ try {
190
+ this.logger.verbose("NativeInteractionClient - handleRedirectPromise sending message to native broker.");
191
+ const response = await this.nativeMessageHandler.sendMessage(messageBody);
192
+ this.validateNativeResponse(response);
193
+ const result = this.handleNativeResponse(response, request, reqTimestamp);
194
+ this.browserStorage.setInteractionInProgress(false);
195
+ return await result;
196
+ }
197
+ catch (e) {
198
+ this.browserStorage.setInteractionInProgress(false);
199
+ throw e;
200
+ }
201
+ }
202
+ /**
203
+ * Logout from native platform via browser extension
204
+ * @param request
205
+ */
206
+ logout() {
207
+ this.logger.trace("NativeInteractionClient - logout called.");
208
+ return Promise.reject("Logout not implemented yet");
209
+ }
210
+ /**
211
+ * Transform response from native platform into AuthenticationResult object which will be returned to the end user
212
+ * @param response
213
+ * @param request
214
+ * @param reqTimestamp
215
+ */
216
+ async handleNativeResponse(response, request, reqTimestamp) {
217
+ this.logger.trace("NativeInteractionClient - handleNativeResponse called.");
218
+ if (response.account.id !== request.accountId) {
219
+ // 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
220
+ throw createNativeAuthError(userSwitch);
221
+ }
222
+ // Get the preferred_cache domain for the given authority
223
+ const authority = await this.getDiscoveredAuthority(request.authority);
224
+ // generate identifiers
225
+ const idTokenClaims = AuthToken.extractTokenClaims(response.id_token, base64Decode);
226
+ const homeAccountIdentifier = this.createHomeAccountIdentifier(response, idTokenClaims);
227
+ const baseAccount = buildAccountToCache(this.browserStorage, authority, homeAccountIdentifier, idTokenClaims, base64Decode, response.client_info, undefined, // environment
228
+ idTokenClaims.tid, undefined, // auth code payload
229
+ response.account.id, this.logger);
230
+ // generate authenticationResult
231
+ const result = await this.generateAuthenticationResult(response, request, idTokenClaims, baseAccount, authority.canonicalAuthority, reqTimestamp);
232
+ // cache accounts and tokens in the appropriate storage
233
+ this.cacheAccount(baseAccount);
234
+ this.cacheNativeTokens(response, request, homeAccountIdentifier, idTokenClaims, result.accessToken, result.tenantId, reqTimestamp);
235
+ return result;
236
+ }
237
+ /**
238
+ * creates an homeAccountIdentifier for the account
239
+ * @param response
240
+ * @param idTokenObj
241
+ * @returns
242
+ */
243
+ createHomeAccountIdentifier(response, idTokenClaims) {
244
+ // Save account in browser storage
245
+ const homeAccountIdentifier = AccountEntity.generateHomeAccountId(response.client_info || Constants.EMPTY_STRING, AuthorityType.Default, this.logger, this.browserCrypto, idTokenClaims);
246
+ return homeAccountIdentifier;
247
+ }
248
+ /**
249
+ * Helper to generate scopes
250
+ * @param response
251
+ * @param request
252
+ * @returns
253
+ */
254
+ generateScopes(response, request) {
255
+ return response.scope
256
+ ? ScopeSet.fromString(response.scope)
257
+ : ScopeSet.fromString(request.scope);
258
+ }
259
+ /**
260
+ * If PoP token is requesred, records the PoP token if returned from the WAM, else generates one in the browser
261
+ * @param request
262
+ * @param response
263
+ */
264
+ async generatePopAccessToken(response, request) {
265
+ if (request.tokenType === AuthenticationScheme.POP) {
266
+ /**
267
+ * This code prioritizes SHR returned from the native layer. In case of error/SHR not calculated from WAM and the AT
268
+ * is still received, SHR is calculated locally
269
+ */
270
+ // Check if native layer returned an SHR token
271
+ if (response.shr) {
272
+ this.logger.trace("handleNativeServerResponse: SHR is enabled in native layer");
273
+ return response.shr;
274
+ }
275
+ // Generate SHR in msal js if WAM does not compute it when POP is enabled
276
+ const popTokenGenerator = new PopTokenGenerator(this.browserCrypto);
277
+ const shrParameters = {
278
+ resourceRequestMethod: request.resourceRequestMethod,
279
+ resourceRequestUri: request.resourceRequestUri,
280
+ shrClaims: request.shrClaims,
281
+ shrNonce: request.shrNonce,
282
+ };
283
+ /**
284
+ * KeyID must be present in the native request from when the PoP key was generated in order for
285
+ * PopTokenGenerator to query the full key for signing
286
+ */
287
+ if (!request.keyId) {
288
+ throw createClientAuthError(ClientAuthErrorCodes.keyIdMissing);
289
+ }
290
+ return popTokenGenerator.signPopToken(response.access_token, request.keyId, shrParameters);
291
+ }
292
+ else {
293
+ return response.access_token;
294
+ }
295
+ }
296
+ /**
297
+ * Generates authentication result
298
+ * @param response
299
+ * @param request
300
+ * @param idTokenObj
301
+ * @param accountEntity
302
+ * @param authority
303
+ * @param reqTimestamp
304
+ * @returns
305
+ */
306
+ async generateAuthenticationResult(response, request, idTokenClaims, accountEntity, authority, reqTimestamp) {
307
+ // Add Native Broker fields to Telemetry
308
+ const mats = this.addTelemetryFromNativeResponse(response);
309
+ // If scopes not returned in server response, use request scopes
310
+ const responseScopes = response.scope
311
+ ? ScopeSet.fromString(response.scope)
312
+ : ScopeSet.fromString(request.scope);
313
+ const accountProperties = response.account.properties || {};
314
+ const uid = accountProperties["UID"] ||
315
+ idTokenClaims.oid ||
316
+ idTokenClaims.sub ||
317
+ Constants.EMPTY_STRING;
318
+ const tid = accountProperties["TenantId"] ||
319
+ idTokenClaims.tid ||
320
+ Constants.EMPTY_STRING;
321
+ const accountInfo = updateAccountTenantProfileData(accountEntity.getAccountInfo(), undefined, // tenantProfile optional
322
+ idTokenClaims);
323
+ // generate PoP token as needed
324
+ const responseAccessToken = await this.generatePopAccessToken(response, request);
325
+ const tokenType = request.tokenType === AuthenticationScheme.POP
326
+ ? AuthenticationScheme.POP
327
+ : AuthenticationScheme.BEARER;
328
+ const result = {
329
+ authority: authority,
330
+ uniqueId: uid,
331
+ tenantId: tid,
332
+ scopes: responseScopes.asArray(),
333
+ account: accountInfo,
334
+ idToken: response.id_token,
335
+ idTokenClaims: idTokenClaims,
336
+ accessToken: responseAccessToken,
337
+ fromCache: mats ? this.isResponseFromCache(mats) : false,
338
+ expiresOn: new Date(Number(reqTimestamp + response.expires_in) * 1000),
339
+ tokenType: tokenType,
340
+ correlationId: this.correlationId,
341
+ state: response.state,
342
+ fromNativeBroker: true,
343
+ };
344
+ return result;
345
+ }
346
+ /**
347
+ * cache the account entity in browser storage
348
+ * @param accountEntity
349
+ */
350
+ cacheAccount(accountEntity) {
351
+ // Store the account info and hence `nativeAccountId` in browser cache
352
+ this.browserStorage.setAccount(accountEntity);
353
+ // Remove any existing cached tokens for this account in browser storage
354
+ this.browserStorage.removeAccountContext(accountEntity).catch((e) => {
355
+ this.logger.error(`Error occurred while removing account context from browser storage. ${e}`);
356
+ });
357
+ }
358
+ /**
359
+ * Stores the access_token and id_token in inmemory storage
360
+ * @param response
361
+ * @param request
362
+ * @param homeAccountIdentifier
363
+ * @param idTokenObj
364
+ * @param responseAccessToken
365
+ * @param tenantId
366
+ * @param reqTimestamp
367
+ */
368
+ cacheNativeTokens(response, request, homeAccountIdentifier, idTokenClaims, responseAccessToken, tenantId, reqTimestamp) {
369
+ const cachedIdToken = CacheHelpers.createIdTokenEntity(homeAccountIdentifier, request.authority, response.id_token || "", request.clientId, idTokenClaims.tid || "");
370
+ // cache accessToken in inmemory storage
371
+ const expiresIn = request.tokenType === AuthenticationScheme.POP
372
+ ? Constants.SHR_NONCE_VALIDITY
373
+ : (typeof response.expires_in === "string"
374
+ ? parseInt(response.expires_in, 10)
375
+ : response.expires_in) || 0;
376
+ const tokenExpirationSeconds = reqTimestamp + expiresIn;
377
+ const responseScopes = this.generateScopes(response, request);
378
+ const cachedAccessToken = CacheHelpers.createAccessTokenEntity(homeAccountIdentifier, request.authority, responseAccessToken, request.clientId, idTokenClaims.tid || tenantId, responseScopes.printScopes(), tokenExpirationSeconds, 0, base64Decode);
379
+ const nativeCacheRecord = new CacheRecord(undefined, cachedIdToken, cachedAccessToken);
380
+ void this.nativeStorageManager.saveCacheRecord(nativeCacheRecord, request.storeInCache);
381
+ }
382
+ addTelemetryFromNativeResponse(response) {
383
+ const mats = this.getMATSFromResponse(response);
384
+ if (!mats) {
385
+ return null;
386
+ }
387
+ this.performanceClient.addFields({
388
+ extensionId: this.nativeMessageHandler.getExtensionId(),
389
+ extensionVersion: this.nativeMessageHandler.getExtensionVersion(),
390
+ matsBrokerVersion: mats.broker_version,
391
+ matsAccountJoinOnStart: mats.account_join_on_start,
392
+ matsAccountJoinOnEnd: mats.account_join_on_end,
393
+ matsDeviceJoin: mats.device_join,
394
+ matsPromptBehavior: mats.prompt_behavior,
395
+ matsApiErrorCode: mats.api_error_code,
396
+ matsUiVisible: mats.ui_visible,
397
+ matsSilentCode: mats.silent_code,
398
+ matsSilentBiSubCode: mats.silent_bi_sub_code,
399
+ matsSilentMessage: mats.silent_message,
400
+ matsSilentStatus: mats.silent_status,
401
+ matsHttpStatus: mats.http_status,
402
+ matsHttpEventCount: mats.http_event_count,
403
+ }, this.correlationId);
404
+ return mats;
405
+ }
406
+ /**
407
+ * Validates native platform response before processing
408
+ * @param response
409
+ */
410
+ validateNativeResponse(response) {
411
+ if (response.hasOwnProperty("access_token") &&
412
+ response.hasOwnProperty("id_token") &&
413
+ response.hasOwnProperty("client_info") &&
414
+ response.hasOwnProperty("account") &&
415
+ response.hasOwnProperty("scope") &&
416
+ response.hasOwnProperty("expires_in")) {
417
+ return response;
418
+ }
419
+ else {
420
+ throw createAuthError(AuthErrorCodes.unexpectedError, "Response missing expected properties.");
421
+ }
422
+ }
423
+ /**
424
+ * Gets MATS telemetry from native response
425
+ * @param response
426
+ * @returns
427
+ */
428
+ getMATSFromResponse(response) {
429
+ if (response.properties.MATS) {
430
+ try {
431
+ return JSON.parse(response.properties.MATS);
432
+ }
433
+ catch (e) {
434
+ this.logger.error("NativeInteractionClient - Error parsing MATS telemetry, returning null instead");
435
+ }
436
+ }
437
+ return null;
438
+ }
439
+ /**
440
+ * Returns whether or not response came from native cache
441
+ * @param response
442
+ * @returns
443
+ */
444
+ isResponseFromCache(mats) {
445
+ if (typeof mats.is_cached === "undefined") {
446
+ this.logger.verbose("NativeInteractionClient - MATS telemetry does not contain field indicating if response was served from cache. Returning false.");
447
+ return false;
448
+ }
449
+ return !!mats.is_cached;
450
+ }
451
+ /**
452
+ * Translates developer provided request object into NativeRequest object
453
+ * @param request
454
+ */
455
+ async initializeNativeRequest(request) {
456
+ this.logger.trace("NativeInteractionClient - initializeNativeRequest called");
457
+ const authority = request.authority || this.config.auth.authority;
458
+ if (request.account) {
459
+ await this.validateRequestAuthority(authority, request.account);
460
+ }
461
+ const canonicalAuthority = new UrlString(authority);
462
+ canonicalAuthority.validateAsUri();
463
+ // 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.
464
+ const { scopes, ...remainingProperties } = request;
465
+ const scopeSet = new ScopeSet(scopes || []);
466
+ scopeSet.appendScopes(OIDC_DEFAULT_SCOPES);
467
+ const getPrompt = () => {
468
+ // If request is silent, prompt is always none
469
+ switch (this.apiId) {
470
+ case ApiId.ssoSilent:
471
+ case ApiId.acquireTokenSilent_silentFlow:
472
+ this.logger.trace("initializeNativeRequest: silent request sets prompt to none");
473
+ return PromptValue.NONE;
474
+ }
475
+ // Prompt not provided, request may proceed and native broker decides if it needs to prompt
476
+ if (!request.prompt) {
477
+ this.logger.trace("initializeNativeRequest: prompt was not provided");
478
+ return undefined;
479
+ }
480
+ // If request is interactive, check if prompt provided is allowed to go directly to native broker
481
+ switch (request.prompt) {
482
+ case PromptValue.NONE:
483
+ case PromptValue.CONSENT:
484
+ case PromptValue.LOGIN:
485
+ this.logger.trace("initializeNativeRequest: prompt is compatible with native flow");
486
+ return request.prompt;
487
+ default:
488
+ this.logger.trace(`initializeNativeRequest: prompt = ${request.prompt} is not compatible with native flow`);
489
+ throw createBrowserAuthError(nativePromptNotSupported);
490
+ }
491
+ };
492
+ const validatedRequest = {
493
+ ...remainingProperties,
494
+ accountId: this.accountId,
495
+ clientId: this.config.auth.clientId,
496
+ authority: canonicalAuthority.urlString,
497
+ scope: scopeSet.printScopes(),
498
+ redirectUri: this.getRedirectUri(request.redirectUri),
499
+ prompt: getPrompt(),
500
+ correlationId: this.correlationId,
501
+ tokenType: request.authenticationScheme,
502
+ windowTitleSubstring: document.title,
503
+ extraParameters: {
504
+ ...request.extraQueryParameters,
505
+ ...request.tokenQueryParameters,
506
+ },
507
+ extendedExpiryToken: false, // Make this configurable?
508
+ };
509
+ this.handleExtraBrokerParams(validatedRequest);
510
+ validatedRequest.extraParameters =
511
+ validatedRequest.extraParameters || {};
512
+ validatedRequest.extraParameters.telemetry =
513
+ NativeConstants.MATS_TELEMETRY;
514
+ if (request.authenticationScheme === AuthenticationScheme.POP) {
515
+ // add POP request type
516
+ const shrParameters = {
517
+ resourceRequestUri: request.resourceRequestUri,
518
+ resourceRequestMethod: request.resourceRequestMethod,
519
+ shrClaims: request.shrClaims,
520
+ shrNonce: request.shrNonce,
521
+ };
522
+ const popTokenGenerator = new PopTokenGenerator(this.browserCrypto);
523
+ const reqCnfData = await invokeAsync(popTokenGenerator.generateCnf.bind(popTokenGenerator), PerformanceEvents.PopTokenGenerateCnf, this.logger, this.performanceClient, this.correlationId)(shrParameters, this.logger);
524
+ // to reduce the URL length, it is recommended to send the hash of the req_cnf instead of the whole string
525
+ validatedRequest.reqCnf = reqCnfData.reqCnfHash;
526
+ validatedRequest.keyId = reqCnfData.kid;
527
+ }
528
+ return validatedRequest;
529
+ }
530
+ /**
531
+ * Handles extra broker request parameters
532
+ * @param request {NativeTokenRequest}
533
+ * @private
534
+ */
535
+ handleExtraBrokerParams(request) {
536
+ if (!request.extraParameters) {
537
+ return;
538
+ }
539
+ if (request.extraParameters.hasOwnProperty(BrokerServerParamKeys.BROKER_CLIENT_ID) &&
540
+ request.extraParameters.hasOwnProperty(BrokerServerParamKeys.BROKER_REDIRECT_URI) &&
541
+ request.extraParameters.hasOwnProperty(AADServerParamKeys.CLIENT_ID)) {
542
+ const child_client_id = request.extraParameters[AADServerParamKeys.CLIENT_ID];
543
+ const child_redirect_uri = request.redirectUri;
544
+ const brk_redirect_uri = request.extraParameters[BrokerServerParamKeys.BROKER_REDIRECT_URI];
545
+ request.extraParameters = {
546
+ child_client_id,
547
+ child_redirect_uri,
548
+ };
549
+ request.redirectUri = brk_redirect_uri;
550
+ }
551
+ }
560
552
  }
561
553
 
562
554
  export { NativeInteractionClient };