@azure/msal-browser 3.1.0 → 3.2.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 (180) hide show
  1. package/dist/app/IPublicClientApplication.d.ts.map +1 -1
  2. package/dist/app/IPublicClientApplication.mjs +20 -19
  3. package/dist/app/IPublicClientApplication.mjs.map +1 -1
  4. package/dist/app/PublicClientApplication.d.ts +14 -6
  5. package/dist/app/PublicClientApplication.d.ts.map +1 -1
  6. package/dist/app/PublicClientApplication.mjs +17 -7
  7. package/dist/app/PublicClientApplication.mjs.map +1 -1
  8. package/dist/broker/nativeBroker/NativeMessageHandler.d.ts +3 -4
  9. package/dist/broker/nativeBroker/NativeMessageHandler.d.ts.map +1 -1
  10. package/dist/broker/nativeBroker/NativeMessageHandler.mjs +13 -13
  11. package/dist/broker/nativeBroker/NativeMessageHandler.mjs.map +1 -1
  12. package/dist/broker/nativeBroker/NativeStatusCodes.d.ts +8 -0
  13. package/dist/broker/nativeBroker/NativeStatusCodes.d.ts.map +1 -0
  14. package/dist/broker/nativeBroker/NativeStatusCodes.mjs +16 -0
  15. package/dist/broker/nativeBroker/NativeStatusCodes.mjs.map +1 -0
  16. package/dist/cache/AsyncMemoryStorage.mjs +1 -1
  17. package/dist/cache/BrowserCacheManager.d.ts +3 -3
  18. package/dist/cache/BrowserCacheManager.d.ts.map +1 -1
  19. package/dist/cache/BrowserCacheManager.mjs +8 -7
  20. package/dist/cache/BrowserCacheManager.mjs.map +1 -1
  21. package/dist/cache/BrowserStorage.d.ts.map +1 -1
  22. package/dist/cache/BrowserStorage.mjs +7 -9
  23. package/dist/cache/BrowserStorage.mjs.map +1 -1
  24. package/dist/cache/CryptoKeyStore.mjs +1 -1
  25. package/dist/cache/DatabaseStorage.mjs +1 -1
  26. package/dist/cache/MemoryStorage.mjs +1 -1
  27. package/dist/cache/TokenCache.mjs +1 -1
  28. package/dist/config/Configuration.d.ts.map +1 -1
  29. package/dist/config/Configuration.mjs +7 -7
  30. package/dist/config/Configuration.mjs.map +1 -1
  31. package/dist/controllers/ControllerFactory.mjs +1 -1
  32. package/dist/controllers/IController.d.ts +3 -2
  33. package/dist/controllers/IController.d.ts.map +1 -1
  34. package/dist/controllers/StandardController.d.ts +11 -6
  35. package/dist/controllers/StandardController.d.ts.map +1 -1
  36. package/dist/controllers/StandardController.mjs +53 -34
  37. package/dist/controllers/StandardController.mjs.map +1 -1
  38. package/dist/crypto/BrowserCrypto.d.ts +44 -49
  39. package/dist/crypto/BrowserCrypto.d.ts.map +1 -1
  40. package/dist/crypto/BrowserCrypto.mjs +76 -76
  41. package/dist/crypto/BrowserCrypto.mjs.map +1 -1
  42. package/dist/crypto/CryptoOps.d.ts +1 -7
  43. package/dist/crypto/CryptoOps.d.ts.map +1 -1
  44. package/dist/crypto/CryptoOps.mjs +11 -19
  45. package/dist/crypto/CryptoOps.mjs.map +1 -1
  46. package/dist/crypto/PkceGenerator.d.ts +6 -21
  47. package/dist/crypto/PkceGenerator.d.ts.map +1 -1
  48. package/dist/crypto/PkceGenerator.mjs +45 -46
  49. package/dist/crypto/PkceGenerator.mjs.map +1 -1
  50. package/dist/crypto/SignedHttpRequest.mjs +1 -1
  51. package/dist/encode/Base64Decode.d.ts.map +1 -1
  52. package/dist/encode/Base64Decode.mjs +18 -2
  53. package/dist/encode/Base64Decode.mjs.map +1 -1
  54. package/dist/encode/Base64Encode.mjs +1 -1
  55. package/dist/error/BrowserAuthError.d.ts +10 -1
  56. package/dist/error/BrowserAuthError.d.ts.map +1 -1
  57. package/dist/error/BrowserAuthError.mjs +12 -3
  58. package/dist/error/BrowserAuthError.mjs.map +1 -1
  59. package/dist/error/BrowserAuthErrorCodes.d.ts +1 -0
  60. package/dist/error/BrowserAuthErrorCodes.d.ts.map +1 -1
  61. package/dist/error/BrowserAuthErrorCodes.mjs +3 -2
  62. package/dist/error/BrowserAuthErrorCodes.mjs.map +1 -1
  63. package/dist/error/BrowserConfigurationAuthError.d.ts +9 -46
  64. package/dist/error/BrowserConfigurationAuthError.d.ts.map +1 -1
  65. package/dist/error/BrowserConfigurationAuthError.mjs +20 -73
  66. package/dist/error/BrowserConfigurationAuthError.mjs.map +1 -1
  67. package/dist/error/BrowserConfigurationAuthErrorCodes.d.ts +4 -0
  68. package/dist/error/BrowserConfigurationAuthErrorCodes.d.ts.map +1 -0
  69. package/dist/error/BrowserConfigurationAuthErrorCodes.mjs +12 -0
  70. package/dist/error/BrowserConfigurationAuthErrorCodes.mjs.map +1 -0
  71. package/dist/error/NativeAuthError.d.ts +17 -45
  72. package/dist/error/NativeAuthError.d.ts.map +1 -1
  73. package/dist/error/NativeAuthError.mjs +47 -78
  74. package/dist/error/NativeAuthError.mjs.map +1 -1
  75. package/dist/error/NativeAuthErrorCodes.d.ts +3 -0
  76. package/dist/error/NativeAuthErrorCodes.d.ts.map +1 -0
  77. package/dist/error/NativeAuthErrorCodes.mjs +11 -0
  78. package/dist/error/NativeAuthErrorCodes.mjs.map +1 -0
  79. package/dist/event/EventHandler.d.ts.map +1 -1
  80. package/dist/event/EventHandler.mjs +3 -2
  81. package/dist/event/EventHandler.mjs.map +1 -1
  82. package/dist/event/EventMessage.mjs +1 -1
  83. package/dist/event/EventType.mjs +1 -1
  84. package/dist/index.d.ts +2 -2
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.mjs +4 -2
  87. package/dist/index.mjs.map +1 -1
  88. package/dist/interaction_client/BaseInteractionClient.d.ts.map +1 -1
  89. package/dist/interaction_client/BaseInteractionClient.mjs +7 -8
  90. package/dist/interaction_client/BaseInteractionClient.mjs.map +1 -1
  91. package/dist/interaction_client/HybridSpaAuthorizationCodeClient.mjs +1 -1
  92. package/dist/interaction_client/NativeInteractionClient.d.ts.map +1 -1
  93. package/dist/interaction_client/NativeInteractionClient.mjs +12 -10
  94. package/dist/interaction_client/NativeInteractionClient.mjs.map +1 -1
  95. package/dist/interaction_client/PopupClient.mjs +1 -1
  96. package/dist/interaction_client/RedirectClient.mjs +1 -1
  97. package/dist/interaction_client/SilentAuthCodeClient.d.ts.map +1 -1
  98. package/dist/interaction_client/SilentAuthCodeClient.mjs +5 -8
  99. package/dist/interaction_client/SilentAuthCodeClient.mjs.map +1 -1
  100. package/dist/interaction_client/SilentCacheClient.d.ts.map +1 -1
  101. package/dist/interaction_client/SilentCacheClient.mjs +10 -18
  102. package/dist/interaction_client/SilentCacheClient.mjs.map +1 -1
  103. package/dist/interaction_client/SilentIframeClient.mjs +2 -2
  104. package/dist/interaction_client/SilentRefreshClient.d.ts.map +1 -1
  105. package/dist/interaction_client/SilentRefreshClient.mjs +8 -18
  106. package/dist/interaction_client/SilentRefreshClient.mjs.map +1 -1
  107. package/dist/interaction_client/StandardInteractionClient.d.ts.map +1 -1
  108. package/dist/interaction_client/StandardInteractionClient.mjs +12 -33
  109. package/dist/interaction_client/StandardInteractionClient.mjs.map +1 -1
  110. package/dist/interaction_handler/InteractionHandler.d.ts.map +1 -1
  111. package/dist/interaction_handler/InteractionHandler.mjs +6 -9
  112. package/dist/interaction_handler/InteractionHandler.mjs.map +1 -1
  113. package/dist/interaction_handler/RedirectHandler.d.ts.map +1 -1
  114. package/dist/interaction_handler/RedirectHandler.mjs +3 -3
  115. package/dist/interaction_handler/RedirectHandler.mjs.map +1 -1
  116. package/dist/interaction_handler/SilentHandler.d.ts.map +1 -1
  117. package/dist/interaction_handler/SilentHandler.mjs +3 -4
  118. package/dist/interaction_handler/SilentHandler.mjs.map +1 -1
  119. package/dist/navigation/NavigationClient.mjs +1 -1
  120. package/dist/network/FetchClient.mjs +1 -1
  121. package/dist/operatingcontext/BaseOperatingContext.mjs +1 -1
  122. package/dist/operatingcontext/StandardOperatingContext.mjs +1 -1
  123. package/dist/operatingcontext/TeamsAppOperatingContext.mjs +1 -1
  124. package/dist/packageMetadata.d.ts +1 -1
  125. package/dist/packageMetadata.mjs +2 -2
  126. package/dist/telemetry/BrowserPerformanceClient.mjs +1 -1
  127. package/dist/telemetry/BrowserPerformanceMeasurement.mjs +1 -1
  128. package/dist/utils/BrowserConstants.mjs +1 -1
  129. package/dist/utils/BrowserProtocolUtils.d.ts.map +1 -1
  130. package/dist/utils/BrowserProtocolUtils.mjs +3 -3
  131. package/dist/utils/BrowserProtocolUtils.mjs.map +1 -1
  132. package/dist/utils/BrowserStringUtils.mjs +1 -1
  133. package/dist/utils/BrowserUtils.mjs +1 -1
  134. package/lib/msal-browser.cjs +1413 -1727
  135. package/lib/msal-browser.cjs.map +1 -1
  136. package/lib/msal-browser.js +1413 -1727
  137. package/lib/msal-browser.js.map +1 -1
  138. package/lib/msal-browser.min.js +68 -65
  139. package/package.json +2 -2
  140. package/src/app/IPublicClientApplication.ts +55 -18
  141. package/src/app/PublicClientApplication.ts +18 -6
  142. package/src/broker/nativeBroker/NativeMessageHandler.ts +12 -15
  143. package/src/broker/nativeBroker/NativeStatusCodes.ts +13 -0
  144. package/src/cache/BrowserCacheManager.ts +21 -6
  145. package/src/cache/BrowserStorage.ts +9 -11
  146. package/src/config/Configuration.ts +16 -8
  147. package/src/controllers/IController.ts +4 -1
  148. package/src/controllers/StandardController.ts +155 -92
  149. package/src/crypto/BrowserCrypto.ts +118 -102
  150. package/src/crypto/CryptoOps.ts +10 -22
  151. package/src/crypto/PkceGenerator.ts +93 -54
  152. package/src/encode/Base64Decode.ts +21 -1
  153. package/src/error/BrowserAuthError.ts +13 -1
  154. package/src/error/BrowserAuthErrorCodes.ts +1 -0
  155. package/src/error/BrowserConfigurationAuthError.ts +33 -102
  156. package/src/error/BrowserConfigurationAuthErrorCodes.ts +9 -0
  157. package/src/error/NativeAuthError.ts +73 -101
  158. package/src/error/NativeAuthErrorCodes.ts +7 -0
  159. package/src/event/EventHandler.ts +2 -1
  160. package/src/index.ts +5 -0
  161. package/src/interaction_client/BaseInteractionClient.ts +13 -7
  162. package/src/interaction_client/NativeInteractionClient.ts +29 -11
  163. package/src/interaction_client/SilentAuthCodeClient.ts +18 -16
  164. package/src/interaction_client/SilentCacheClient.ts +22 -30
  165. package/src/interaction_client/SilentIframeClient.ts +1 -1
  166. package/src/interaction_client/SilentRefreshClient.ts +26 -28
  167. package/src/interaction_client/StandardInteractionClient.ts +36 -67
  168. package/src/interaction_handler/InteractionHandler.ts +20 -15
  169. package/src/interaction_handler/RedirectHandler.ts +6 -2
  170. package/src/interaction_handler/SilentHandler.ts +6 -3
  171. package/src/packageMetadata.ts +1 -1
  172. package/src/utils/BrowserProtocolUtils.ts +3 -2
  173. package/dist/crypto/ISubtleCrypto.d.ts +0 -10
  174. package/dist/crypto/ISubtleCrypto.d.ts.map +0 -1
  175. package/dist/crypto/ModernBrowserCrypto.d.ts +0 -10
  176. package/dist/crypto/ModernBrowserCrypto.d.ts.map +0 -1
  177. package/dist/crypto/ModernBrowserCrypto.mjs +0 -31
  178. package/dist/crypto/ModernBrowserCrypto.mjs.map +0 -1
  179. package/src/crypto/ISubtleCrypto.ts +0 -30
  180. package/src/crypto/ModernBrowserCrypto.ts +0 -69
@@ -19,7 +19,6 @@ import {
19
19
  IPerformanceClient,
20
20
  BaseAuthRequest,
21
21
  PromptValue,
22
- ClientAuthError,
23
22
  InProgressPerformanceEvent,
24
23
  RequestThumbprint,
25
24
  ServerError,
@@ -27,6 +26,9 @@ import {
27
26
  ServerResponseType,
28
27
  UrlString,
29
28
  invokeAsync,
29
+ createClientAuthError,
30
+ ClientAuthErrorCodes,
31
+ AccountFilter,
30
32
  } from "@azure/msal-common";
31
33
  import {
32
34
  BrowserCacheManager,
@@ -50,7 +52,10 @@ import { SsoSilentRequest } from "../request/SsoSilentRequest";
50
52
  import { EventCallbackFunction, EventError } from "../event/EventMessage";
51
53
  import { EventType } from "../event/EventType";
52
54
  import { EndSessionRequest } from "../request/EndSessionRequest";
53
- import { BrowserConfigurationAuthError } from "../error/BrowserConfigurationAuthError";
55
+ import {
56
+ BrowserConfigurationAuthErrorCodes,
57
+ createBrowserConfigurationAuthError,
58
+ } from "../error/BrowserConfigurationAuthError";
54
59
  import { EndSessionPopupRequest } from "../request/EndSessionPopupRequest";
55
60
  import { INavigationClient } from "../navigation/INavigationClient";
56
61
  import { EventHandler } from "../event/EventHandler";
@@ -63,7 +68,10 @@ import { ITokenCache } from "../cache/ITokenCache";
63
68
  import { NativeInteractionClient } from "../interaction_client/NativeInteractionClient";
64
69
  import { NativeMessageHandler } from "../broker/nativeBroker/NativeMessageHandler";
65
70
  import { SilentRequest } from "../request/SilentRequest";
66
- import { NativeAuthError } from "../error/NativeAuthError";
71
+ import {
72
+ NativeAuthError,
73
+ isFatalNativeAuthError,
74
+ } from "../error/NativeAuthError";
67
75
  import { SilentCacheClient } from "../interaction_client/SilentCacheClient";
68
76
  import { SilentAuthCodeClient } from "../interaction_client/SilentAuthCodeClient";
69
77
  import {
@@ -77,6 +85,7 @@ import { BaseOperatingContext } from "../operatingcontext/BaseOperatingContext";
77
85
  import { IController } from "./IController";
78
86
  import { AuthenticationResult } from "../response/AuthenticationResult";
79
87
  import { ClearCacheRequest } from "../request/ClearCacheRequest";
88
+ import { createNewGuid } from "../crypto/BrowserCrypto";
80
89
 
81
90
  export class StandardController implements IController {
82
91
  // OperatingContext
@@ -281,8 +290,7 @@ export class StandardController implements IController {
281
290
  await NativeMessageHandler.createProvider(
282
291
  this.logger,
283
292
  this.config.system.nativeBrokerHandshakeTimeout,
284
- this.performanceClient,
285
- this.browserCrypto
293
+ this.performanceClient
286
294
  );
287
295
  } catch (e) {
288
296
  this.logger.verbose(e as string);
@@ -301,7 +309,7 @@ export class StandardController implements IController {
301
309
  PerformanceEvents.ClearTokensAndKeysWithClaims,
302
310
  this.logger,
303
311
  this.performanceClient
304
- )();
312
+ )(this.performanceClient);
305
313
  }
306
314
 
307
315
  this.initialized = true;
@@ -528,7 +536,10 @@ export class StandardController implements IController {
528
536
  result = nativeClient
529
537
  .acquireTokenRedirect(request)
530
538
  .catch((e: AuthError) => {
531
- if (e instanceof NativeAuthError && e.isFatal()) {
539
+ if (
540
+ e instanceof NativeAuthError &&
541
+ isFatalNativeAuthError(e)
542
+ ) {
532
543
  this.nativeExtensionProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
533
544
  const redirectClient = this.createRedirectClient(
534
545
  request.correlationId
@@ -630,7 +641,10 @@ export class StandardController implements IController {
630
641
  return response;
631
642
  })
632
643
  .catch((e: AuthError) => {
633
- if (e instanceof NativeAuthError && e.isFatal()) {
644
+ if (
645
+ e instanceof NativeAuthError &&
646
+ isFatalNativeAuthError(e)
647
+ ) {
634
648
  this.nativeExtensionProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
635
649
  const popupClient = this.createPopupClient(
636
650
  request.correlationId
@@ -781,7 +795,7 @@ export class StandardController implements IController {
781
795
  ApiId.ssoSilent
782
796
  ).catch((e: AuthError) => {
783
797
  // If native token acquisition fails for availability reasons fallback to standard flow
784
- if (e instanceof NativeAuthError && e.isFatal()) {
798
+ if (e instanceof NativeAuthError && isFatalNativeAuthError(e)) {
785
799
  this.nativeExtensionProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
786
800
  const silentIframeClient = this.createSilentIframeClient(
787
801
  validRequest.correlationId
@@ -931,7 +945,10 @@ export class StandardController implements IController {
931
945
  request.nativeAccountId
932
946
  ).catch((e: AuthError) => {
933
947
  // If native token acquisition fails for availability reasons fallback to standard flow
934
- if (e instanceof NativeAuthError && e.isFatal()) {
948
+ if (
949
+ e instanceof NativeAuthError &&
950
+ isFatalNativeAuthError(e)
951
+ ) {
935
952
  this.nativeExtensionProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
936
953
  }
937
954
  throw e;
@@ -1038,9 +1055,17 @@ export class StandardController implements IController {
1038
1055
  case CacheLookupPolicy.Default:
1039
1056
  case CacheLookupPolicy.AccessToken:
1040
1057
  case CacheLookupPolicy.AccessTokenAndRefreshToken:
1041
- return silentCacheClient.acquireToken(commonRequest);
1058
+ return invokeAsync(
1059
+ silentCacheClient.acquireToken.bind(silentCacheClient),
1060
+ PerformanceEvents.SilentCacheClientAcquireToken,
1061
+ this.logger,
1062
+ this.performanceClient,
1063
+ commonRequest.correlationId
1064
+ )(commonRequest);
1042
1065
  default:
1043
- throw ClientAuthError.createRefreshRequiredError();
1066
+ throw createClientAuthError(
1067
+ ClientAuthErrorCodes.tokenRefreshRequired
1068
+ );
1044
1069
  }
1045
1070
  }
1046
1071
 
@@ -1067,13 +1092,17 @@ export class StandardController implements IController {
1067
1092
  commonRequest.correlationId
1068
1093
  );
1069
1094
 
1070
- this.performanceClient.setPreQueueTime(
1095
+ return invokeAsync(
1096
+ silentRefreshClient.acquireToken.bind(silentRefreshClient),
1071
1097
  PerformanceEvents.SilentRefreshClientAcquireToken,
1098
+ this.logger,
1099
+ this.performanceClient,
1072
1100
  commonRequest.correlationId
1073
- );
1074
- return silentRefreshClient.acquireToken(commonRequest);
1101
+ )(commonRequest);
1075
1102
  default:
1076
- throw ClientAuthError.createRefreshRequiredError();
1103
+ throw createClientAuthError(
1104
+ ClientAuthErrorCodes.tokenRefreshRequired
1105
+ );
1077
1106
  }
1078
1107
  }
1079
1108
 
@@ -1168,18 +1197,45 @@ export class StandardController implements IController {
1168
1197
  // #region Account APIs
1169
1198
 
1170
1199
  /**
1171
- * Returns all accounts that MSAL currently has data for.
1172
- * (the account object is created at the time of successful login)
1173
- * or empty array when no accounts are found
1174
- * @returns Array of account objects in cache
1200
+ * Returns all the accounts in the cache that match the optional filter. If no filter is provided, all accounts are returned.
1201
+ * @param accountFilter - (Optional) filter to narrow down the accounts returned
1202
+ * @returns Array of AccountInfo objects in cache
1175
1203
  */
1176
- getAllAccounts(): AccountInfo[] {
1204
+ getAllAccounts(accountFilter?: AccountFilter): AccountInfo[] {
1177
1205
  this.logger.verbose("getAllAccounts called");
1178
1206
  return this.isBrowserEnvironment
1179
- ? this.browserStorage.getAllAccounts()
1207
+ ? this.browserStorage.getAllAccounts(accountFilter)
1180
1208
  : [];
1181
1209
  }
1182
1210
 
1211
+ /**
1212
+ * Returns the first account found in the cache that matches the account filter passed in.
1213
+ * @param accountFilter
1214
+ * @returns The first account found in the cache matching the provided filter or null if no account could be found.
1215
+ */
1216
+ getAccount(accountFilter: AccountFilter): AccountInfo | null {
1217
+ this.logger.trace("getAccount called");
1218
+ if (Object.keys(accountFilter).length === 0) {
1219
+ this.logger.warning("getAccount: No accountFilter provided");
1220
+ return null;
1221
+ }
1222
+
1223
+ const account: AccountInfo | null =
1224
+ this.browserStorage.getAccountInfoFilteredBy(accountFilter);
1225
+
1226
+ if (account) {
1227
+ this.logger.verbose(
1228
+ "getAccount: Account matching provided filter found, returning"
1229
+ );
1230
+ return account;
1231
+ } else {
1232
+ this.logger.verbose(
1233
+ "getAccount: No matching account found, returning null"
1234
+ );
1235
+ return null;
1236
+ }
1237
+ }
1238
+
1183
1239
  /**
1184
1240
  * Returns the signed in account matching username.
1185
1241
  * (the account object is created at the time of successful login)
@@ -1375,7 +1431,9 @@ export class StandardController implements IController {
1375
1431
  BrowserCacheLocation.MemoryStorage &&
1376
1432
  !this.config.cache.storeAuthStateInCookie
1377
1433
  ) {
1378
- throw BrowserConfigurationAuthError.createInMemoryRedirectUnavailableError();
1434
+ throw createBrowserConfigurationAuthError(
1435
+ BrowserConfigurationAuthErrorCodes.inMemRedirectUnavailable
1436
+ );
1379
1437
  }
1380
1438
 
1381
1439
  if (
@@ -1768,7 +1826,7 @@ export class StandardController implements IController {
1768
1826
  }
1769
1827
 
1770
1828
  if (this.isBrowserEnvironment) {
1771
- return this.browserCrypto.createNewGuid();
1829
+ return createNewGuid();
1772
1830
  }
1773
1831
 
1774
1832
  /*
@@ -1862,11 +1920,13 @@ export class StandardController implements IController {
1862
1920
  correlationId
1863
1921
  );
1864
1922
 
1865
- this.performanceClient.setPreQueueTime(
1923
+ const response = invokeAsync(
1924
+ this.acquireTokenSilentAsync.bind(this),
1866
1925
  PerformanceEvents.AcquireTokenSilentAsync,
1926
+ this.logger,
1927
+ this.performanceClient,
1867
1928
  correlationId
1868
- );
1869
- const response = this.acquireTokenSilentAsync(
1929
+ )(
1870
1930
  {
1871
1931
  ...request,
1872
1932
  correlationId,
@@ -1960,7 +2020,7 @@ export class StandardController implements IController {
1960
2020
  ApiId.acquireTokenSilent_silentFlow
1961
2021
  ).catch(async (e: AuthError) => {
1962
2022
  // If native token acquisition fails for availability reasons fallback to web flow
1963
- if (e instanceof NativeAuthError && e.isFatal()) {
2023
+ if (e instanceof NativeAuthError && isFatalNativeAuthError(e)) {
1964
2024
  this.logger.verbose(
1965
2025
  "acquireTokenSilent - native platform unavailable, falling back to web flow"
1966
2026
  );
@@ -1983,15 +2043,15 @@ export class StandardController implements IController {
1983
2043
  request.correlationId
1984
2044
  );
1985
2045
 
1986
- this.performanceClient.setPreQueueTime(
2046
+ const silentRequest = await invokeAsync(
2047
+ silentCacheClient.initializeSilentRequest.bind(
2048
+ silentCacheClient
2049
+ ),
1987
2050
  PerformanceEvents.InitializeSilentRequest,
2051
+ this.logger,
2052
+ this.performanceClient,
1988
2053
  request.correlationId
1989
- );
1990
- const silentRequest =
1991
- await silentCacheClient.initializeSilentRequest(
1992
- request,
1993
- account
1994
- );
2054
+ )(request, account);
1995
2055
 
1996
2056
  const requestWithCLP = {
1997
2057
  ...request,
@@ -2000,72 +2060,75 @@ export class StandardController implements IController {
2000
2060
  request.cacheLookupPolicy || CacheLookupPolicy.Default,
2001
2061
  };
2002
2062
 
2003
- this.performanceClient.setPreQueueTime(
2063
+ result = invokeAsync(
2064
+ this.acquireTokenFromCache.bind(this),
2004
2065
  PerformanceEvents.AcquireTokenFromCache,
2066
+ this.logger,
2067
+ this.performanceClient,
2005
2068
  silentRequest.correlationId
2006
- );
2007
- result = this.acquireTokenFromCache(
2008
- silentCacheClient,
2009
- silentRequest,
2010
- requestWithCLP
2011
- ).catch((cacheError: AuthError) => {
2012
- if (
2013
- requestWithCLP.cacheLookupPolicy ===
2014
- CacheLookupPolicy.AccessToken
2015
- ) {
2016
- throw cacheError;
2017
- }
2018
-
2019
- // block the reload if it occurred inside a hidden iframe
2020
- BrowserUtils.blockReloadInHiddenIframes();
2021
- this.eventHandler.emitEvent(
2022
- EventType.ACQUIRE_TOKEN_NETWORK_START,
2023
- InteractionType.Silent,
2024
- silentRequest
2025
- );
2026
-
2027
- this.performanceClient.setPreQueueTime(
2028
- PerformanceEvents.AcquireTokenByRefreshToken,
2029
- silentRequest.correlationId
2030
- );
2031
- return this.acquireTokenByRefreshToken(
2032
- silentRequest,
2033
- requestWithCLP
2034
- ).catch((refreshTokenError: AuthError) => {
2035
- const isServerError =
2036
- refreshTokenError instanceof ServerError;
2037
- const isInteractionRequiredError =
2038
- refreshTokenError instanceof
2039
- InteractionRequiredAuthError;
2040
- const isInvalidGrantError =
2041
- refreshTokenError.errorCode ===
2042
- BrowserConstants.INVALID_GRANT_ERROR;
2043
-
2069
+ )(silentCacheClient, silentRequest, requestWithCLP).catch(
2070
+ (cacheError: AuthError) => {
2044
2071
  if (
2045
- (!isServerError ||
2046
- !isInvalidGrantError ||
2047
- isInteractionRequiredError ||
2048
- requestWithCLP.cacheLookupPolicy ===
2049
- CacheLookupPolicy.AccessTokenAndRefreshToken ||
2050
- requestWithCLP.cacheLookupPolicy ===
2051
- CacheLookupPolicy.RefreshToken) &&
2052
- requestWithCLP.cacheLookupPolicy !==
2053
- CacheLookupPolicy.Skip
2072
+ requestWithCLP.cacheLookupPolicy ===
2073
+ CacheLookupPolicy.AccessToken
2054
2074
  ) {
2055
- throw refreshTokenError;
2075
+ throw cacheError;
2056
2076
  }
2057
2077
 
2058
- this.logger.verbose(
2059
- "Refresh token expired/invalid or CacheLookupPolicy is set to Skip, attempting acquire token by iframe.",
2060
- request.correlationId
2078
+ // block the reload if it occurred inside a hidden iframe
2079
+ BrowserUtils.blockReloadInHiddenIframes();
2080
+ this.eventHandler.emitEvent(
2081
+ EventType.ACQUIRE_TOKEN_NETWORK_START,
2082
+ InteractionType.Silent,
2083
+ silentRequest
2061
2084
  );
2062
- this.performanceClient.setPreQueueTime(
2063
- PerformanceEvents.AcquireTokenBySilentIframe,
2085
+
2086
+ return invokeAsync(
2087
+ this.acquireTokenByRefreshToken.bind(this),
2088
+ PerformanceEvents.AcquireTokenByRefreshToken,
2089
+ this.logger,
2090
+ this.performanceClient,
2064
2091
  silentRequest.correlationId
2092
+ )(silentRequest, requestWithCLP).catch(
2093
+ (refreshTokenError: AuthError) => {
2094
+ const isServerError =
2095
+ refreshTokenError instanceof ServerError;
2096
+ const isInteractionRequiredError =
2097
+ refreshTokenError instanceof
2098
+ InteractionRequiredAuthError;
2099
+ const isInvalidGrantError =
2100
+ refreshTokenError.errorCode ===
2101
+ BrowserConstants.INVALID_GRANT_ERROR;
2102
+
2103
+ if (
2104
+ (!isServerError ||
2105
+ !isInvalidGrantError ||
2106
+ isInteractionRequiredError ||
2107
+ requestWithCLP.cacheLookupPolicy ===
2108
+ CacheLookupPolicy.AccessTokenAndRefreshToken ||
2109
+ requestWithCLP.cacheLookupPolicy ===
2110
+ CacheLookupPolicy.RefreshToken) &&
2111
+ requestWithCLP.cacheLookupPolicy !==
2112
+ CacheLookupPolicy.Skip
2113
+ ) {
2114
+ throw refreshTokenError;
2115
+ }
2116
+
2117
+ this.logger.verbose(
2118
+ "Refresh token expired/invalid or CacheLookupPolicy is set to Skip, attempting acquire token by iframe.",
2119
+ request.correlationId
2120
+ );
2121
+ return invokeAsync(
2122
+ this.acquireTokenBySilentIframe.bind(this),
2123
+ PerformanceEvents.AcquireTokenBySilentIframe,
2124
+ this.logger,
2125
+ this.performanceClient,
2126
+ silentRequest.correlationId
2127
+ )(silentRequest);
2128
+ }
2065
2129
  );
2066
- return this.acquireTokenBySilentIframe(silentRequest);
2067
- });
2068
- });
2130
+ }
2131
+ );
2069
2132
  }
2070
2133
 
2071
2134
  return result
@@ -8,9 +8,18 @@ import {
8
8
  createBrowserAuthError,
9
9
  BrowserAuthErrorCodes,
10
10
  } from "../error/BrowserAuthError";
11
- import { ISubtleCrypto } from "./ISubtleCrypto";
12
- import { ModernBrowserCrypto } from "./ModernBrowserCrypto";
13
- import { Logger } from "@azure/msal-common";
11
+ import {
12
+ IPerformanceClient,
13
+ Logger,
14
+ PerformanceEvents,
15
+ } from "@azure/msal-common";
16
+ import { KEY_FORMAT_JWK } from "../utils/BrowserConstants";
17
+
18
+ /**
19
+ * This file defines functions used by the browser library to perform cryptography operations such as
20
+ * hashing and encoding. It also has helper functions to validate the availability of specific APIs.
21
+ */
22
+
14
23
  /**
15
24
  * See here for more info on RsaHashedKeyGenParams: https://developer.mozilla.org/en-US/docs/Web/API/RsaHashedKeyGenParams
16
25
  */
@@ -23,113 +32,120 @@ const MODULUS_LENGTH = 2048;
23
32
  // Public Exponent
24
33
  const PUBLIC_EXPONENT: Uint8Array = new Uint8Array([0x01, 0x00, 0x01]);
25
34
 
35
+ const keygenAlgorithmOptions: RsaHashedKeyGenParams = {
36
+ name: PKCS1_V15_KEYGEN_ALG,
37
+ hash: S256_HASH_ALG,
38
+ modulusLength: MODULUS_LENGTH,
39
+ publicExponent: PUBLIC_EXPONENT,
40
+ };
41
+
26
42
  /**
27
- * This class implements functions used by the browser library to perform cryptography operations such as
28
- * hashing and encoding. It also has helper functions to validate the availability of specific APIs.
43
+ * Check whether browser crypto is available.
29
44
  */
30
- export class BrowserCrypto {
31
- private keygenAlgorithmOptions: RsaHashedKeyGenParams;
32
- private subtleCrypto: ISubtleCrypto;
33
- private logger: Logger;
34
-
35
- constructor(logger: Logger) {
36
- this.logger = logger;
37
-
38
- if (this.hasBrowserCrypto()) {
39
- // Use standard modern web crypto if available
40
- this.logger.verbose(
41
- "BrowserCrypto: modern crypto interface available"
42
- );
43
- this.subtleCrypto = new ModernBrowserCrypto();
44
- } else {
45
- this.logger.error("BrowserCrypto: crypto interface is unavailable");
46
- throw createBrowserAuthError(
47
- BrowserAuthErrorCodes.cryptoNonExistent
48
- );
49
- }
50
-
51
- this.keygenAlgorithmOptions = {
52
- name: PKCS1_V15_KEYGEN_ALG,
53
- hash: S256_HASH_ALG,
54
- modulusLength: MODULUS_LENGTH,
55
- publicExponent: PUBLIC_EXPONENT,
56
- };
45
+ export function validateCryptoAvailable(logger: Logger): void {
46
+ if ("crypto" in window) {
47
+ logger.verbose("BrowserCrypto: modern crypto interface available");
48
+ } else {
49
+ logger.error("BrowserCrypto: crypto interface is unavailable");
50
+ throw createBrowserAuthError(BrowserAuthErrorCodes.cryptoNonExistent);
57
51
  }
52
+ }
58
53
 
59
- /**
60
- * Check whether browser crypto is available.
61
- */
62
- private hasBrowserCrypto(): boolean {
63
- return "crypto" in window;
64
- }
54
+ /**
55
+ * Returns a sha-256 hash of the given dataString as an ArrayBuffer.
56
+ * @param dataString
57
+ */
58
+ export async function sha256Digest(
59
+ dataString: string,
60
+ performanceClient?: IPerformanceClient,
61
+ correlationId?: string
62
+ ): Promise<ArrayBuffer> {
63
+ performanceClient?.addQueueMeasurement(
64
+ PerformanceEvents.Sha256Digest,
65
+ correlationId
66
+ );
67
+ const data = BrowserStringUtils.stringToUtf8Arr(dataString);
68
+ return window.crypto.subtle.digest(
69
+ S256_HASH_ALG,
70
+ data
71
+ ) as Promise<ArrayBuffer>;
72
+ }
65
73
 
66
- /**
67
- * Returns a sha-256 hash of the given dataString as an ArrayBuffer.
68
- * @param dataString
69
- */
70
- async sha256Digest(dataString: string): Promise<ArrayBuffer> {
71
- const data = BrowserStringUtils.stringToUtf8Arr(dataString);
72
- // MSR Crypto wants object with name property, instead of string
73
- return this.subtleCrypto.digest({ name: S256_HASH_ALG }, data);
74
- }
74
+ /**
75
+ * Populates buffer with cryptographically random values.
76
+ * @param dataBuffer
77
+ */
78
+ export function getRandomValues(dataBuffer: Uint8Array): Uint8Array {
79
+ return window.crypto.getRandomValues(dataBuffer);
80
+ }
75
81
 
76
- /**
77
- * Populates buffer with cryptographically random values.
78
- * @param dataBuffer
79
- */
80
- getRandomValues(dataBuffer: Uint8Array): Uint8Array {
81
- return this.subtleCrypto.getRandomValues(dataBuffer);
82
- }
82
+ /**
83
+ * Creates a new random GUID
84
+ * @returns
85
+ */
86
+ export function createNewGuid(): string {
87
+ return window.crypto.randomUUID();
88
+ }
83
89
 
84
- /**
85
- * Generates a keypair based on current keygen algorithm config.
86
- * @param extractable
87
- * @param usages
88
- */
89
- async generateKeyPair(
90
- extractable: boolean,
91
- usages: Array<KeyUsage>
92
- ): Promise<CryptoKeyPair> {
93
- return this.subtleCrypto.generateKey(
94
- this.keygenAlgorithmOptions,
95
- extractable,
96
- usages
97
- );
98
- }
90
+ /**
91
+ * Generates a keypair based on current keygen algorithm config.
92
+ * @param extractable
93
+ * @param usages
94
+ */
95
+ export async function generateKeyPair(
96
+ extractable: boolean,
97
+ usages: Array<KeyUsage>
98
+ ): Promise<CryptoKeyPair> {
99
+ return window.crypto.subtle.generateKey(
100
+ keygenAlgorithmOptions,
101
+ extractable,
102
+ usages
103
+ ) as Promise<CryptoKeyPair>;
104
+ }
99
105
 
100
- /**
101
- * Export key as Json Web Key (JWK)
102
- * @param key
103
- */
104
- async exportJwk(key: CryptoKey): Promise<JsonWebKey> {
105
- return this.subtleCrypto.exportKey(key);
106
- }
106
+ /**
107
+ * Export key as Json Web Key (JWK)
108
+ * @param key
109
+ */
110
+ export async function exportJwk(key: CryptoKey): Promise<JsonWebKey> {
111
+ return window.crypto.subtle.exportKey(
112
+ KEY_FORMAT_JWK,
113
+ key
114
+ ) as Promise<JsonWebKey>;
115
+ }
107
116
 
108
- /**
109
- * Imports key as Json Web Key (JWK), can set extractable and usages.
110
- * @param key
111
- * @param extractable
112
- * @param usages
113
- */
114
- async importJwk(
115
- key: JsonWebKey,
116
- extractable: boolean,
117
- usages: Array<KeyUsage>
118
- ): Promise<CryptoKey> {
119
- return this.subtleCrypto.importKey(
120
- key,
121
- this.keygenAlgorithmOptions,
122
- extractable,
123
- usages
124
- );
125
- }
117
+ /**
118
+ * Imports key as Json Web Key (JWK), can set extractable and usages.
119
+ * @param key
120
+ * @param extractable
121
+ * @param usages
122
+ */
123
+ export async function importJwk(
124
+ key: JsonWebKey,
125
+ extractable: boolean,
126
+ usages: Array<KeyUsage>
127
+ ): Promise<CryptoKey> {
128
+ return window.crypto.subtle.importKey(
129
+ KEY_FORMAT_JWK,
130
+ key,
131
+ keygenAlgorithmOptions,
132
+ extractable,
133
+ usages
134
+ ) as Promise<CryptoKey>;
135
+ }
126
136
 
127
- /**
128
- * Signs given data with given key
129
- * @param key
130
- * @param data
131
- */
132
- async sign(key: CryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> {
133
- return this.subtleCrypto.sign(this.keygenAlgorithmOptions, key, data);
134
- }
137
+ /**
138
+ * Signs given data with given key
139
+ * @param key
140
+ * @param data
141
+ */
142
+ export async function sign(
143
+ key: CryptoKey,
144
+ data: ArrayBuffer
145
+ ): Promise<ArrayBuffer> {
146
+ return window.crypto.subtle.sign(
147
+ keygenAlgorithmOptions,
148
+ key,
149
+ data
150
+ ) as Promise<ArrayBuffer>;
135
151
  }