@azure/msal-browser 3.20.0 → 3.21.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 (208) hide show
  1. package/dist/app/IPublicClientApplication.d.ts +53 -53
  2. package/dist/app/IPublicClientApplication.mjs +105 -105
  3. package/dist/app/PublicClientApplication.d.ts +293 -293
  4. package/dist/app/PublicClientApplication.mjs +364 -364
  5. package/dist/app/PublicClientNext.d.ts +276 -276
  6. package/dist/app/PublicClientNext.mjs +354 -354
  7. package/dist/broker/nativeBroker/NativeMessageHandler.d.ts +62 -62
  8. package/dist/broker/nativeBroker/NativeMessageHandler.mjs +254 -254
  9. package/dist/broker/nativeBroker/NativeRequest.d.ts +45 -45
  10. package/dist/broker/nativeBroker/NativeResponse.d.ts +48 -48
  11. package/dist/broker/nativeBroker/NativeStatusCodes.d.ts +7 -7
  12. package/dist/broker/nativeBroker/NativeStatusCodes.mjs +11 -11
  13. package/dist/cache/AccountManager.d.ts +48 -48
  14. package/dist/cache/AccountManager.mjs +126 -126
  15. package/dist/cache/AsyncMemoryStorage.d.ts +50 -50
  16. package/dist/cache/AsyncMemoryStorage.mjs +131 -131
  17. package/dist/cache/BrowserCacheManager.d.ts +410 -385
  18. package/dist/cache/BrowserCacheManager.d.ts.map +1 -1
  19. package/dist/cache/BrowserCacheManager.mjs +1364 -1294
  20. package/dist/cache/BrowserCacheManager.mjs.map +1 -1
  21. package/dist/cache/BrowserStorage.d.ts +11 -11
  22. package/dist/cache/BrowserStorage.mjs +32 -32
  23. package/dist/cache/DatabaseStorage.d.ts +56 -56
  24. package/dist/cache/DatabaseStorage.mjs +200 -200
  25. package/dist/cache/IAsyncStorage.d.ts +27 -27
  26. package/dist/cache/ITokenCache.d.ts +11 -11
  27. package/dist/cache/IWindowStorage.d.ts +27 -27
  28. package/dist/cache/MemoryStorage.d.ts +11 -11
  29. package/dist/cache/MemoryStorage.mjs +31 -31
  30. package/dist/cache/TokenCache.d.ts +77 -77
  31. package/dist/cache/TokenCache.mjs +195 -195
  32. package/dist/config/Configuration.d.ts +213 -208
  33. package/dist/config/Configuration.d.ts.map +1 -1
  34. package/dist/config/Configuration.mjs +128 -128
  35. package/dist/config/Configuration.mjs.map +1 -1
  36. package/dist/controllers/ControllerFactory.d.ts +5 -5
  37. package/dist/controllers/ControllerFactory.mjs +25 -25
  38. package/dist/controllers/IController.d.ts +60 -60
  39. package/dist/controllers/NestedAppAuthController.d.ts +202 -202
  40. package/dist/controllers/NestedAppAuthController.mjs +473 -473
  41. package/dist/controllers/StandardController.d.ts +405 -405
  42. package/dist/controllers/StandardController.d.ts.map +1 -1
  43. package/dist/controllers/StandardController.mjs +1334 -1316
  44. package/dist/controllers/StandardController.mjs.map +1 -1
  45. package/dist/controllers/UnknownOperatingContextController.d.ts +86 -86
  46. package/dist/controllers/UnknownOperatingContextController.mjs +256 -256
  47. package/dist/crypto/BrowserCrypto.d.ts +52 -52
  48. package/dist/crypto/BrowserCrypto.mjs +151 -151
  49. package/dist/crypto/CryptoOps.d.ts +74 -74
  50. package/dist/crypto/CryptoOps.mjs +176 -176
  51. package/dist/crypto/PkceGenerator.d.ts +8 -8
  52. package/dist/crypto/PkceGenerator.mjs +54 -54
  53. package/dist/crypto/SignedHttpRequest.d.ts +30 -30
  54. package/dist/crypto/SignedHttpRequest.mjs +39 -39
  55. package/dist/encode/Base64Decode.d.ts +9 -9
  56. package/dist/encode/Base64Decode.mjs +36 -36
  57. package/dist/encode/Base64Encode.d.ts +19 -19
  58. package/dist/encode/Base64Encode.mjs +43 -43
  59. package/dist/error/BrowserAuthError.d.ts +256 -255
  60. package/dist/error/BrowserAuthError.d.ts.map +1 -1
  61. package/dist/error/BrowserAuthError.mjs +265 -264
  62. package/dist/error/BrowserAuthError.mjs.map +1 -1
  63. package/dist/error/BrowserAuthErrorCodes.d.ts +47 -46
  64. package/dist/error/BrowserAuthErrorCodes.d.ts.map +1 -1
  65. package/dist/error/BrowserAuthErrorCodes.mjs +53 -52
  66. package/dist/error/BrowserAuthErrorCodes.mjs.map +1 -1
  67. package/dist/error/BrowserConfigurationAuthError.d.ts +33 -33
  68. package/dist/error/BrowserConfigurationAuthError.mjs +40 -40
  69. package/dist/error/BrowserConfigurationAuthError.mjs.map +1 -1
  70. package/dist/error/BrowserConfigurationAuthErrorCodes.d.ts +3 -3
  71. package/dist/error/BrowserConfigurationAuthErrorCodes.mjs +7 -7
  72. package/dist/error/NativeAuthError.d.ts +29 -29
  73. package/dist/error/NativeAuthError.mjs +60 -60
  74. package/dist/error/NativeAuthErrorCodes.d.ts +2 -2
  75. package/dist/error/NativeAuthErrorCodes.mjs +6 -6
  76. package/dist/error/NestedAppAuthError.d.ts +14 -14
  77. package/dist/error/NestedAppAuthError.mjs +23 -23
  78. package/dist/event/EventHandler.d.ts +41 -41
  79. package/dist/event/EventHandler.mjs +125 -125
  80. package/dist/event/EventMessage.d.ts +25 -25
  81. package/dist/event/EventMessage.mjs +68 -68
  82. package/dist/event/EventType.d.ts +29 -29
  83. package/dist/event/EventType.mjs +32 -32
  84. package/dist/index.d.ts +40 -40
  85. package/dist/index.mjs +1 -1
  86. package/dist/interaction_client/BaseInteractionClient.d.ts +50 -50
  87. package/dist/interaction_client/BaseInteractionClient.mjs +106 -106
  88. package/dist/interaction_client/HybridSpaAuthorizationCodeClient.d.ts +4 -4
  89. package/dist/interaction_client/HybridSpaAuthorizationCodeClient.mjs +10 -10
  90. package/dist/interaction_client/NativeInteractionClient.d.ts +151 -151
  91. package/dist/interaction_client/NativeInteractionClient.mjs +621 -621
  92. package/dist/interaction_client/PopupClient.d.ts +118 -105
  93. package/dist/interaction_client/PopupClient.d.ts.map +1 -1
  94. package/dist/interaction_client/PopupClient.mjs +460 -434
  95. package/dist/interaction_client/PopupClient.mjs.map +1 -1
  96. package/dist/interaction_client/RedirectClient.d.ts +50 -50
  97. package/dist/interaction_client/RedirectClient.d.ts.map +1 -1
  98. package/dist/interaction_client/RedirectClient.mjs +349 -317
  99. package/dist/interaction_client/RedirectClient.mjs.map +1 -1
  100. package/dist/interaction_client/SilentAuthCodeClient.d.ts +23 -23
  101. package/dist/interaction_client/SilentAuthCodeClient.mjs +57 -57
  102. package/dist/interaction_client/SilentCacheClient.d.ts +16 -16
  103. package/dist/interaction_client/SilentCacheClient.mjs +42 -42
  104. package/dist/interaction_client/SilentIframeClient.d.ts +32 -32
  105. package/dist/interaction_client/SilentIframeClient.d.ts.map +1 -1
  106. package/dist/interaction_client/SilentIframeClient.mjs +111 -101
  107. package/dist/interaction_client/SilentIframeClient.mjs.map +1 -1
  108. package/dist/interaction_client/SilentRefreshClient.d.ts +20 -20
  109. package/dist/interaction_client/SilentRefreshClient.mjs +47 -47
  110. package/dist/interaction_client/StandardInteractionClient.d.ts +48 -48
  111. package/dist/interaction_client/StandardInteractionClient.mjs +199 -199
  112. package/dist/interaction_handler/InteractionHandler.d.ts +33 -33
  113. package/dist/interaction_handler/InteractionHandler.mjs +93 -93
  114. package/dist/interaction_handler/RedirectHandler.d.ts +32 -32
  115. package/dist/interaction_handler/RedirectHandler.d.ts.map +1 -1
  116. package/dist/interaction_handler/RedirectHandler.mjs +135 -134
  117. package/dist/interaction_handler/RedirectHandler.mjs.map +1 -1
  118. package/dist/interaction_handler/SilentHandler.d.ts +13 -13
  119. package/dist/interaction_handler/SilentHandler.mjs +134 -134
  120. package/dist/naa/AccountInfo.d.ts +11 -11
  121. package/dist/naa/AuthBridge.d.ts +8 -8
  122. package/dist/naa/AuthResult.d.ts +6 -6
  123. package/dist/naa/BridgeAccountContext.d.ts +12 -12
  124. package/dist/naa/BridgeCapabilities.d.ts +3 -3
  125. package/dist/naa/BridgeError.d.ts +9 -9
  126. package/dist/naa/BridgeError.mjs +7 -7
  127. package/dist/naa/BridgeProxy.d.ts +67 -67
  128. package/dist/naa/BridgeProxy.d.ts.map +1 -1
  129. package/dist/naa/BridgeProxy.mjs +153 -148
  130. package/dist/naa/BridgeProxy.mjs.map +1 -1
  131. package/dist/naa/BridgeRequest.d.ts +7 -7
  132. package/dist/naa/BridgeRequestEnvelope.d.ts +12 -12
  133. package/dist/naa/BridgeResponseEnvelope.d.ts +13 -13
  134. package/dist/naa/BridgeStatusCode.d.ts +11 -11
  135. package/dist/naa/BridgeStatusCode.mjs +14 -14
  136. package/dist/naa/IBridgeProxy.d.ts +10 -10
  137. package/dist/naa/InitContext.d.ts +8 -8
  138. package/dist/naa/TokenRequest.d.ts +18 -18
  139. package/dist/naa/TokenResponse.d.ts +13 -13
  140. package/dist/naa/mapping/NestedAppAuthAdapter.d.ts +35 -35
  141. package/dist/naa/mapping/NestedAppAuthAdapter.mjs +179 -179
  142. package/dist/navigation/INavigationClient.d.ts +16 -16
  143. package/dist/navigation/NavigationClient.d.ts +22 -22
  144. package/dist/navigation/NavigationClient.mjs +40 -40
  145. package/dist/navigation/NavigationOptions.d.ts +12 -12
  146. package/dist/network/FetchClient.d.ts +26 -26
  147. package/dist/network/FetchClient.mjs +99 -99
  148. package/dist/operatingcontext/BaseOperatingContext.d.ts +41 -41
  149. package/dist/operatingcontext/BaseOperatingContext.mjs +94 -94
  150. package/dist/operatingcontext/NestedAppOperatingContext.d.ts +34 -34
  151. package/dist/operatingcontext/NestedAppOperatingContext.mjs +71 -71
  152. package/dist/operatingcontext/StandardOperatingContext.d.ts +25 -25
  153. package/dist/operatingcontext/StandardOperatingContext.mjs +43 -43
  154. package/dist/operatingcontext/UnknownOperatingContext.d.ts +25 -25
  155. package/dist/operatingcontext/UnknownOperatingContext.mjs +42 -42
  156. package/dist/packageMetadata.d.ts +2 -2
  157. package/dist/packageMetadata.mjs +4 -4
  158. package/dist/request/AuthorizationCodeRequest.d.ts +8 -8
  159. package/dist/request/AuthorizationUrlRequest.d.ts +8 -8
  160. package/dist/request/ClearCacheRequest.d.ts +10 -10
  161. package/dist/request/EndSessionPopupRequest.d.ts +18 -18
  162. package/dist/request/EndSessionRequest.d.ts +15 -15
  163. package/dist/request/InitializeApplicationRequest.d.ts +8 -8
  164. package/dist/request/PopupRequest.d.ts +34 -34
  165. package/dist/request/PopupWindowAttributes.d.ts +15 -15
  166. package/dist/request/RedirectRequest.d.ts +40 -35
  167. package/dist/request/RedirectRequest.d.ts.map +1 -1
  168. package/dist/request/RequestHelpers.d.ts +13 -13
  169. package/dist/request/RequestHelpers.mjs +53 -53
  170. package/dist/request/SilentRequest.d.ts +33 -33
  171. package/dist/request/SsoSilentRequest.d.ts +29 -29
  172. package/dist/response/AuthenticationResult.d.ts +4 -4
  173. package/dist/response/ResponseHandler.d.ts +7 -7
  174. package/dist/response/ResponseHandler.mjs +36 -36
  175. package/dist/telemetry/BrowserPerformanceClient.d.ts +38 -34
  176. package/dist/telemetry/BrowserPerformanceClient.d.ts.map +1 -1
  177. package/dist/telemetry/BrowserPerformanceClient.mjs +163 -163
  178. package/dist/telemetry/BrowserPerformanceClient.mjs.map +1 -1
  179. package/dist/telemetry/BrowserPerformanceMeasurement.d.ts +21 -21
  180. package/dist/telemetry/BrowserPerformanceMeasurement.mjs +92 -92
  181. package/dist/utils/BrowserConstants.d.ts +182 -180
  182. package/dist/utils/BrowserConstants.d.ts.map +1 -1
  183. package/dist/utils/BrowserConstants.mjs +214 -212
  184. package/dist/utils/BrowserConstants.mjs.map +1 -1
  185. package/dist/utils/BrowserProtocolUtils.d.ts +11 -11
  186. package/dist/utils/BrowserProtocolUtils.mjs +21 -21
  187. package/dist/utils/BrowserUtils.d.ts +75 -75
  188. package/dist/utils/BrowserUtils.mjs +157 -157
  189. package/lib/msal-browser.cjs +19027 -18857
  190. package/lib/msal-browser.cjs.map +1 -1
  191. package/lib/msal-browser.js +19027 -18857
  192. package/lib/msal-browser.js.map +1 -1
  193. package/lib/msal-browser.min.js +62 -62
  194. package/package.json +2 -2
  195. package/src/cache/BrowserCacheManager.ts +95 -0
  196. package/src/config/Configuration.ts +9 -1
  197. package/src/controllers/StandardController.ts +30 -12
  198. package/src/error/BrowserAuthError.ts +2 -0
  199. package/src/error/BrowserAuthErrorCodes.ts +1 -0
  200. package/src/interaction_client/PopupClient.ts +202 -117
  201. package/src/interaction_client/RedirectClient.ts +62 -2
  202. package/src/interaction_client/SilentIframeClient.ts +41 -3
  203. package/src/interaction_handler/RedirectHandler.ts +1 -0
  204. package/src/naa/BridgeProxy.ts +7 -2
  205. package/src/packageMetadata.ts +1 -1
  206. package/src/request/RedirectRequest.ts +5 -0
  207. package/src/telemetry/BrowserPerformanceClient.ts +1 -1
  208. package/src/utils/BrowserConstants.ts +2 -0
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "type": "git",
11
11
  "url": "https://github.com/AzureAD/microsoft-authentication-library-for-js.git"
12
12
  },
13
- "version": "3.20.0",
13
+ "version": "3.21.0",
14
14
  "description": "Microsoft Authentication Library for js",
15
15
  "keywords": [
16
16
  "implicit",
@@ -104,6 +104,6 @@
104
104
  "typescript": "^4.9.5"
105
105
  },
106
106
  "dependencies": {
107
- "@azure/msal-common": "14.14.0"
107
+ "@azure/msal-common": "14.14.1"
108
108
  }
109
109
  }
@@ -1552,6 +1552,9 @@ export class BrowserCacheManager extends CacheManager {
1552
1552
  this.removeTemporaryItem(
1553
1553
  this.generateCacheKey(TemporaryCacheKeys.NATIVE_REQUEST)
1554
1554
  );
1555
+ this.removeTemporaryItem(
1556
+ this.generateCacheKey(TemporaryCacheKeys.REDIRECT_REQUEST)
1557
+ );
1555
1558
  this.setInteractionInProgress(false);
1556
1559
  }
1557
1560
 
@@ -1613,6 +1616,98 @@ export class BrowserCacheManager extends CacheManager {
1613
1616
  this.setInteractionInProgress(false);
1614
1617
  }
1615
1618
 
1619
+ /**
1620
+ * Create request retry key to cache retry status
1621
+ */
1622
+ generateRequestRetriedKey(): string {
1623
+ return `${Constants.CACHE_PREFIX}.${TemporaryCacheKeys.REQUEST_RETRY}.${this.clientId}`;
1624
+ }
1625
+
1626
+ /**
1627
+ * Gets the request retry value from the cache
1628
+ */
1629
+ getRequestRetried(): number | null {
1630
+ const requestRetriedKey = this.generateRequestRetriedKey();
1631
+ const cachedRetryNumber = this.getTemporaryCache(requestRetriedKey);
1632
+ if (!cachedRetryNumber) {
1633
+ return null;
1634
+ }
1635
+ return parseInt(cachedRetryNumber);
1636
+ }
1637
+
1638
+ /**
1639
+ * Sets the request retry value to "retried" in the cache
1640
+ */
1641
+ setRequestRetried(): void {
1642
+ this.logger.trace("BrowserCacheManager.setRequestRetried called");
1643
+ const requestRetriedKey = this.generateRequestRetriedKey();
1644
+ this.setTemporaryCache(requestRetriedKey, "1", false);
1645
+ }
1646
+
1647
+ /**
1648
+ * Removes all request retry values in the cache
1649
+ */
1650
+ removeRequestRetried(): void {
1651
+ const requestRetriedKey = this.generateRequestRetriedKey();
1652
+ this.removeTemporaryItem(requestRetriedKey);
1653
+ }
1654
+
1655
+ /**
1656
+ * Caches the redirectRequest in the cache
1657
+ * @param redirectRequest
1658
+ */
1659
+ cacheRedirectRequest(redirectRequest: RedirectRequest): void {
1660
+ this.logger.trace("BrowserCacheManager.cacheRedirectRequest called");
1661
+ const { ...restParams } = redirectRequest;
1662
+ delete restParams.onRedirectNavigate;
1663
+ const encodedValue = JSON.stringify(restParams);
1664
+
1665
+ this.setTemporaryCache(
1666
+ TemporaryCacheKeys.REDIRECT_REQUEST,
1667
+ encodedValue,
1668
+ true
1669
+ );
1670
+ }
1671
+
1672
+ /**
1673
+ * Gets redirect request from the cache. Logs an error and returns undefined if nothing is found.
1674
+ */
1675
+ getCachedRedirectRequest(): RedirectRequest | undefined {
1676
+ this.logger.trace(
1677
+ "BrowserCacheManager.getCachedRedirectRequest called"
1678
+ );
1679
+ const cachedRedirectRequest = this.getTemporaryCache(
1680
+ TemporaryCacheKeys.REDIRECT_REQUEST,
1681
+ true
1682
+ );
1683
+ if (!cachedRedirectRequest) {
1684
+ this.logger.error(`No cached redirect request found.`);
1685
+ } else {
1686
+ this.removeTemporaryItem(
1687
+ this.generateCacheKey(TemporaryCacheKeys.REDIRECT_REQUEST)
1688
+ );
1689
+ let parsedRequest: RedirectRequest;
1690
+ try {
1691
+ parsedRequest = JSON.parse(
1692
+ cachedRedirectRequest
1693
+ ) as RedirectRequest;
1694
+ } catch (e) {
1695
+ this.logger.errorPii(
1696
+ `Attempted to parse: ${cachedRedirectRequest}`
1697
+ );
1698
+ this.logger.error(
1699
+ `Parsing cached redirect request threw with error: ${e}`
1700
+ );
1701
+ return;
1702
+ }
1703
+
1704
+ if (parsedRequest) {
1705
+ return parsedRequest;
1706
+ }
1707
+ }
1708
+ return;
1709
+ }
1710
+
1616
1711
  cacheCodeRequest(authCodeRequest: CommonAuthorizationCodeRequest): void {
1617
1712
  this.logger.trace("BrowserCacheManager.cacheCodeRequest called");
1618
1713
 
@@ -99,11 +99,19 @@ export type BrowserAuthOptions = {
99
99
  * @deprecated This flag is deprecated and will be removed in the next major version. createNestablePublicClientApplication should be used instead.
100
100
  */
101
101
  supportsNestedAppAuth?: boolean;
102
+ /**
103
+ * Callback that will be passed the url that MSAL will navigate to in redirect flows. Returning false in the callback will stop navigation.
104
+ */
105
+ onRedirectNavigate?: (url: string) => boolean | void;
102
106
  };
103
107
 
104
108
  /** @internal */
105
- export type InternalAuthOptions = Required<BrowserAuthOptions> & {
109
+ export type InternalAuthOptions = Omit<
110
+ Required<BrowserAuthOptions>,
111
+ "onRedirectNavigate"
112
+ > & {
106
113
  OIDCOptions: Required<OIDCOptions>;
114
+ onRedirectNavigate?: (url: string) => boolean | void;
107
115
  };
108
116
 
109
117
  /**
@@ -584,19 +584,37 @@ export class StandardController implements IController {
584
584
  scenarioId: request.scenarioId,
585
585
  });
586
586
 
587
+ // Override on request only if set, as onRedirectNavigate field is deprecated
587
588
  const onRedirectNavigateCb = request.onRedirectNavigate;
588
- request.onRedirectNavigate = (url: string) => {
589
- const navigate =
590
- typeof onRedirectNavigateCb === "function"
591
- ? onRedirectNavigateCb(url)
592
- : undefined;
593
- if (navigate !== false) {
594
- atrMeasurement.end({ success: true });
595
- } else {
596
- atrMeasurement.discard();
597
- }
598
- return navigate;
599
- };
589
+ if (onRedirectNavigateCb) {
590
+ request.onRedirectNavigate = (url: string) => {
591
+ const navigate =
592
+ typeof onRedirectNavigateCb === "function"
593
+ ? onRedirectNavigateCb(url)
594
+ : undefined;
595
+ if (navigate !== false) {
596
+ atrMeasurement.end({ success: true });
597
+ } else {
598
+ atrMeasurement.discard();
599
+ }
600
+ return navigate;
601
+ };
602
+ } else {
603
+ const configOnRedirectNavigateCb =
604
+ this.config.auth.onRedirectNavigate;
605
+ this.config.auth.onRedirectNavigate = (url: string) => {
606
+ const navigate =
607
+ typeof configOnRedirectNavigateCb === "function"
608
+ ? configOnRedirectNavigateCb(url)
609
+ : undefined;
610
+ if (navigate !== false) {
611
+ atrMeasurement.end({ success: true });
612
+ } else {
613
+ atrMeasurement.discard();
614
+ }
615
+ return navigate;
616
+ };
617
+ }
600
618
 
601
619
  // If logged in, emit acquire token events
602
620
  const isLoggedIn = this.getAllAccounts().length > 0;
@@ -92,6 +92,8 @@ export const BrowserAuthErrorMessages = {
92
92
  "Invalid base64 encoded string.",
93
93
  [BrowserAuthErrorCodes.invalidPopTokenRequest]:
94
94
  "Invalid PoP token request. The request should not have both a popKid value and signPopToken set to true.",
95
+ [BrowserAuthErrorCodes.failedToRetry]:
96
+ "Unable to retry failed auth code redemption due to usage of the onRedirectNavigate request parameter. Please set onRedirectNavigate on the PublicClientApplication configuration instead or call loginRedirect again.",
95
97
  };
96
98
 
97
99
  /**
@@ -56,3 +56,4 @@ export const uninitializedPublicClientApplication =
56
56
  export const nativePromptNotSupported = "native_prompt_not_supported";
57
57
  export const invalidBase64String = "invalid_base64_string";
58
58
  export const invalidPopTokenRequest = "invalid_pop_token_request";
59
+ export const failedToRetry = "failed_to_retry";
@@ -20,6 +20,7 @@ import {
20
20
  ServerResponseType,
21
21
  invokeAsync,
22
22
  invoke,
23
+ ServerError,
23
24
  } from "@azure/msal-common";
24
25
  import { StandardInteractionClient } from "./StandardInteractionClient";
25
26
  import { EventType } from "../event/EventType";
@@ -47,6 +48,7 @@ import { PopupWindowAttributes } from "../request/PopupWindowAttributes";
47
48
  import { EventError } from "../event/EventMessage";
48
49
  import { AuthenticationResult } from "../response/AuthenticationResult";
49
50
  import * as ResponseHandler from "../response/ResponseHandler";
51
+ import { AuthorizationUrlRequest } from "../request/AuthorizationUrlRequest";
50
52
 
51
53
  export type PopupParams = {
52
54
  popup?: Window | null;
@@ -182,7 +184,7 @@ export class PopupClient extends StandardInteractionClient {
182
184
  }
183
185
 
184
186
  /**
185
- * Helper which obtains an access_token for your API via opening a popup window in the user's browser
187
+ * Helper which initializes authorization clients and requests
186
188
  * @param validRequest
187
189
  * @param popupName
188
190
  * @param popup
@@ -211,19 +213,20 @@ export class PopupClient extends StandardInteractionClient {
211
213
 
212
214
  BrowserUtils.preconnect(validRequest.authority);
213
215
 
216
+ let authClient: AuthorizationCodeClient | undefined;
217
+
214
218
  try {
215
219
  // Create auth code request and generate PKCE params
216
- const authCodeRequest: CommonAuthorizationCodeRequest =
217
- await invokeAsync(
218
- this.initializeAuthorizationCodeRequest.bind(this),
219
- PerformanceEvents.StandardInteractionClientInitializeAuthorizationCodeRequest,
220
- this.logger,
221
- this.performanceClient,
222
- this.correlationId
223
- )(validRequest);
220
+ const authCodeRequest = await invokeAsync(
221
+ this.initializeAuthorizationCodeRequest.bind(this),
222
+ PerformanceEvents.StandardInteractionClientInitializeAuthorizationCodeRequest,
223
+ this.logger,
224
+ this.performanceClient,
225
+ this.correlationId
226
+ )(validRequest);
224
227
 
225
228
  // Initialize the client
226
- const authClient: AuthorizationCodeClient = await invokeAsync(
229
+ authClient = await invokeAsync(
227
230
  this.createAuthCodeClient.bind(this),
228
231
  PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,
229
232
  this.logger,
@@ -236,136 +239,218 @@ export class PopupClient extends StandardInteractionClient {
236
239
  validRequest.account
237
240
  );
238
241
 
239
- const isNativeBroker = NativeMessageHandler.isNativeAvailable(
240
- this.config,
242
+ return await invokeAsync(
243
+ this.acquireTokenPopupAsyncHelper.bind(this),
244
+ PerformanceEvents.PopupClientTokenHelper,
241
245
  this.logger,
242
- this.nativeMessageHandler,
243
- request.authenticationScheme
244
- );
245
- // Start measurement for server calls with native brokering enabled
246
- let fetchNativeAccountIdMeasurement;
247
- if (isNativeBroker) {
248
- fetchNativeAccountIdMeasurement =
249
- this.performanceClient.startMeasurement(
250
- PerformanceEvents.FetchAccountIdWithNativeBroker,
251
- request.correlationId
252
- );
253
- }
254
-
255
- // Create acquire token url.
256
- const navigateUrl = await authClient.getAuthCodeUrl({
257
- ...validRequest,
258
- nativeBroker: isNativeBroker,
259
- });
260
-
261
- // Create popup interaction handler.
262
- const interactionHandler = new InteractionHandler(
246
+ this.performanceClient,
247
+ this.correlationId
248
+ )(
263
249
  authClient,
264
- this.browserStorage,
265
250
  authCodeRequest,
266
- this.logger,
267
- this.performanceClient
268
- );
269
-
270
- // Show the UI once the url has been created. Get the window handle for the popup.
271
- const popupParameters: PopupParams = {
272
- popup,
251
+ validRequest,
252
+ request,
273
253
  popupName,
274
254
  popupWindowAttributes,
275
- };
276
- const popupWindow: Window = this.initiateAuthRequest(
277
- navigateUrl,
278
- popupParameters
255
+ popup
279
256
  );
280
- this.eventHandler.emitEvent(
281
- EventType.POPUP_OPENED,
282
- InteractionType.Popup,
283
- { popupWindow },
284
- null
257
+ } catch (e) {
258
+ if (popup) {
259
+ // Close the synchronous popup if an error is thrown before the window unload event is registered
260
+ popup.close();
261
+ }
262
+
263
+ if (e instanceof AuthError) {
264
+ (e as AuthError).setCorrelationId(this.correlationId);
265
+ serverTelemetryManager.cacheFailedRequest(e);
266
+ }
267
+
268
+ if (
269
+ !authClient ||
270
+ !(e instanceof ServerError) ||
271
+ e.errorCode !== BrowserConstants.INVALID_GRANT_ERROR
272
+ ) {
273
+ throw e;
274
+ }
275
+
276
+ this.performanceClient.addFields(
277
+ {
278
+ retryError: e.errorCode,
279
+ },
280
+ this.correlationId
285
281
  );
286
282
 
287
- // Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
288
- const responseString = await this.monitorPopupForHash(popupWindow);
283
+ const retryAuthCodeRequest = await invokeAsync(
284
+ this.initializeAuthorizationCodeRequest.bind(this),
285
+ PerformanceEvents.StandardInteractionClientInitializeAuthorizationCodeRequest,
286
+ this.logger,
287
+ this.performanceClient,
288
+ this.correlationId
289
+ )(validRequest);
289
290
 
290
- const serverParams = invoke(
291
- ResponseHandler.deserializeResponse,
292
- PerformanceEvents.DeserializeResponse,
291
+ return await invokeAsync(
292
+ this.acquireTokenPopupAsyncHelper.bind(this),
293
+ PerformanceEvents.PopupClientTokenHelper,
293
294
  this.logger,
294
295
  this.performanceClient,
295
296
  this.correlationId
296
297
  )(
297
- responseString,
298
- this.config.auth.OIDCOptions.serverResponseType,
299
- this.logger
300
- );
301
- // Remove throttle if it exists
302
- ThrottlingUtils.removeThrottle(
303
- this.browserStorage,
304
- this.config.auth.clientId,
305
- authCodeRequest
298
+ authClient,
299
+ retryAuthCodeRequest,
300
+ validRequest,
301
+ request,
302
+ popupName,
303
+ popupWindowAttributes,
304
+ popup
306
305
  );
306
+ }
307
+ }
307
308
 
308
- if (serverParams.accountId) {
309
- this.logger.verbose(
310
- "Account id found in hash, calling WAM for token"
311
- );
312
- // end measurement for server call with native brokering enabled
313
- if (fetchNativeAccountIdMeasurement) {
314
- fetchNativeAccountIdMeasurement.end({
315
- success: true,
316
- isNativeBroker: true,
317
- });
318
- }
309
+ /**
310
+ * Helper which obtains an access_token for your API via opening a popup window in the user's browser
311
+ * @param authClient
312
+ * @param authCodeRequest
313
+ * @param validRequest
314
+ * @param request
315
+ * @param popupName
316
+ * @param popupWindowAttributes
317
+ * @param popup
318
+ * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.
319
+ */
320
+ protected async acquireTokenPopupAsyncHelper(
321
+ authClient: AuthorizationCodeClient,
322
+ authCodeRequest: CommonAuthorizationCodeRequest,
323
+ validRequest: AuthorizationUrlRequest,
324
+ request: PopupRequest,
325
+ popupName: string,
326
+ popupWindowAttributes: PopupWindowAttributes,
327
+ popup?: Window | null
328
+ ): Promise<AuthenticationResult> {
329
+ const correlationId = validRequest.correlationId;
330
+ this.performanceClient.addQueueMeasurement(
331
+ PerformanceEvents.PopupClientTokenHelper,
332
+ correlationId
333
+ );
319
334
 
320
- if (!this.nativeMessageHandler) {
321
- throw createBrowserAuthError(
322
- BrowserAuthErrorCodes.nativeConnectionNotEstablished
323
- );
324
- }
325
- const nativeInteractionClient = new NativeInteractionClient(
326
- this.config,
327
- this.browserStorage,
328
- this.browserCrypto,
329
- this.logger,
330
- this.eventHandler,
331
- this.navigationClient,
332
- ApiId.acquireTokenPopup,
333
- this.performanceClient,
334
- this.nativeMessageHandler,
335
- serverParams.accountId,
336
- this.nativeStorage,
337
- validRequest.correlationId
338
- );
339
- const { userRequestState } = ProtocolUtils.parseRequestState(
340
- this.browserCrypto,
341
- validRequest.state
335
+ const isNativeBroker = NativeMessageHandler.isNativeAvailable(
336
+ this.config,
337
+ this.logger,
338
+ this.nativeMessageHandler,
339
+ request.authenticationScheme
340
+ );
341
+
342
+ // Start measurement for server calls with native brokering enabled
343
+ let fetchNativeAccountIdMeasurement;
344
+ if (isNativeBroker) {
345
+ fetchNativeAccountIdMeasurement =
346
+ this.performanceClient.startMeasurement(
347
+ PerformanceEvents.FetchAccountIdWithNativeBroker,
348
+ request.correlationId
342
349
  );
343
- return await nativeInteractionClient.acquireToken({
344
- ...validRequest,
345
- state: userRequestState,
346
- prompt: undefined, // Server should handle the prompt, ideally native broker can do this part silently
347
- });
348
- }
350
+ }
349
351
 
350
- // Handle response from hash string.
351
- const result = await interactionHandler.handleCodeResponse(
352
- serverParams,
353
- validRequest
354
- );
352
+ // Create acquire token url.
353
+ const navigateUrl = await authClient.getAuthCodeUrl({
354
+ ...validRequest,
355
+ nativeBroker: isNativeBroker,
356
+ });
355
357
 
356
- return result;
357
- } catch (e) {
358
- if (popup) {
359
- // Close the synchronous popup if an error is thrown before the window unload event is registered
360
- popup.close();
358
+ // Create popup interaction handler.
359
+ const interactionHandler = new InteractionHandler(
360
+ authClient,
361
+ this.browserStorage,
362
+ authCodeRequest,
363
+ this.logger,
364
+ this.performanceClient
365
+ );
366
+
367
+ // Show the UI once the url has been created. Get the window handle for the popup.
368
+ const popupParameters: PopupParams = {
369
+ popup,
370
+ popupName,
371
+ popupWindowAttributes,
372
+ };
373
+ const popupWindow: Window = this.initiateAuthRequest(
374
+ navigateUrl,
375
+ popupParameters
376
+ );
377
+ this.eventHandler.emitEvent(
378
+ EventType.POPUP_OPENED,
379
+ InteractionType.Popup,
380
+ { popupWindow },
381
+ null
382
+ );
383
+
384
+ // Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
385
+ const responseString = await this.monitorPopupForHash(popupWindow);
386
+
387
+ const serverParams = invoke(
388
+ ResponseHandler.deserializeResponse,
389
+ PerformanceEvents.DeserializeResponse,
390
+ this.logger,
391
+ this.performanceClient,
392
+ this.correlationId
393
+ )(
394
+ responseString,
395
+ this.config.auth.OIDCOptions.serverResponseType,
396
+ this.logger
397
+ );
398
+ // Remove throttle if it exists
399
+ ThrottlingUtils.removeThrottle(
400
+ this.browserStorage,
401
+ this.config.auth.clientId,
402
+ authCodeRequest
403
+ );
404
+
405
+ if (serverParams.accountId) {
406
+ this.logger.verbose(
407
+ "Account id found in hash, calling WAM for token"
408
+ );
409
+ // end measurement for server call with native brokering enabled
410
+ if (fetchNativeAccountIdMeasurement) {
411
+ fetchNativeAccountIdMeasurement.end({
412
+ success: true,
413
+ isNativeBroker: true,
414
+ });
361
415
  }
362
416
 
363
- if (e instanceof AuthError) {
364
- (e as AuthError).setCorrelationId(this.correlationId);
365
- serverTelemetryManager.cacheFailedRequest(e);
417
+ if (!this.nativeMessageHandler) {
418
+ throw createBrowserAuthError(
419
+ BrowserAuthErrorCodes.nativeConnectionNotEstablished
420
+ );
366
421
  }
367
- throw e;
422
+ const nativeInteractionClient = new NativeInteractionClient(
423
+ this.config,
424
+ this.browserStorage,
425
+ this.browserCrypto,
426
+ this.logger,
427
+ this.eventHandler,
428
+ this.navigationClient,
429
+ ApiId.acquireTokenPopup,
430
+ this.performanceClient,
431
+ this.nativeMessageHandler,
432
+ serverParams.accountId,
433
+ this.nativeStorage,
434
+ validRequest.correlationId
435
+ );
436
+ const { userRequestState } = ProtocolUtils.parseRequestState(
437
+ this.browserCrypto,
438
+ validRequest.state
439
+ );
440
+ return nativeInteractionClient.acquireToken({
441
+ ...validRequest,
442
+ state: userRequestState,
443
+ prompt: undefined, // Server should handle the prompt, ideally native broker can do this part silently
444
+ });
368
445
  }
446
+
447
+ // Handle response from hash string.
448
+ const result = await interactionHandler.handleCodeResponse(
449
+ serverParams,
450
+ validRequest
451
+ );
452
+
453
+ return result;
369
454
  }
370
455
 
371
456
  /**