@azure/msal-browser 4.0.0-alpha.0 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/dist/app/IPublicClientApplication.mjs +1 -1
  2. package/dist/app/PublicClientApplication.mjs +1 -1
  3. package/dist/app/PublicClientNext.mjs +1 -1
  4. package/dist/broker/nativeBroker/NativeMessageHandler.d.ts +1 -1
  5. package/dist/broker/nativeBroker/NativeMessageHandler.d.ts.map +1 -1
  6. package/dist/broker/nativeBroker/NativeMessageHandler.mjs +8 -8
  7. package/dist/broker/nativeBroker/NativeMessageHandler.mjs.map +1 -1
  8. package/dist/broker/nativeBroker/NativeResponse.d.ts +1 -1
  9. package/dist/broker/nativeBroker/NativeStatusCodes.mjs +1 -1
  10. package/dist/cache/AccountManager.mjs +1 -1
  11. package/dist/cache/AsyncMemoryStorage.mjs +1 -1
  12. package/dist/cache/BrowserCacheManager.d.ts +9 -9
  13. package/dist/cache/BrowserCacheManager.d.ts.map +1 -1
  14. package/dist/cache/BrowserCacheManager.mjs +19 -19
  15. package/dist/cache/BrowserCacheManager.mjs.map +1 -1
  16. package/dist/cache/CacheHelpers.mjs +1 -1
  17. package/dist/cache/CookieStorage.mjs +1 -1
  18. package/dist/cache/CookieStorage.mjs.map +1 -1
  19. package/dist/cache/DatabaseStorage.mjs +1 -1
  20. package/dist/cache/IWindowStorage.d.ts +2 -2
  21. package/dist/cache/IWindowStorage.d.ts.map +1 -1
  22. package/dist/cache/LocalStorage.d.ts +7 -3
  23. package/dist/cache/LocalStorage.d.ts.map +1 -1
  24. package/dist/cache/LocalStorage.mjs +48 -34
  25. package/dist/cache/LocalStorage.mjs.map +1 -1
  26. package/dist/cache/MemoryStorage.mjs +1 -1
  27. package/dist/cache/SessionStorage.mjs +1 -1
  28. package/dist/cache/TokenCache.d.ts.map +1 -1
  29. package/dist/cache/TokenCache.mjs +15 -14
  30. package/dist/cache/TokenCache.mjs.map +1 -1
  31. package/dist/config/Configuration.d.ts +2 -2
  32. package/dist/config/Configuration.d.ts.map +1 -1
  33. package/dist/config/Configuration.mjs +5 -5
  34. package/dist/config/Configuration.mjs.map +1 -1
  35. package/dist/controllers/ControllerFactory.mjs +1 -1
  36. package/dist/controllers/NestedAppAuthController.d.ts +4 -3
  37. package/dist/controllers/NestedAppAuthController.d.ts.map +1 -1
  38. package/dist/controllers/NestedAppAuthController.mjs +9 -7
  39. package/dist/controllers/NestedAppAuthController.mjs.map +1 -1
  40. package/dist/controllers/StandardController.d.ts +2 -2
  41. package/dist/controllers/StandardController.d.ts.map +1 -1
  42. package/dist/controllers/StandardController.mjs +27 -23
  43. package/dist/controllers/StandardController.mjs.map +1 -1
  44. package/dist/controllers/UnknownOperatingContextController.d.ts +2 -2
  45. package/dist/controllers/UnknownOperatingContextController.d.ts.map +1 -1
  46. package/dist/controllers/UnknownOperatingContextController.mjs +3 -3
  47. package/dist/controllers/UnknownOperatingContextController.mjs.map +1 -1
  48. package/dist/crypto/BrowserCrypto.d.ts +1 -1
  49. package/dist/crypto/BrowserCrypto.d.ts.map +1 -1
  50. package/dist/crypto/BrowserCrypto.mjs +3 -3
  51. package/dist/crypto/BrowserCrypto.mjs.map +1 -1
  52. package/dist/crypto/CryptoOps.d.ts +1 -1
  53. package/dist/crypto/CryptoOps.d.ts.map +1 -1
  54. package/dist/crypto/CryptoOps.mjs +3 -3
  55. package/dist/crypto/CryptoOps.mjs.map +1 -1
  56. package/dist/crypto/PkceGenerator.mjs +1 -1
  57. package/dist/crypto/SignedHttpRequest.mjs +1 -1
  58. package/dist/encode/Base64Decode.mjs +1 -1
  59. package/dist/encode/Base64Encode.mjs +1 -1
  60. package/dist/error/BrowserAuthError.mjs +1 -1
  61. package/dist/error/BrowserAuthErrorCodes.mjs +1 -1
  62. package/dist/error/BrowserConfigurationAuthError.mjs +1 -1
  63. package/dist/error/BrowserConfigurationAuthErrorCodes.mjs +1 -1
  64. package/dist/error/NativeAuthError.mjs +1 -1
  65. package/dist/error/NativeAuthError.mjs.map +1 -1
  66. package/dist/error/NativeAuthErrorCodes.mjs +1 -1
  67. package/dist/error/NestedAppAuthError.mjs +1 -1
  68. package/dist/event/EventHandler.mjs +1 -1
  69. package/dist/event/EventMessage.mjs +1 -1
  70. package/dist/event/EventType.mjs +1 -1
  71. package/dist/index.mjs +1 -1
  72. package/dist/interaction_client/BaseInteractionClient.mjs +1 -1
  73. package/dist/interaction_client/HybridSpaAuthorizationCodeClient.mjs +1 -1
  74. package/dist/interaction_client/NativeInteractionClient.d.ts +1 -1
  75. package/dist/interaction_client/NativeInteractionClient.d.ts.map +1 -1
  76. package/dist/interaction_client/NativeInteractionClient.mjs +4 -4
  77. package/dist/interaction_client/NativeInteractionClient.mjs.map +1 -1
  78. package/dist/interaction_client/PopupClient.d.ts.map +1 -1
  79. package/dist/interaction_client/PopupClient.mjs +4 -4
  80. package/dist/interaction_client/PopupClient.mjs.map +1 -1
  81. package/dist/interaction_client/RedirectClient.mjs +2 -2
  82. package/dist/interaction_client/RedirectClient.mjs.map +1 -1
  83. package/dist/interaction_client/SilentAuthCodeClient.mjs +1 -1
  84. package/dist/interaction_client/SilentCacheClient.mjs +1 -1
  85. package/dist/interaction_client/SilentIframeClient.mjs +2 -2
  86. package/dist/interaction_client/SilentIframeClient.mjs.map +1 -1
  87. package/dist/interaction_client/SilentRefreshClient.mjs +1 -1
  88. package/dist/interaction_client/StandardInteractionClient.mjs +1 -1
  89. package/dist/interaction_handler/InteractionHandler.mjs +1 -1
  90. package/dist/interaction_handler/RedirectHandler.mjs +1 -1
  91. package/dist/interaction_handler/SilentHandler.mjs +1 -1
  92. package/dist/naa/BridgeError.mjs +1 -1
  93. package/dist/naa/BridgeProxy.mjs +1 -1
  94. package/dist/naa/BridgeStatusCode.mjs +1 -1
  95. package/dist/naa/mapping/NestedAppAuthAdapter.mjs +1 -1
  96. package/dist/navigation/NavigationClient.mjs +1 -1
  97. package/dist/network/FetchClient.mjs +1 -1
  98. package/dist/operatingcontext/BaseOperatingContext.mjs +1 -1
  99. package/dist/operatingcontext/NestedAppOperatingContext.mjs +1 -1
  100. package/dist/operatingcontext/StandardOperatingContext.mjs +1 -1
  101. package/dist/operatingcontext/UnknownOperatingContext.mjs +1 -1
  102. package/dist/packageMetadata.d.ts +1 -1
  103. package/dist/packageMetadata.d.ts.map +1 -1
  104. package/dist/packageMetadata.mjs +2 -2
  105. package/dist/request/AuthorizationUrlRequest.d.ts +1 -1
  106. package/dist/request/AuthorizationUrlRequest.d.ts.map +1 -1
  107. package/dist/request/PopupRequest.d.ts +1 -1
  108. package/dist/request/PopupRequest.d.ts.map +1 -1
  109. package/dist/request/RedirectRequest.d.ts +1 -1
  110. package/dist/request/RedirectRequest.d.ts.map +1 -1
  111. package/dist/request/RequestHelpers.mjs +1 -1
  112. package/dist/request/SsoSilentRequest.d.ts +1 -1
  113. package/dist/request/SsoSilentRequest.d.ts.map +1 -1
  114. package/dist/response/ResponseHandler.mjs +1 -1
  115. package/dist/telemetry/BrowserPerformanceClient.mjs +1 -1
  116. package/dist/telemetry/BrowserPerformanceMeasurement.mjs +1 -1
  117. package/dist/utils/BrowserConstants.mjs +1 -1
  118. package/dist/utils/BrowserProtocolUtils.mjs +1 -1
  119. package/dist/utils/BrowserUtils.d.ts.map +1 -1
  120. package/dist/utils/BrowserUtils.mjs +4 -2
  121. package/dist/utils/BrowserUtils.mjs.map +1 -1
  122. package/lib/msal-browser.cjs +238 -197
  123. package/lib/msal-browser.cjs.map +1 -1
  124. package/lib/msal-browser.js +238 -197
  125. package/lib/msal-browser.js.map +1 -1
  126. package/lib/msal-browser.min.js +63 -63
  127. package/lib/types/broker/nativeBroker/NativeMessageHandler.d.ts +1 -1
  128. package/lib/types/broker/nativeBroker/NativeMessageHandler.d.ts.map +1 -1
  129. package/lib/types/broker/nativeBroker/NativeResponse.d.ts +1 -1
  130. package/lib/types/cache/BrowserCacheManager.d.ts +9 -9
  131. package/lib/types/cache/BrowserCacheManager.d.ts.map +1 -1
  132. package/lib/types/cache/IWindowStorage.d.ts +2 -2
  133. package/lib/types/cache/IWindowStorage.d.ts.map +1 -1
  134. package/lib/types/cache/LocalStorage.d.ts +7 -3
  135. package/lib/types/cache/LocalStorage.d.ts.map +1 -1
  136. package/lib/types/cache/TokenCache.d.ts.map +1 -1
  137. package/lib/types/config/Configuration.d.ts +2 -2
  138. package/lib/types/config/Configuration.d.ts.map +1 -1
  139. package/lib/types/controllers/NestedAppAuthController.d.ts +4 -3
  140. package/lib/types/controllers/NestedAppAuthController.d.ts.map +1 -1
  141. package/lib/types/controllers/StandardController.d.ts +2 -2
  142. package/lib/types/controllers/StandardController.d.ts.map +1 -1
  143. package/lib/types/controllers/UnknownOperatingContextController.d.ts +2 -2
  144. package/lib/types/controllers/UnknownOperatingContextController.d.ts.map +1 -1
  145. package/lib/types/crypto/BrowserCrypto.d.ts +1 -1
  146. package/lib/types/crypto/BrowserCrypto.d.ts.map +1 -1
  147. package/lib/types/crypto/CryptoOps.d.ts +1 -1
  148. package/lib/types/crypto/CryptoOps.d.ts.map +1 -1
  149. package/lib/types/interaction_client/NativeInteractionClient.d.ts +1 -1
  150. package/lib/types/interaction_client/NativeInteractionClient.d.ts.map +1 -1
  151. package/lib/types/interaction_client/PopupClient.d.ts.map +1 -1
  152. package/lib/types/packageMetadata.d.ts +1 -1
  153. package/lib/types/packageMetadata.d.ts.map +1 -1
  154. package/lib/types/request/AuthorizationUrlRequest.d.ts +1 -1
  155. package/lib/types/request/AuthorizationUrlRequest.d.ts.map +1 -1
  156. package/lib/types/request/PopupRequest.d.ts +1 -1
  157. package/lib/types/request/PopupRequest.d.ts.map +1 -1
  158. package/lib/types/request/RedirectRequest.d.ts +1 -1
  159. package/lib/types/request/RedirectRequest.d.ts.map +1 -1
  160. package/lib/types/request/SsoSilentRequest.d.ts +1 -1
  161. package/lib/types/request/SsoSilentRequest.d.ts.map +1 -1
  162. package/lib/types/utils/BrowserUtils.d.ts.map +1 -1
  163. package/package.json +2 -2
  164. package/src/broker/nativeBroker/NativeMessageHandler.ts +7 -7
  165. package/src/broker/nativeBroker/NativeResponse.ts +1 -1
  166. package/src/cache/BrowserCacheManager.ts +56 -30
  167. package/src/cache/IWindowStorage.ts +2 -2
  168. package/src/cache/LocalStorage.ts +142 -43
  169. package/src/cache/TokenCache.ts +28 -11
  170. package/src/config/Configuration.ts +6 -6
  171. package/src/controllers/NestedAppAuthController.ts +15 -7
  172. package/src/controllers/StandardController.ts +41 -24
  173. package/src/controllers/UnknownOperatingContextController.ts +6 -5
  174. package/src/crypto/BrowserCrypto.ts +4 -2
  175. package/src/crypto/CryptoOps.ts +8 -2
  176. package/src/interaction_client/NativeInteractionClient.ts +5 -4
  177. package/src/interaction_client/PopupClient.ts +9 -8
  178. package/src/interaction_client/RedirectClient.ts +1 -1
  179. package/src/interaction_client/SilentIframeClient.ts +1 -1
  180. package/src/packageMetadata.ts +1 -1
  181. package/src/request/AuthorizationUrlRequest.ts +1 -1
  182. package/src/request/PopupRequest.ts +1 -1
  183. package/src/request/RedirectRequest.ts +1 -1
  184. package/src/request/SsoSilentRequest.ts +1 -1
  185. package/src/utils/BrowserUtils.ts +3 -1
@@ -372,16 +372,16 @@ export class NativeMessageHandler {
372
372
  * @param nativeExtensionProvider
373
373
  * @param authenticationScheme
374
374
  */
375
- static isNativeAvailable(
375
+ static isPlatformBrokerAvailable(
376
376
  config: BrowserConfiguration,
377
377
  logger: Logger,
378
378
  nativeExtensionProvider?: NativeMessageHandler,
379
379
  authenticationScheme?: AuthenticationScheme
380
380
  ): boolean {
381
- logger.trace("isNativeAvailable called");
382
- if (!config.system.allowNativeBroker) {
381
+ logger.trace("isPlatformBrokerAvailable called");
382
+ if (!config.system.allowPlatformBroker) {
383
383
  logger.trace(
384
- "isNativeAvailable: allowNativeBroker is not enabled, returning false"
384
+ "isPlatformBrokerAvailable: allowPlatformBroker is not enabled, returning false"
385
385
  );
386
386
  // Developer disabled WAM
387
387
  return false;
@@ -389,7 +389,7 @@ export class NativeMessageHandler {
389
389
 
390
390
  if (!nativeExtensionProvider) {
391
391
  logger.trace(
392
- "isNativeAvailable: WAM extension provider is not initialized, returning false"
392
+ "isPlatformBrokerAvailable: Platform extension provider is not initialized, returning false"
393
393
  );
394
394
  // Extension is not available
395
395
  return false;
@@ -400,12 +400,12 @@ export class NativeMessageHandler {
400
400
  case AuthenticationScheme.BEARER:
401
401
  case AuthenticationScheme.POP:
402
402
  logger.trace(
403
- "isNativeAvailable: authenticationScheme is supported, returning true"
403
+ "isPlatformBrokerAvailable: authenticationScheme is supported, returning true"
404
404
  );
405
405
  return true;
406
406
  default:
407
407
  logger.trace(
408
- "isNativeAvailable: authenticationScheme is not supported, returning false"
408
+ "isPlatformBrokerAvailable: authenticationScheme is not supported, returning false"
409
409
  );
410
410
  return false;
411
411
  }
@@ -13,7 +13,7 @@ export type NativeAccountInfo = {
13
13
  };
14
14
 
15
15
  /**
16
- * Token response returned by Native Platform e.g. WAM
16
+ * Token response returned by Native Platform
17
17
  */
18
18
  export type NativeResponse = {
19
19
  access_token: string;
@@ -37,6 +37,7 @@ import {
37
37
  CacheHelpers,
38
38
  StoreInCache,
39
39
  CacheError,
40
+ invokeAsync,
40
41
  } from "@azure/msal-common/browser";
41
42
  import { CacheOptions } from "../config/Configuration.js";
42
43
  import {
@@ -85,15 +86,15 @@ export class BrowserCacheManager extends CacheManager {
85
86
  // Logger instance
86
87
  protected logger: Logger;
87
88
  // Telemetry perf client
88
- protected performanceClient?: IPerformanceClient;
89
+ protected performanceClient: IPerformanceClient;
89
90
 
90
91
  constructor(
91
92
  clientId: string,
92
93
  cacheConfig: Required<CacheOptions>,
93
94
  cryptoImpl: ICrypto,
94
95
  logger: Logger,
95
- staticAuthorityOptions?: StaticAuthorityOptions,
96
- performanceClient?: IPerformanceClient
96
+ performanceClient: IPerformanceClient,
97
+ staticAuthorityOptions?: StaticAuthorityOptions
97
98
  ) {
98
99
  super(clientId, cryptoImpl, logger, staticAuthorityOptions);
99
100
  this.cacheConfig = cacheConfig;
@@ -110,8 +111,8 @@ export class BrowserCacheManager extends CacheManager {
110
111
  this.performanceClient = performanceClient;
111
112
  }
112
113
 
113
- async initialize(): Promise<void> {
114
- await this.browserStorage.initialize();
114
+ async initialize(correlationId: string): Promise<void> {
115
+ await this.browserStorage.initialize(correlationId);
115
116
  }
116
117
 
117
118
  /**
@@ -124,7 +125,11 @@ export class BrowserCacheManager extends CacheManager {
124
125
  try {
125
126
  switch (cacheLocation) {
126
127
  case BrowserCacheLocation.LocalStorage:
127
- return new LocalStorage(this.clientId);
128
+ return new LocalStorage(
129
+ this.clientId,
130
+ this.logger,
131
+ this.performanceClient
132
+ );
128
133
  case BrowserCacheLocation.SessionStorage:
129
134
  return new SessionStorage();
130
135
  case BrowserCacheLocation.MemoryStorage:
@@ -189,10 +194,18 @@ export class BrowserCacheManager extends CacheManager {
189
194
  * set account entity in the platform cache
190
195
  * @param account
191
196
  */
192
- async setAccount(account: AccountEntity): Promise<void> {
197
+ async setAccount(
198
+ account: AccountEntity,
199
+ correlationId: string
200
+ ): Promise<void> {
193
201
  this.logger.trace("BrowserCacheManager.setAccount called");
194
202
  const key = account.generateAccountKey();
195
- await this.browserStorage.setUserData(key, JSON.stringify(account));
203
+ await invokeAsync(
204
+ this.browserStorage.setUserData.bind(this.browserStorage),
205
+ PerformanceEvents.SetUserData,
206
+ this.logger,
207
+ this.performanceClient
208
+ )(key, JSON.stringify(account), correlationId);
196
209
  this.addAccountKeyToMap(key);
197
210
  }
198
211
 
@@ -457,14 +470,19 @@ export class BrowserCacheManager extends CacheManager {
457
470
  * set IdToken credential to the platform cache
458
471
  * @param idToken
459
472
  */
460
- async setIdTokenCredential(idToken: IdTokenEntity): Promise<void> {
473
+ async setIdTokenCredential(
474
+ idToken: IdTokenEntity,
475
+ correlationId: string
476
+ ): Promise<void> {
461
477
  this.logger.trace("BrowserCacheManager.setIdTokenCredential called");
462
478
  const idTokenKey = CacheHelpers.generateCredentialKey(idToken);
463
479
 
464
- await this.browserStorage.setUserData(
465
- idTokenKey,
466
- JSON.stringify(idToken)
467
- );
480
+ await invokeAsync(
481
+ this.browserStorage.setUserData.bind(this.browserStorage),
482
+ PerformanceEvents.SetUserData,
483
+ this.logger,
484
+ this.performanceClient
485
+ )(idTokenKey, JSON.stringify(idToken), correlationId);
468
486
 
469
487
  this.addTokenKey(idTokenKey, CredentialType.ID_TOKEN);
470
488
  }
@@ -505,16 +523,19 @@ export class BrowserCacheManager extends CacheManager {
505
523
  * @param accessToken
506
524
  */
507
525
  async setAccessTokenCredential(
508
- accessToken: AccessTokenEntity
526
+ accessToken: AccessTokenEntity,
527
+ correlationId: string
509
528
  ): Promise<void> {
510
529
  this.logger.trace(
511
530
  "BrowserCacheManager.setAccessTokenCredential called"
512
531
  );
513
532
  const accessTokenKey = CacheHelpers.generateCredentialKey(accessToken);
514
- await this.browserStorage.setUserData(
515
- accessTokenKey,
516
- JSON.stringify(accessToken)
517
- );
533
+ await invokeAsync(
534
+ this.browserStorage.setUserData.bind(this.browserStorage),
535
+ PerformanceEvents.SetUserData,
536
+ this.logger,
537
+ this.performanceClient
538
+ )(accessTokenKey, JSON.stringify(accessToken), correlationId);
518
539
 
519
540
  this.addTokenKey(accessTokenKey, CredentialType.ACCESS_TOKEN);
520
541
  }
@@ -557,17 +578,20 @@ export class BrowserCacheManager extends CacheManager {
557
578
  * @param refreshToken
558
579
  */
559
580
  async setRefreshTokenCredential(
560
- refreshToken: RefreshTokenEntity
581
+ refreshToken: RefreshTokenEntity,
582
+ correlationId: string
561
583
  ): Promise<void> {
562
584
  this.logger.trace(
563
585
  "BrowserCacheManager.setRefreshTokenCredential called"
564
586
  );
565
587
  const refreshTokenKey =
566
588
  CacheHelpers.generateCredentialKey(refreshToken);
567
- await this.browserStorage.setUserData(
568
- refreshTokenKey,
569
- JSON.stringify(refreshToken)
570
- );
589
+ await invokeAsync(
590
+ this.browserStorage.setUserData.bind(this.browserStorage),
591
+ PerformanceEvents.SetUserData,
592
+ this.logger,
593
+ this.performanceClient
594
+ )(refreshTokenKey, JSON.stringify(refreshToken), correlationId);
571
595
 
572
596
  this.addTokenKey(refreshTokenKey, CredentialType.REFRESH_TOKEN);
573
597
  }
@@ -1404,7 +1428,7 @@ export class BrowserCacheManager extends CacheManager {
1404
1428
  idToken: idTokenEntity,
1405
1429
  accessToken: accessTokenEntity,
1406
1430
  };
1407
- return this.saveCacheRecord(cacheRecord);
1431
+ return this.saveCacheRecord(cacheRecord, result.correlationId);
1408
1432
  }
1409
1433
 
1410
1434
  /**
@@ -1415,14 +1439,14 @@ export class BrowserCacheManager extends CacheManager {
1415
1439
  */
1416
1440
  async saveCacheRecord(
1417
1441
  cacheRecord: CacheRecord,
1418
- storeInCache?: StoreInCache,
1419
- correlationId?: string
1442
+ correlationId: string,
1443
+ storeInCache?: StoreInCache
1420
1444
  ): Promise<void> {
1421
1445
  try {
1422
1446
  await super.saveCacheRecord(
1423
1447
  cacheRecord,
1424
- storeInCache,
1425
- correlationId
1448
+ correlationId,
1449
+ storeInCache
1426
1450
  );
1427
1451
  } catch (e) {
1428
1452
  if (
@@ -1451,7 +1475,8 @@ export class BrowserCacheManager extends CacheManager {
1451
1475
 
1452
1476
  export const DEFAULT_BROWSER_CACHE_MANAGER = (
1453
1477
  clientId: string,
1454
- logger: Logger
1478
+ logger: Logger,
1479
+ performanceClient: IPerformanceClient
1455
1480
  ): BrowserCacheManager => {
1456
1481
  const cacheOptions: Required<CacheOptions> = {
1457
1482
  cacheLocation: BrowserCacheLocation.MemoryStorage,
@@ -1465,6 +1490,7 @@ export const DEFAULT_BROWSER_CACHE_MANAGER = (
1465
1490
  clientId,
1466
1491
  cacheOptions,
1467
1492
  DEFAULT_CRYPTO_IMPLEMENTATION,
1468
- logger
1493
+ logger,
1494
+ performanceClient
1469
1495
  );
1470
1496
  };
@@ -7,7 +7,7 @@ export interface IWindowStorage<T> {
7
7
  /**
8
8
  * Async initializer
9
9
  */
10
- initialize(): Promise<void>;
10
+ initialize(correlationId: string): Promise<void>;
11
11
  /**
12
12
  * Get the item from the window storage object matching the given key.
13
13
  * @param key
@@ -29,7 +29,7 @@ export interface IWindowStorage<T> {
29
29
  /**
30
30
  * Setter for sensitive data that may contain PII.
31
31
  */
32
- setUserData(key: string, value: T): Promise<void>;
32
+ setUserData(key: string, value: T, correlationId: string): Promise<void>;
33
33
 
34
34
  /**
35
35
  * Removes the item in the window storage object matching the given key.
@@ -3,7 +3,15 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { Constants, TokenKeys } from "@azure/msal-common/browser";
6
+ import {
7
+ Constants,
8
+ TokenKeys,
9
+ IPerformanceClient,
10
+ invokeAsync,
11
+ PerformanceEvents,
12
+ Logger,
13
+ invoke,
14
+ } from "@azure/msal-common/browser";
7
15
  import {
8
16
  createNewGuid,
9
17
  decrypt,
@@ -25,6 +33,7 @@ import { CookieStorage } from "./CookieStorage.js";
25
33
  import { IWindowStorage } from "./IWindowStorage.js";
26
34
  import { MemoryStorage } from "./MemoryStorage.js";
27
35
  import { getAccountKeys, getTokenKeys } from "./CacheHelpers.js";
36
+ import { StaticCacheKeys } from "../utils/BrowserConstants.js";
28
37
 
29
38
  const ENCRYPTION_KEY = "msal.cache.encryption";
30
39
 
@@ -43,9 +52,15 @@ export class LocalStorage implements IWindowStorage<string> {
43
52
  private clientId: string;
44
53
  private initialized: boolean;
45
54
  private memoryStorage: MemoryStorage<string>;
55
+ private performanceClient: IPerformanceClient;
56
+ private logger: Logger;
46
57
  private encryptionCookie?: EncryptionCookie;
47
58
 
48
- constructor(clientId: string) {
59
+ constructor(
60
+ clientId: string,
61
+ logger: Logger,
62
+ performanceClient: IPerformanceClient
63
+ ) {
49
64
  if (!window.localStorage) {
50
65
  throw createBrowserConfigurationAuthError(
51
66
  BrowserConfigurationAuthErrorCodes.storageNotSupported
@@ -54,9 +69,11 @@ export class LocalStorage implements IWindowStorage<string> {
54
69
  this.memoryStorage = new MemoryStorage<string>();
55
70
  this.initialized = false;
56
71
  this.clientId = clientId;
72
+ this.logger = logger;
73
+ this.performanceClient = performanceClient;
57
74
  }
58
75
 
59
- async initialize(): Promise<void> {
76
+ async initialize(correlationId: string): Promise<void> {
60
77
  this.initialized = true;
61
78
 
62
79
  const cookies = new CookieStorage();
@@ -65,26 +82,61 @@ export class LocalStorage implements IWindowStorage<string> {
65
82
  if (cookieString) {
66
83
  try {
67
84
  parsedCookie = JSON.parse(cookieString);
68
- } catch (e) {
69
- // TODO: Log telemetry but don't throw
70
- }
85
+ } catch (e) {}
71
86
  }
72
87
  if (parsedCookie.key && parsedCookie.id) {
73
88
  // Encryption key already exists, import
89
+ const baseKey = invoke(
90
+ base64DecToArr,
91
+ PerformanceEvents.Base64Decode,
92
+ this.logger,
93
+ this.performanceClient,
94
+ correlationId
95
+ )(parsedCookie.key);
74
96
  this.encryptionCookie = {
75
97
  id: parsedCookie.id,
76
- key: await generateHKDF(base64DecToArr(parsedCookie.key)),
98
+ key: await invokeAsync(
99
+ generateHKDF,
100
+ PerformanceEvents.GenerateHKDF,
101
+ this.logger,
102
+ this.performanceClient,
103
+ correlationId
104
+ )(baseKey),
77
105
  };
78
- await this.importExistingCache();
106
+ await invokeAsync(
107
+ this.importExistingCache.bind(this),
108
+ PerformanceEvents.ImportExistingCache,
109
+ this.logger,
110
+ this.performanceClient,
111
+ correlationId
112
+ )(correlationId);
79
113
  } else {
80
114
  // Encryption key doesn't exist or is invalid, generate a new one and clear existing cache
81
115
  this.clear();
82
116
  const id = createNewGuid();
83
- const baseKey = await generateBaseKey();
84
- const keyStr = urlEncodeArr(new Uint8Array(baseKey));
117
+ const baseKey = await invokeAsync(
118
+ generateBaseKey,
119
+ PerformanceEvents.GenerateBaseKey,
120
+ this.logger,
121
+ this.performanceClient,
122
+ correlationId
123
+ )();
124
+ const keyStr = invoke(
125
+ urlEncodeArr,
126
+ PerformanceEvents.UrlEncodeArr,
127
+ this.logger,
128
+ this.performanceClient,
129
+ correlationId
130
+ )(new Uint8Array(baseKey));
85
131
  this.encryptionCookie = {
86
132
  id: id,
87
- key: await generateHKDF(baseKey),
133
+ key: await invokeAsync(
134
+ generateHKDF,
135
+ PerformanceEvents.GenerateHKDF,
136
+ this.logger,
137
+ this.performanceClient,
138
+ correlationId
139
+ )(baseKey),
88
140
  };
89
141
 
90
142
  const cookieData = {
@@ -112,18 +164,24 @@ export class LocalStorage implements IWindowStorage<string> {
112
164
  window.localStorage.setItem(key, value);
113
165
  }
114
166
 
115
- async setUserData(key: string, value: string): Promise<void> {
167
+ async setUserData(
168
+ key: string,
169
+ value: string,
170
+ correlationId: string
171
+ ): Promise<void> {
116
172
  if (!this.initialized || !this.encryptionCookie) {
117
173
  throw createBrowserAuthError(
118
174
  BrowserAuthErrorCodes.uninitializedPublicClientApplication
119
175
  );
120
176
  }
121
177
 
122
- const { data, nonce } = await encrypt(
123
- this.encryptionCookie.key,
124
- value,
125
- this.getContext(key)
126
- );
178
+ const { data, nonce } = await invokeAsync(
179
+ encrypt,
180
+ PerformanceEvents.Encrypt,
181
+ this.logger,
182
+ this.performanceClient,
183
+ correlationId
184
+ )(this.encryptionCookie.key, value, this.getContext(key));
127
185
  const encryptedData: EncryptedData = {
128
186
  id: this.encryptionCookie.id,
129
187
  nonce: nonce,
@@ -176,20 +234,34 @@ export class LocalStorage implements IWindowStorage<string> {
176
234
  * Helper to decrypt all known MSAL keys in localStorage and save them to inMemory storage
177
235
  * @returns
178
236
  */
179
- private async importExistingCache(): Promise<void> {
237
+ private async importExistingCache(correlationId: string): Promise<void> {
180
238
  if (!this.encryptionCookie) {
181
239
  return;
182
240
  }
183
241
 
184
- const accountKeys = getAccountKeys(this);
185
- await this.importArray(accountKeys);
242
+ let accountKeys = getAccountKeys(this);
243
+ accountKeys = await this.importArray(accountKeys, correlationId);
244
+ // Write valid account keys back to map
245
+ this.setItem(StaticCacheKeys.ACCOUNT_KEYS, JSON.stringify(accountKeys));
186
246
 
187
247
  const tokenKeys: TokenKeys = getTokenKeys(this.clientId, this);
188
- await Promise.all([
189
- this.importArray(tokenKeys.idToken),
190
- this.importArray(tokenKeys.accessToken),
191
- this.importArray(tokenKeys.refreshToken),
192
- ]);
248
+ tokenKeys.idToken = await this.importArray(
249
+ tokenKeys.idToken,
250
+ correlationId
251
+ );
252
+ tokenKeys.accessToken = await this.importArray(
253
+ tokenKeys.accessToken,
254
+ correlationId
255
+ );
256
+ tokenKeys.refreshToken = await this.importArray(
257
+ tokenKeys.refreshToken,
258
+ correlationId
259
+ );
260
+ // Write valid token keys back to map
261
+ this.setItem(
262
+ `${StaticCacheKeys.TOKEN_KEYS}.${this.clientId}`,
263
+ JSON.stringify(tokenKeys)
264
+ );
193
265
  }
194
266
 
195
267
  /**
@@ -198,7 +270,8 @@ export class LocalStorage implements IWindowStorage<string> {
198
270
  * @returns
199
271
  */
200
272
  private async getItemFromEncryptedCache(
201
- key: string
273
+ key: string,
274
+ correlationId: string
202
275
  ): Promise<string | null> {
203
276
  if (!this.encryptionCookie) {
204
277
  return null;
@@ -212,21 +285,36 @@ export class LocalStorage implements IWindowStorage<string> {
212
285
  let encObj: EncryptedData;
213
286
  try {
214
287
  encObj = JSON.parse(rawCache);
215
- if (!encObj.id || !encObj.nonce || !encObj.data) {
216
- throw "Not encrypted!"; // TODO: Typed error
217
- }
218
-
219
- if (encObj.id !== this.encryptionCookie.id) {
220
- throw "Old item!"; // TODO: Typed error
221
- }
222
288
  } catch (e) {
223
289
  // Not a valid encrypted object, remove
224
- this.removeItem(key);
225
- // TODO: Log to telemetry
226
290
  return null;
227
291
  }
228
292
 
229
- return decrypt(
293
+ if (!encObj.id || !encObj.nonce || !encObj.data) {
294
+ // Data is not encrypted, likely from old version of MSAL. It must be removed because we don't know how old it is.
295
+ this.performanceClient.incrementFields(
296
+ { unencryptedCacheCount: 1 },
297
+ correlationId
298
+ );
299
+ return null;
300
+ }
301
+
302
+ if (encObj.id !== this.encryptionCookie.id) {
303
+ // Data was encrypted with a different key. It must be removed because it is from a previous session.
304
+ this.performanceClient.incrementFields(
305
+ { encryptedCacheExpiredCount: 1 },
306
+ correlationId
307
+ );
308
+ return null;
309
+ }
310
+
311
+ return invokeAsync(
312
+ decrypt,
313
+ PerformanceEvents.Decrypt,
314
+ this.logger,
315
+ this.performanceClient,
316
+ correlationId
317
+ )(
230
318
  this.encryptionCookie.key,
231
319
  encObj.nonce,
232
320
  this.getContext(key),
@@ -237,21 +325,32 @@ export class LocalStorage implements IWindowStorage<string> {
237
325
  /**
238
326
  * Helper to decrypt and save an array of cache keys
239
327
  * @param arr
328
+ * @returns Array of keys successfully imported
240
329
  */
241
- private async importArray(arr: Array<string>): Promise<void> {
330
+ private async importArray(
331
+ arr: Array<string>,
332
+ correlationId: string
333
+ ): Promise<Array<string>> {
334
+ const importedArr: Array<string> = [];
242
335
  const promiseArr: Array<Promise<void>> = [];
243
336
  arr.forEach((key) => {
244
- const promise = this.getItemFromEncryptedCache(key).then(
245
- (value) => {
246
- if (value) {
247
- this.memoryStorage.setItem(key, value);
248
- }
337
+ const promise = this.getItemFromEncryptedCache(
338
+ key,
339
+ correlationId
340
+ ).then((value) => {
341
+ if (value) {
342
+ this.memoryStorage.setItem(key, value);
343
+ importedArr.push(key);
344
+ } else {
345
+ // If value is empty, unencrypted or expired remove
346
+ this.removeItem(key);
249
347
  }
250
- );
348
+ });
251
349
  promiseArr.push(promise);
252
350
  });
253
351
 
254
352
  await Promise.all(promiseArr);
353
+ return importedArr;
255
354
  }
256
355
 
257
356
  /**
@@ -86,6 +86,9 @@ export class TokenCache implements ITokenCache {
86
86
  );
87
87
  }
88
88
 
89
+ const correlationId =
90
+ request.correlationId || BrowserCrypto.createNewGuid();
91
+
89
92
  const idTokenClaims = response.id_token
90
93
  ? AuthToken.extractTokenClaims(response.id_token, base64Decode)
91
94
  : undefined;
@@ -115,6 +118,7 @@ export class TokenCache implements ITokenCache {
115
118
  const cacheRecordAccount: AccountEntity = await this.loadAccount(
116
119
  request,
117
120
  options.clientInfo || response.client_info || "",
121
+ correlationId,
118
122
  idTokenClaims,
119
123
  authority
120
124
  );
@@ -123,7 +127,8 @@ export class TokenCache implements ITokenCache {
123
127
  response,
124
128
  cacheRecordAccount.homeAccountId,
125
129
  cacheRecordAccount.environment,
126
- cacheRecordAccount.realm
130
+ cacheRecordAccount.realm,
131
+ correlationId
127
132
  );
128
133
 
129
134
  const accessToken = await this.loadAccessToken(
@@ -132,13 +137,15 @@ export class TokenCache implements ITokenCache {
132
137
  cacheRecordAccount.homeAccountId,
133
138
  cacheRecordAccount.environment,
134
139
  cacheRecordAccount.realm,
135
- options
140
+ options,
141
+ correlationId
136
142
  );
137
143
 
138
144
  const refreshToken = await this.loadRefreshToken(
139
145
  response,
140
146
  cacheRecordAccount.homeAccountId,
141
- cacheRecordAccount.environment
147
+ cacheRecordAccount.environment,
148
+ correlationId
142
149
  );
143
150
 
144
151
  return this.generateAuthenticationResult(
@@ -166,6 +173,7 @@ export class TokenCache implements ITokenCache {
166
173
  private async loadAccount(
167
174
  request: SilentRequest,
168
175
  clientInfo: string,
176
+ correlationId: string,
169
177
  idTokenClaims?: TokenClaims,
170
178
  authority?: Authority
171
179
  ): Promise<AccountEntity> {
@@ -175,7 +183,7 @@ export class TokenCache implements ITokenCache {
175
183
  const accountEntity = AccountEntity.createFromAccountInfo(
176
184
  request.account
177
185
  );
178
- await this.storage.setAccount(accountEntity);
186
+ await this.storage.setAccount(accountEntity, correlationId);
179
187
  return accountEntity;
180
188
  } else if (!authority || (!clientInfo && !idTokenClaims)) {
181
189
  this.logger.error(
@@ -210,7 +218,7 @@ export class TokenCache implements ITokenCache {
210
218
  this.logger
211
219
  );
212
220
 
213
- await this.storage.setAccount(cachedAccount);
221
+ await this.storage.setAccount(cachedAccount, correlationId);
214
222
  return cachedAccount;
215
223
  }
216
224
 
@@ -226,7 +234,8 @@ export class TokenCache implements ITokenCache {
226
234
  response: ExternalTokenResponse,
227
235
  homeAccountId: string,
228
236
  environment: string,
229
- tenantId: string
237
+ tenantId: string,
238
+ correlationId: string
230
239
  ): Promise<IdTokenEntity | null> {
231
240
  if (!response.id_token) {
232
241
  this.logger.verbose("TokenCache - no id token found in response");
@@ -242,7 +251,7 @@ export class TokenCache implements ITokenCache {
242
251
  tenantId
243
252
  );
244
253
 
245
- await this.storage.setIdTokenCredential(idTokenEntity);
254
+ await this.storage.setIdTokenCredential(idTokenEntity, correlationId);
246
255
  return idTokenEntity;
247
256
  }
248
257
 
@@ -261,7 +270,8 @@ export class TokenCache implements ITokenCache {
261
270
  homeAccountId: string,
262
271
  environment: string,
263
272
  tenantId: string,
264
- options: LoadTokenOptions
273
+ options: LoadTokenOptions,
274
+ correlationId: string
265
275
  ): Promise<AccessTokenEntity | null> {
266
276
  if (!response.access_token) {
267
277
  this.logger.verbose(
@@ -309,7 +319,10 @@ export class TokenCache implements ITokenCache {
309
319
  base64Decode
310
320
  );
311
321
 
312
- await this.storage.setAccessTokenCredential(accessTokenEntity);
322
+ await this.storage.setAccessTokenCredential(
323
+ accessTokenEntity,
324
+ correlationId
325
+ );
313
326
  return accessTokenEntity;
314
327
  }
315
328
 
@@ -324,7 +337,8 @@ export class TokenCache implements ITokenCache {
324
337
  private async loadRefreshToken(
325
338
  response: ExternalTokenResponse,
326
339
  homeAccountId: string,
327
- environment: string
340
+ environment: string,
341
+ correlationId: string
328
342
  ): Promise<RefreshTokenEntity | null> {
329
343
  if (!response.refresh_token) {
330
344
  this.logger.verbose(
@@ -344,7 +358,10 @@ export class TokenCache implements ITokenCache {
344
358
  response.refresh_token_expires_in
345
359
  );
346
360
 
347
- await this.storage.setRefreshTokenCredential(refreshTokenEntity);
361
+ await this.storage.setRefreshTokenCredential(
362
+ refreshTokenEntity,
363
+ correlationId
364
+ );
348
365
  return refreshTokenEntity;
349
366
  }
350
367