@azure/msal-browser 3.5.1-beta.0 → 3.6.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 (257) 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 +1282 -1262
  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 +221 -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 +1291 -1293
  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 +539 -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.mjs +43 -43
  142. package/dist/interaction_client/SilentRefreshClient.mjs.map +1 -1
  143. package/dist/interaction_client/StandardInteractionClient.d.ts +54 -54
  144. package/dist/interaction_client/StandardInteractionClient.mjs +222 -222
  145. package/dist/interaction_client/StandardInteractionClient.mjs.map +1 -1
  146. package/dist/interaction_handler/InteractionHandler.d.ts +33 -33
  147. package/dist/interaction_handler/InteractionHandler.mjs +93 -93
  148. package/dist/interaction_handler/InteractionHandler.mjs.map +1 -1
  149. package/dist/interaction_handler/RedirectHandler.d.ts +32 -32
  150. package/dist/interaction_handler/RedirectHandler.mjs +134 -134
  151. package/dist/interaction_handler/RedirectHandler.mjs.map +1 -1
  152. package/dist/interaction_handler/SilentHandler.d.ts +13 -13
  153. package/dist/interaction_handler/SilentHandler.mjs +133 -133
  154. package/dist/interaction_handler/SilentHandler.mjs.map +1 -1
  155. package/dist/naa/AccountInfo.d.ts +11 -11
  156. package/dist/naa/AccountRequests.d.ts +9 -9
  157. package/dist/naa/AuthBridge.d.ts +8 -5
  158. package/dist/naa/AuthBridge.d.ts.map +1 -1
  159. package/dist/naa/BridgeCapabilities.d.ts +3 -3
  160. package/dist/naa/BridgeError.d.ts +9 -9
  161. package/dist/naa/BridgeError.mjs +7 -7
  162. package/dist/naa/BridgeError.mjs.map +1 -1
  163. package/dist/naa/BridgeProxy.d.ts +72 -72
  164. package/dist/naa/BridgeProxy.d.ts.map +1 -1
  165. package/dist/naa/BridgeProxy.mjs +153 -152
  166. package/dist/naa/BridgeProxy.mjs.map +1 -1
  167. package/dist/naa/BridgeRequest.d.ts +6 -6
  168. package/dist/naa/BridgeRequestEnvelope.d.ts +13 -13
  169. package/dist/naa/BridgeResponseEnvelope.d.ts +10 -10
  170. package/dist/naa/BridgeStatusCode.d.ts +10 -10
  171. package/dist/naa/BridgeStatusCode.mjs +15 -15
  172. package/dist/naa/BridgeStatusCode.mjs.map +1 -1
  173. package/dist/naa/IBridgeProxy.d.ts +12 -12
  174. package/dist/naa/InitializeBridgeResponse.d.ts +6 -6
  175. package/dist/naa/TokenRequest.d.ts +19 -19
  176. package/dist/naa/TokenResponse.d.ts +15 -15
  177. package/dist/naa/mapping/NestedAppAuthAdapter.d.ts +23 -23
  178. package/dist/naa/mapping/NestedAppAuthAdapter.mjs +141 -141
  179. package/dist/naa/mapping/NestedAppAuthAdapter.mjs.map +1 -1
  180. package/dist/navigation/INavigationClient.d.ts +16 -16
  181. package/dist/navigation/NavigationClient.d.ts +22 -22
  182. package/dist/navigation/NavigationClient.mjs +40 -40
  183. package/dist/navigation/NavigationClient.mjs.map +1 -1
  184. package/dist/navigation/NavigationOptions.d.ts +12 -12
  185. package/dist/network/FetchClient.d.ts +26 -26
  186. package/dist/network/FetchClient.mjs +99 -99
  187. package/dist/network/FetchClient.mjs.map +1 -1
  188. package/dist/operatingcontext/BaseOperatingContext.d.ts +40 -40
  189. package/dist/operatingcontext/BaseOperatingContext.mjs +44 -44
  190. package/dist/operatingcontext/BaseOperatingContext.mjs.map +1 -1
  191. package/dist/operatingcontext/StandardOperatingContext.d.ts +25 -25
  192. package/dist/operatingcontext/StandardOperatingContext.mjs +43 -43
  193. package/dist/operatingcontext/StandardOperatingContext.mjs.map +1 -1
  194. package/dist/operatingcontext/TeamsAppOperatingContext.d.ts +32 -32
  195. package/dist/operatingcontext/TeamsAppOperatingContext.mjs +85 -85
  196. package/dist/operatingcontext/TeamsAppOperatingContext.mjs.map +1 -1
  197. package/dist/operatingcontext/UnknownOperatingContext.d.ts +25 -25
  198. package/dist/operatingcontext/UnknownOperatingContext.mjs +42 -42
  199. package/dist/operatingcontext/UnknownOperatingContext.mjs.map +1 -1
  200. package/dist/packageMetadata.d.ts +2 -2
  201. package/dist/packageMetadata.mjs +4 -4
  202. package/dist/packageMetadata.mjs.map +1 -1
  203. package/dist/request/AuthorizationCodeRequest.d.ts +8 -8
  204. package/dist/request/AuthorizationUrlRequest.d.ts +8 -8
  205. package/dist/request/ClearCacheRequest.d.ts +10 -10
  206. package/dist/request/EndSessionPopupRequest.d.ts +18 -18
  207. package/dist/request/EndSessionRequest.d.ts +15 -15
  208. package/dist/request/PopupRequest.d.ts +34 -34
  209. package/dist/request/PopupWindowAttributes.d.ts +15 -15
  210. package/dist/request/RedirectRequest.d.ts +35 -35
  211. package/dist/request/SilentRequest.d.ts +32 -32
  212. package/dist/request/SsoSilentRequest.d.ts +29 -29
  213. package/dist/response/AuthenticationResult.d.ts +4 -4
  214. package/dist/response/ResponseHandler.d.ts +7 -7
  215. package/dist/response/ResponseHandler.mjs +36 -36
  216. package/dist/response/ResponseHandler.mjs.map +1 -1
  217. package/dist/telemetry/BrowserPerformanceClient.d.ts +36 -36
  218. package/dist/telemetry/BrowserPerformanceClient.mjs +125 -125
  219. package/dist/telemetry/BrowserPerformanceClient.mjs.map +1 -1
  220. package/dist/telemetry/BrowserPerformanceMeasurement.d.ts +21 -21
  221. package/dist/telemetry/BrowserPerformanceMeasurement.mjs +92 -92
  222. package/dist/telemetry/BrowserPerformanceMeasurement.mjs.map +1 -1
  223. package/dist/utils/BrowserConstants.d.ts +176 -176
  224. package/dist/utils/BrowserConstants.mjs +204 -204
  225. package/dist/utils/BrowserConstants.mjs.map +1 -1
  226. package/dist/utils/BrowserProtocolUtils.d.ts +11 -11
  227. package/dist/utils/BrowserProtocolUtils.mjs +21 -21
  228. package/dist/utils/BrowserProtocolUtils.mjs.map +1 -1
  229. package/dist/utils/BrowserUtils.d.ts +56 -56
  230. package/dist/utils/BrowserUtils.mjs +125 -125
  231. package/dist/utils/BrowserUtils.mjs.map +1 -1
  232. package/lib/msal-browser.cjs +18217 -17928
  233. package/lib/msal-browser.cjs.map +1 -1
  234. package/lib/msal-browser.js +18217 -17928
  235. package/lib/msal-browser.js.map +1 -1
  236. package/lib/msal-browser.min.js +71 -68
  237. package/package.json +103 -102
  238. package/src/app/PublicClientApplication.ts +2 -1
  239. package/src/cache/BrowserCacheManager.ts +31 -4
  240. package/src/cache/DatabaseStorage.ts +1 -1
  241. package/src/cache/TokenCache.ts +33 -29
  242. package/src/config/Configuration.ts +1 -1
  243. package/src/controllers/ControllerFactory.ts +3 -5
  244. package/src/controllers/StandardController.ts +4 -6
  245. package/src/crypto/CryptoOps.ts +1 -1
  246. package/src/crypto/SignedHttpRequest.ts +1 -1
  247. package/src/index.ts +1 -0
  248. package/src/interaction_client/BaseInteractionClient.ts +2 -2
  249. package/src/interaction_client/NativeInteractionClient.ts +23 -20
  250. package/src/interaction_client/PopupClient.ts +1 -1
  251. package/src/interaction_client/RedirectClient.ts +3 -3
  252. package/src/interaction_client/SilentAuthCodeClient.ts +1 -1
  253. package/src/interaction_client/StandardInteractionClient.ts +1 -1
  254. package/src/interaction_handler/SilentHandler.ts +2 -2
  255. package/src/naa/AuthBridge.ts +3 -2
  256. package/src/naa/BridgeProxy.ts +6 -4
  257. package/src/packageMetadata.ts +1 -1
@@ -1,6 +1,6 @@
1
- /*! @azure/msal-browser v3.5.1-beta.0 2023-11-14 */
1
+ /*! @azure/msal-browser v3.6.0 2023-12-01 */
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,543 @@ 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, idTokenClaims.tid, undefined, response.account.id, this.logger);
228
+ // generate authenticationResult
229
+ const result = await this.generateAuthenticationResult(response, request, idTokenClaims, baseAccount, authority.canonicalAuthority, reqTimestamp);
230
+ // cache accounts and tokens in the appropriate storage
231
+ this.cacheAccount(baseAccount);
232
+ this.cacheNativeTokens(response, request, homeAccountIdentifier, idTokenClaims, result.accessToken, result.tenantId, reqTimestamp);
233
+ return result;
234
+ }
235
+ /**
236
+ * creates an homeAccountIdentifier for the account
237
+ * @param response
238
+ * @param idTokenObj
239
+ * @returns
240
+ */
241
+ createHomeAccountIdentifier(response, idTokenClaims) {
242
+ // Save account in browser storage
243
+ const homeAccountIdentifier = AccountEntity.generateHomeAccountId(response.client_info || Constants.EMPTY_STRING, AuthorityType.Default, this.logger, this.browserCrypto, idTokenClaims);
244
+ return homeAccountIdentifier;
245
+ }
246
+ /**
247
+ * Helper to generate scopes
248
+ * @param response
249
+ * @param request
250
+ * @returns
251
+ */
252
+ generateScopes(response, request) {
253
+ return response.scope
254
+ ? ScopeSet.fromString(response.scope)
255
+ : ScopeSet.fromString(request.scope);
256
+ }
257
+ /**
258
+ * If PoP token is requesred, records the PoP token if returned from the WAM, else generates one in the browser
259
+ * @param request
260
+ * @param response
261
+ */
262
+ async generatePopAccessToken(response, request) {
263
+ if (request.tokenType === AuthenticationScheme.POP) {
264
+ /**
265
+ * This code prioritizes SHR returned from the native layer. In case of error/SHR not calculated from WAM and the AT
266
+ * is still received, SHR is calculated locally
267
+ */
268
+ // Check if native layer returned an SHR token
269
+ if (response.shr) {
270
+ this.logger.trace("handleNativeServerResponse: SHR is enabled in native layer");
271
+ return response.shr;
272
+ }
273
+ // Generate SHR in msal js if WAM does not compute it when POP is enabled
274
+ const popTokenGenerator = new PopTokenGenerator(this.browserCrypto);
275
+ const shrParameters = {
276
+ resourceRequestMethod: request.resourceRequestMethod,
277
+ resourceRequestUri: request.resourceRequestUri,
278
+ shrClaims: request.shrClaims,
279
+ shrNonce: request.shrNonce,
280
+ };
281
+ /**
282
+ * KeyID must be present in the native request from when the PoP key was generated in order for
283
+ * PopTokenGenerator to query the full key for signing
284
+ */
285
+ if (!request.keyId) {
286
+ throw createClientAuthError(ClientAuthErrorCodes.keyIdMissing);
287
+ }
288
+ return popTokenGenerator.signPopToken(response.access_token, request.keyId, shrParameters);
289
+ }
290
+ else {
291
+ return response.access_token;
292
+ }
293
+ }
294
+ /**
295
+ * Generates authentication result
296
+ * @param response
297
+ * @param request
298
+ * @param idTokenObj
299
+ * @param accountEntity
300
+ * @param authority
301
+ * @param reqTimestamp
302
+ * @returns
303
+ */
304
+ async generateAuthenticationResult(response, request, idTokenClaims, accountEntity, authority, reqTimestamp) {
305
+ // Add Native Broker fields to Telemetry
306
+ const mats = this.addTelemetryFromNativeResponse(response);
307
+ // If scopes not returned in server response, use request scopes
308
+ const responseScopes = response.scope
309
+ ? ScopeSet.fromString(response.scope)
310
+ : ScopeSet.fromString(request.scope);
311
+ const accountProperties = response.account.properties || {};
312
+ const uid = accountProperties["UID"] ||
313
+ idTokenClaims.oid ||
314
+ idTokenClaims.sub ||
315
+ Constants.EMPTY_STRING;
316
+ const tid = accountProperties["TenantId"] ||
317
+ idTokenClaims.tid ||
318
+ Constants.EMPTY_STRING;
319
+ const accountInfo = updateAccountTenantProfileData(accountEntity.getAccountInfo(), undefined, // tenantProfile optional
320
+ idTokenClaims);
321
+ // generate PoP token as needed
322
+ const responseAccessToken = await this.generatePopAccessToken(response, request);
323
+ const tokenType = request.tokenType === AuthenticationScheme.POP
324
+ ? AuthenticationScheme.POP
325
+ : AuthenticationScheme.BEARER;
326
+ const result = {
327
+ authority: authority,
328
+ uniqueId: uid,
329
+ tenantId: tid,
330
+ scopes: responseScopes.asArray(),
331
+ account: accountInfo,
332
+ idToken: response.id_token,
333
+ idTokenClaims: idTokenClaims,
334
+ accessToken: responseAccessToken,
335
+ fromCache: mats ? this.isResponseFromCache(mats) : false,
336
+ expiresOn: new Date(Number(reqTimestamp + response.expires_in) * 1000),
337
+ tokenType: tokenType,
338
+ correlationId: this.correlationId,
339
+ state: response.state,
340
+ fromNativeBroker: true,
341
+ };
342
+ return result;
343
+ }
344
+ /**
345
+ * cache the account entity in browser storage
346
+ * @param accountEntity
347
+ */
348
+ cacheAccount(accountEntity) {
349
+ // Store the account info and hence `nativeAccountId` in browser cache
350
+ this.browserStorage.setAccount(accountEntity);
351
+ // Remove any existing cached tokens for this account in browser storage
352
+ this.browserStorage.removeAccountContext(accountEntity).catch((e) => {
353
+ this.logger.error(`Error occurred while removing account context from browser storage. ${e}`);
354
+ });
355
+ }
356
+ /**
357
+ * Stores the access_token and id_token in inmemory storage
358
+ * @param response
359
+ * @param request
360
+ * @param homeAccountIdentifier
361
+ * @param idTokenObj
362
+ * @param responseAccessToken
363
+ * @param tenantId
364
+ * @param reqTimestamp
365
+ */
366
+ cacheNativeTokens(response, request, homeAccountIdentifier, idTokenClaims, responseAccessToken, tenantId, reqTimestamp) {
367
+ const cachedIdToken = CacheHelpers.createIdTokenEntity(homeAccountIdentifier, request.authority, response.id_token || "", request.clientId, idTokenClaims.tid || "");
368
+ // cache accessToken in inmemory storage
369
+ const expiresIn = request.tokenType === AuthenticationScheme.POP
370
+ ? Constants.SHR_NONCE_VALIDITY
371
+ : (typeof response.expires_in === "string"
372
+ ? parseInt(response.expires_in, 10)
373
+ : response.expires_in) || 0;
374
+ const tokenExpirationSeconds = reqTimestamp + expiresIn;
375
+ const responseScopes = this.generateScopes(response, request);
376
+ const cachedAccessToken = CacheHelpers.createAccessTokenEntity(homeAccountIdentifier, request.authority, responseAccessToken, request.clientId, idTokenClaims.tid || tenantId, responseScopes.printScopes(), tokenExpirationSeconds, 0, base64Decode);
377
+ const nativeCacheRecord = new CacheRecord(undefined, cachedIdToken, cachedAccessToken);
378
+ void this.nativeStorageManager.saveCacheRecord(nativeCacheRecord, request.storeInCache);
379
+ }
380
+ addTelemetryFromNativeResponse(response) {
381
+ const mats = this.getMATSFromResponse(response);
382
+ if (!mats) {
383
+ return null;
384
+ }
385
+ this.performanceClient.addFields({
386
+ extensionId: this.nativeMessageHandler.getExtensionId(),
387
+ extensionVersion: this.nativeMessageHandler.getExtensionVersion(),
388
+ matsBrokerVersion: mats.broker_version,
389
+ matsAccountJoinOnStart: mats.account_join_on_start,
390
+ matsAccountJoinOnEnd: mats.account_join_on_end,
391
+ matsDeviceJoin: mats.device_join,
392
+ matsPromptBehavior: mats.prompt_behavior,
393
+ matsApiErrorCode: mats.api_error_code,
394
+ matsUiVisible: mats.ui_visible,
395
+ matsSilentCode: mats.silent_code,
396
+ matsSilentBiSubCode: mats.silent_bi_sub_code,
397
+ matsSilentMessage: mats.silent_message,
398
+ matsSilentStatus: mats.silent_status,
399
+ matsHttpStatus: mats.http_status,
400
+ matsHttpEventCount: mats.http_event_count,
401
+ }, this.correlationId);
402
+ return mats;
403
+ }
404
+ /**
405
+ * Validates native platform response before processing
406
+ * @param response
407
+ */
408
+ validateNativeResponse(response) {
409
+ if (response.hasOwnProperty("access_token") &&
410
+ response.hasOwnProperty("id_token") &&
411
+ response.hasOwnProperty("client_info") &&
412
+ response.hasOwnProperty("account") &&
413
+ response.hasOwnProperty("scope") &&
414
+ response.hasOwnProperty("expires_in")) {
415
+ return response;
416
+ }
417
+ else {
418
+ throw createAuthError(AuthErrorCodes.unexpectedError, "Response missing expected properties.");
419
+ }
420
+ }
421
+ /**
422
+ * Gets MATS telemetry from native response
423
+ * @param response
424
+ * @returns
425
+ */
426
+ getMATSFromResponse(response) {
427
+ if (response.properties.MATS) {
428
+ try {
429
+ return JSON.parse(response.properties.MATS);
430
+ }
431
+ catch (e) {
432
+ this.logger.error("NativeInteractionClient - Error parsing MATS telemetry, returning null instead");
433
+ }
434
+ }
435
+ return null;
436
+ }
437
+ /**
438
+ * Returns whether or not response came from native cache
439
+ * @param response
440
+ * @returns
441
+ */
442
+ isResponseFromCache(mats) {
443
+ if (typeof mats.is_cached === "undefined") {
444
+ this.logger.verbose("NativeInteractionClient - MATS telemetry does not contain field indicating if response was served from cache. Returning false.");
445
+ return false;
446
+ }
447
+ return !!mats.is_cached;
448
+ }
449
+ /**
450
+ * Translates developer provided request object into NativeRequest object
451
+ * @param request
452
+ */
453
+ async initializeNativeRequest(request) {
454
+ this.logger.trace("NativeInteractionClient - initializeNativeRequest called");
455
+ const authority = request.authority || this.config.auth.authority;
456
+ if (request.account) {
457
+ await this.validateRequestAuthority(authority, request.account);
458
+ }
459
+ const canonicalAuthority = new UrlString(authority);
460
+ canonicalAuthority.validateAsUri();
461
+ // 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.
462
+ const { scopes, ...remainingProperties } = request;
463
+ const scopeSet = new ScopeSet(scopes || []);
464
+ scopeSet.appendScopes(OIDC_DEFAULT_SCOPES);
465
+ const getPrompt = () => {
466
+ // If request is silent, prompt is always none
467
+ switch (this.apiId) {
468
+ case ApiId.ssoSilent:
469
+ case ApiId.acquireTokenSilent_silentFlow:
470
+ this.logger.trace("initializeNativeRequest: silent request sets prompt to none");
471
+ return PromptValue.NONE;
472
+ }
473
+ // Prompt not provided, request may proceed and native broker decides if it needs to prompt
474
+ if (!request.prompt) {
475
+ this.logger.trace("initializeNativeRequest: prompt was not provided");
476
+ return undefined;
477
+ }
478
+ // If request is interactive, check if prompt provided is allowed to go directly to native broker
479
+ switch (request.prompt) {
480
+ case PromptValue.NONE:
481
+ case PromptValue.CONSENT:
482
+ case PromptValue.LOGIN:
483
+ this.logger.trace("initializeNativeRequest: prompt is compatible with native flow");
484
+ return request.prompt;
485
+ default:
486
+ this.logger.trace(`initializeNativeRequest: prompt = ${request.prompt} is not compatible with native flow`);
487
+ throw createBrowserAuthError(nativePromptNotSupported);
488
+ }
489
+ };
490
+ const validatedRequest = {
491
+ ...remainingProperties,
492
+ accountId: this.accountId,
493
+ clientId: this.config.auth.clientId,
494
+ authority: canonicalAuthority.urlString,
495
+ scope: scopeSet.printScopes(),
496
+ redirectUri: this.getRedirectUri(request.redirectUri),
497
+ prompt: getPrompt(),
498
+ correlationId: this.correlationId,
499
+ tokenType: request.authenticationScheme,
500
+ windowTitleSubstring: document.title,
501
+ extraParameters: {
502
+ ...request.extraQueryParameters,
503
+ ...request.tokenQueryParameters,
504
+ },
505
+ extendedExpiryToken: false, // Make this configurable?
506
+ };
507
+ this.handleExtraBrokerParams(validatedRequest);
508
+ validatedRequest.extraParameters =
509
+ validatedRequest.extraParameters || {};
510
+ validatedRequest.extraParameters.telemetry =
511
+ NativeConstants.MATS_TELEMETRY;
512
+ if (request.authenticationScheme === AuthenticationScheme.POP) {
513
+ // add POP request type
514
+ const shrParameters = {
515
+ resourceRequestUri: request.resourceRequestUri,
516
+ resourceRequestMethod: request.resourceRequestMethod,
517
+ shrClaims: request.shrClaims,
518
+ shrNonce: request.shrNonce,
519
+ };
520
+ const popTokenGenerator = new PopTokenGenerator(this.browserCrypto);
521
+ const reqCnfData = await invokeAsync(popTokenGenerator.generateCnf.bind(popTokenGenerator), PerformanceEvents.PopTokenGenerateCnf, this.logger, this.performanceClient, this.correlationId)(shrParameters, this.logger);
522
+ // to reduce the URL length, it is recommended to send the hash of the req_cnf instead of the whole string
523
+ validatedRequest.reqCnf = reqCnfData.reqCnfHash;
524
+ validatedRequest.keyId = reqCnfData.kid;
525
+ }
526
+ return validatedRequest;
527
+ }
528
+ /**
529
+ * Handles extra broker request parameters
530
+ * @param request {NativeTokenRequest}
531
+ * @private
532
+ */
533
+ handleExtraBrokerParams(request) {
534
+ if (!request.extraParameters) {
535
+ return;
536
+ }
537
+ if (request.extraParameters.hasOwnProperty(BrokerServerParamKeys.BROKER_CLIENT_ID) &&
538
+ request.extraParameters.hasOwnProperty(BrokerServerParamKeys.BROKER_REDIRECT_URI) &&
539
+ request.extraParameters.hasOwnProperty(AADServerParamKeys.CLIENT_ID)) {
540
+ const child_client_id = request.extraParameters[AADServerParamKeys.CLIENT_ID];
541
+ const child_redirect_uri = request.redirectUri;
542
+ const brk_redirect_uri = request.extraParameters[BrokerServerParamKeys.BROKER_REDIRECT_URI];
543
+ request.extraParameters = {
544
+ child_client_id,
545
+ child_redirect_uri,
546
+ };
547
+ request.redirectUri = brk_redirect_uri;
548
+ }
549
+ }
560
550
  }
561
551
 
562
552
  export { NativeInteractionClient };