@azure/msal-common 15.9.0 → 15.10.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 (143) hide show
  1. package/dist/account/AccountInfo.d.ts +2 -1
  2. package/dist/account/AccountInfo.d.ts.map +1 -1
  3. package/dist/account/AccountInfo.mjs +5 -2
  4. package/dist/account/AccountInfo.mjs.map +1 -1
  5. package/dist/account/AuthToken.mjs +1 -1
  6. package/dist/account/CcsCredential.mjs +1 -1
  7. package/dist/account/ClientInfo.mjs +1 -1
  8. package/dist/account/TokenClaims.mjs +1 -1
  9. package/dist/authority/Authority.mjs +1 -1
  10. package/dist/authority/AuthorityFactory.mjs +1 -1
  11. package/dist/authority/AuthorityMetadata.mjs +1 -1
  12. package/dist/authority/AuthorityOptions.mjs +1 -1
  13. package/dist/authority/AuthorityType.mjs +1 -1
  14. package/dist/authority/CloudInstanceDiscoveryErrorResponse.mjs +1 -1
  15. package/dist/authority/CloudInstanceDiscoveryResponse.mjs +1 -1
  16. package/dist/authority/OpenIdConfigResponse.mjs +1 -1
  17. package/dist/authority/ProtocolMode.mjs +1 -1
  18. package/dist/authority/RegionDiscovery.mjs +1 -1
  19. package/dist/cache/CacheManager.d.ts +15 -20
  20. package/dist/cache/CacheManager.d.ts.map +1 -1
  21. package/dist/cache/CacheManager.mjs +32 -97
  22. package/dist/cache/CacheManager.mjs.map +1 -1
  23. package/dist/cache/entities/AccountEntity.d.ts +2 -14
  24. package/dist/cache/entities/AccountEntity.d.ts.map +1 -1
  25. package/dist/cache/entities/AccountEntity.mjs +6 -34
  26. package/dist/cache/entities/AccountEntity.mjs.map +1 -1
  27. package/dist/cache/entities/CredentialEntity.d.ts +1 -1
  28. package/dist/cache/entities/CredentialEntity.d.ts.map +1 -1
  29. package/dist/cache/interface/ICacheManager.d.ts +2 -10
  30. package/dist/cache/interface/ICacheManager.d.ts.map +1 -1
  31. package/dist/cache/persistence/TokenCacheContext.mjs +1 -1
  32. package/dist/cache/utils/CacheHelpers.d.ts +4 -13
  33. package/dist/cache/utils/CacheHelpers.d.ts.map +1 -1
  34. package/dist/cache/utils/CacheHelpers.mjs +6 -71
  35. package/dist/cache/utils/CacheHelpers.mjs.map +1 -1
  36. package/dist/client/AuthorizationCodeClient.mjs +1 -1
  37. package/dist/client/BaseClient.mjs +1 -1
  38. package/dist/client/RefreshTokenClient.d.ts.map +1 -1
  39. package/dist/client/RefreshTokenClient.mjs +2 -3
  40. package/dist/client/RefreshTokenClient.mjs.map +1 -1
  41. package/dist/client/SilentFlowClient.mjs +2 -2
  42. package/dist/client/SilentFlowClient.mjs.map +1 -1
  43. package/dist/config/ClientConfiguration.mjs +1 -1
  44. package/dist/constants/AADServerParamKeys.mjs +1 -1
  45. package/dist/crypto/ICrypto.mjs +1 -1
  46. package/dist/crypto/JoseHeader.mjs +1 -1
  47. package/dist/crypto/PopTokenGenerator.mjs +1 -1
  48. package/dist/error/AuthError.mjs +1 -1
  49. package/dist/error/AuthErrorCodes.mjs +1 -1
  50. package/dist/error/CacheError.mjs +1 -1
  51. package/dist/error/CacheErrorCodes.mjs +1 -1
  52. package/dist/error/ClientAuthError.mjs +1 -1
  53. package/dist/error/ClientAuthErrorCodes.mjs +1 -1
  54. package/dist/error/ClientConfigurationError.mjs +1 -1
  55. package/dist/error/ClientConfigurationErrorCodes.mjs +1 -1
  56. package/dist/error/InteractionRequiredAuthError.mjs +1 -1
  57. package/dist/error/InteractionRequiredAuthErrorCodes.mjs +1 -1
  58. package/dist/error/JoseHeaderError.mjs +1 -1
  59. package/dist/error/JoseHeaderErrorCodes.mjs +1 -1
  60. package/dist/error/NetworkError.mjs +1 -1
  61. package/dist/error/ServerError.mjs +1 -1
  62. package/dist/index-browser.mjs +1 -1
  63. package/dist/index-node.mjs +1 -1
  64. package/dist/index.mjs +1 -1
  65. package/dist/logger/Logger.mjs +1 -1
  66. package/dist/network/INetworkModule.mjs +1 -1
  67. package/dist/network/RequestThumbprint.mjs +1 -1
  68. package/dist/network/ThrottlingUtils.mjs +1 -1
  69. package/dist/packageMetadata.d.ts +1 -1
  70. package/dist/packageMetadata.d.ts.map +1 -1
  71. package/dist/packageMetadata.mjs +2 -2
  72. package/dist/protocol/Authorize.mjs +2 -2
  73. package/dist/protocol/Authorize.mjs.map +1 -1
  74. package/dist/request/AuthenticationHeaderParser.mjs +1 -1
  75. package/dist/request/RequestParameterBuilder.mjs +1 -1
  76. package/dist/request/ScopeSet.mjs +1 -1
  77. package/dist/response/ResponseHandler.d.ts.map +1 -1
  78. package/dist/response/ResponseHandler.mjs +3 -3
  79. package/dist/response/ResponseHandler.mjs.map +1 -1
  80. package/dist/telemetry/performance/PerformanceClient.mjs +1 -1
  81. package/dist/telemetry/performance/PerformanceEvent.d.ts +2 -0
  82. package/dist/telemetry/performance/PerformanceEvent.d.ts.map +1 -1
  83. package/dist/telemetry/performance/PerformanceEvent.mjs +11 -1
  84. package/dist/telemetry/performance/PerformanceEvent.mjs.map +1 -1
  85. package/dist/telemetry/performance/StubPerformanceClient.mjs +1 -1
  86. package/dist/telemetry/server/ServerTelemetryManager.mjs +1 -1
  87. package/dist/url/UrlString.mjs +1 -1
  88. package/dist/utils/ClientAssertionUtils.mjs +1 -1
  89. package/dist/utils/Constants.d.ts +0 -1
  90. package/dist/utils/Constants.d.ts.map +1 -1
  91. package/dist/utils/Constants.mjs +1 -3
  92. package/dist/utils/Constants.mjs.map +1 -1
  93. package/dist/utils/FunctionWrappers.mjs +1 -1
  94. package/dist/utils/ProtocolUtils.mjs +1 -1
  95. package/dist/utils/StringUtils.mjs +1 -1
  96. package/dist/utils/TimeUtils.d.ts +7 -0
  97. package/dist/utils/TimeUtils.d.ts.map +1 -1
  98. package/dist/utils/TimeUtils.mjs +12 -2
  99. package/dist/utils/TimeUtils.mjs.map +1 -1
  100. package/dist/utils/UrlUtils.mjs +1 -1
  101. package/lib/index-browser.cjs +2 -2
  102. package/lib/{index-node-C5c-lcoe.js → index-node-Dy4fVJGl.js} +460 -595
  103. package/lib/index-node-Dy4fVJGl.js.map +1 -0
  104. package/lib/index-node.cjs +2 -2
  105. package/lib/index.cjs +2 -2
  106. package/lib/types/account/AccountInfo.d.ts +2 -1
  107. package/lib/types/account/AccountInfo.d.ts.map +1 -1
  108. package/lib/types/cache/CacheManager.d.ts +15 -20
  109. package/lib/types/cache/CacheManager.d.ts.map +1 -1
  110. package/lib/types/cache/entities/AccountEntity.d.ts +2 -14
  111. package/lib/types/cache/entities/AccountEntity.d.ts.map +1 -1
  112. package/lib/types/cache/entities/CredentialEntity.d.ts +1 -1
  113. package/lib/types/cache/entities/CredentialEntity.d.ts.map +1 -1
  114. package/lib/types/cache/interface/ICacheManager.d.ts +2 -10
  115. package/lib/types/cache/interface/ICacheManager.d.ts.map +1 -1
  116. package/lib/types/cache/utils/CacheHelpers.d.ts +4 -13
  117. package/lib/types/cache/utils/CacheHelpers.d.ts.map +1 -1
  118. package/lib/types/client/RefreshTokenClient.d.ts.map +1 -1
  119. package/lib/types/packageMetadata.d.ts +1 -1
  120. package/lib/types/packageMetadata.d.ts.map +1 -1
  121. package/lib/types/response/ResponseHandler.d.ts.map +1 -1
  122. package/lib/types/telemetry/performance/PerformanceEvent.d.ts +2 -0
  123. package/lib/types/telemetry/performance/PerformanceEvent.d.ts.map +1 -1
  124. package/lib/types/utils/Constants.d.ts +0 -1
  125. package/lib/types/utils/Constants.d.ts.map +1 -1
  126. package/lib/types/utils/TimeUtils.d.ts +7 -0
  127. package/lib/types/utils/TimeUtils.d.ts.map +1 -1
  128. package/package.json +1 -1
  129. package/src/account/AccountInfo.ts +16 -2
  130. package/src/cache/CacheManager.ts +50 -125
  131. package/src/cache/entities/AccountEntity.ts +7 -38
  132. package/src/cache/entities/CredentialEntity.ts +1 -1
  133. package/src/cache/interface/ICacheManager.ts +2 -15
  134. package/src/cache/utils/CacheHelpers.ts +11 -83
  135. package/src/client/RefreshTokenClient.ts +1 -2
  136. package/src/client/SilentFlowClient.ts +2 -2
  137. package/src/packageMetadata.ts +1 -1
  138. package/src/protocol/Authorize.ts +1 -1
  139. package/src/response/ResponseHandler.ts +3 -1
  140. package/src/telemetry/performance/PerformanceEvent.ts +14 -0
  141. package/src/utils/Constants.ts +0 -2
  142. package/src/utils/TimeUtils.ts +15 -0
  143. package/lib/index-node-C5c-lcoe.js.map +0 -1
@@ -1,4 +1,4 @@
1
- /*! @azure/msal-common v15.9.0 2025-07-23 */
1
+ /*! @azure/msal-common v15.10.0 2025-08-05 */
2
2
  'use strict';
3
3
  'use strict';
4
4
 
@@ -9,8 +9,6 @@
9
9
  const Constants = {
10
10
  LIBRARY_NAME: "MSAL.JS",
11
11
  SKU: "msal.js.common",
12
- // Prefix for all library cache entries
13
- CACHE_PREFIX: "msal",
14
12
  // default authority
15
13
  DEFAULT_AUTHORITY: "https://login.microsoftonline.com/common/",
16
14
  DEFAULT_AUTHORITY_HOST: "login.microsoftonline.com",
@@ -2057,6 +2055,16 @@ const IntFields = new Set([
2057
2055
  "multiMatchedRT",
2058
2056
  "unencryptedCacheCount",
2059
2057
  "encryptedCacheExpiredCount",
2058
+ "oldAccountCount",
2059
+ "oldAccessCount",
2060
+ "oldIdCount",
2061
+ "oldRefreshCount",
2062
+ "currAccountCount",
2063
+ "currAccessCount",
2064
+ "currIdCount",
2065
+ "currRefreshCount",
2066
+ "expiredCacheRemovedCount",
2067
+ "upgradedCacheCount",
2060
2068
  ]);
2061
2069
 
2062
2070
  /*
@@ -2301,6 +2309,16 @@ function isTokenExpired(expiresOn, offset) {
2301
2309
  // If current time + offset is greater than token expiration time, then token is expired.
2302
2310
  return offsetCurrentTimeSec > expirationSec;
2303
2311
  }
2312
+ /**
2313
+ * Checks if a cache entry is expired based on the last updated time and cache retention days.
2314
+ * @param lastUpdatedAt
2315
+ * @param cacheRetentionDays
2316
+ * @returns
2317
+ */
2318
+ function isCacheExpired(lastUpdatedAt, cacheRetentionDays) {
2319
+ const cacheExpirationTimestamp = Number(lastUpdatedAt) + cacheRetentionDays * 24 * 60 * 60 * 1000;
2320
+ return Date.now() > cacheExpirationTimestamp;
2321
+ }
2304
2322
  /**
2305
2323
  * If the current time is earlier than the time that a token was cached at, we must discard the token
2306
2324
  * i.e. The system clock was turned back after acquiring the cached token
@@ -2323,6 +2341,7 @@ function delay(t, value) {
2323
2341
  var TimeUtils = /*#__PURE__*/Object.freeze({
2324
2342
  __proto__: null,
2325
2343
  delay: delay,
2344
+ isCacheExpired: isCacheExpired,
2326
2345
  isTokenExpired: isTokenExpired,
2327
2346
  nowSeconds: nowSeconds,
2328
2347
  toDateFromSeconds: toDateFromSeconds,
@@ -2334,24 +2353,6 @@ var TimeUtils = /*#__PURE__*/Object.freeze({
2334
2353
  * Copyright (c) Microsoft Corporation. All rights reserved.
2335
2354
  * Licensed under the MIT License.
2336
2355
  */
2337
- /**
2338
- * Cache Key: <home_account_id>-<environment>-<credential_type>-<client_id or familyId>-<realm>-<scopes>-<claims hash>-<scheme>
2339
- * IdToken Example: uid.utid-login.microsoftonline.com-idtoken-app_client_id-contoso.com
2340
- * AccessToken Example: uid.utid-login.microsoftonline.com-accesstoken-app_client_id-contoso.com-scope1 scope2--pop
2341
- * RefreshToken Example: uid.utid-login.microsoftonline.com-refreshtoken-1-contoso.com
2342
- * @param credentialEntity
2343
- * @returns
2344
- */
2345
- function generateCredentialKey(credentialEntity) {
2346
- const credentialKey = [
2347
- generateAccountId(credentialEntity),
2348
- generateCredentialId(credentialEntity),
2349
- generateTarget(credentialEntity),
2350
- generateClaimsHash(credentialEntity),
2351
- generateScheme(credentialEntity),
2352
- ];
2353
- return credentialKey.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
2354
- }
2355
2356
  /**
2356
2357
  * Create IdTokenEntity
2357
2358
  * @param homeAccountId
@@ -2367,6 +2368,7 @@ function createIdTokenEntity(homeAccountId, environment, idToken, clientId, tena
2367
2368
  clientId: clientId,
2368
2369
  secret: idToken,
2369
2370
  realm: tenantId,
2371
+ lastUpdatedAt: Date.now().toString(), // Set the last updated time to now
2370
2372
  };
2371
2373
  return idTokenEntity;
2372
2374
  }
@@ -2394,6 +2396,7 @@ function createAccessTokenEntity(homeAccountId, environment, accessToken, client
2394
2396
  realm: tenantId,
2395
2397
  target: scopes,
2396
2398
  tokenType: tokenType || AuthenticationScheme.BEARER,
2399
+ lastUpdatedAt: Date.now().toString(), // Set the last updated time to now
2397
2400
  };
2398
2401
  if (userAssertionHash) {
2399
2402
  atEntity.userAssertionHash = userAssertionHash;
@@ -2441,6 +2444,7 @@ function createRefreshTokenEntity(homeAccountId, environment, refreshToken, clie
2441
2444
  environment: environment,
2442
2445
  clientId: clientId,
2443
2446
  secret: refreshToken,
2447
+ lastUpdatedAt: Date.now().toString(),
2444
2448
  };
2445
2449
  if (userAssertionHash) {
2446
2450
  rtEntity.userAssertionHash = userAssertionHash;
@@ -2498,56 +2502,6 @@ function isRefreshTokenEntity(entity) {
2498
2502
  return (isCredentialEntity(entity) &&
2499
2503
  entity["credentialType"] === CredentialType.REFRESH_TOKEN);
2500
2504
  }
2501
- /**
2502
- * Generate Account Id key component as per the schema: <home_account_id>-<environment>
2503
- */
2504
- function generateAccountId(credentialEntity) {
2505
- const accountId = [
2506
- credentialEntity.homeAccountId,
2507
- credentialEntity.environment,
2508
- ];
2509
- return accountId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
2510
- }
2511
- /**
2512
- * Generate Credential Id key component as per the schema: <credential_type>-<client_id>-<realm>
2513
- */
2514
- function generateCredentialId(credentialEntity) {
2515
- const clientOrFamilyId = credentialEntity.credentialType === CredentialType.REFRESH_TOKEN
2516
- ? credentialEntity.familyId || credentialEntity.clientId
2517
- : credentialEntity.clientId;
2518
- const credentialId = [
2519
- credentialEntity.credentialType,
2520
- clientOrFamilyId,
2521
- credentialEntity.realm || "",
2522
- ];
2523
- return credentialId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
2524
- }
2525
- /**
2526
- * Generate target key component as per schema: <target>
2527
- */
2528
- function generateTarget(credentialEntity) {
2529
- return (credentialEntity.target || "").toLowerCase();
2530
- }
2531
- /**
2532
- * Generate requested claims key component as per schema: <requestedClaims>
2533
- */
2534
- function generateClaimsHash(credentialEntity) {
2535
- return (credentialEntity.requestedClaimsHash || "").toLowerCase();
2536
- }
2537
- /**
2538
- * Generate scheme key componenet as per schema: <scheme>
2539
- */
2540
- function generateScheme(credentialEntity) {
2541
- /*
2542
- * PoP Tokens and SSH certs include scheme in cache key
2543
- * Cast to lowercase to handle "bearer" from ADFS
2544
- */
2545
- return credentialEntity.tokenType &&
2546
- credentialEntity.tokenType.toLowerCase() !==
2547
- AuthenticationScheme.BEARER.toLowerCase()
2548
- ? credentialEntity.tokenType.toLowerCase()
2549
- : "";
2550
- }
2551
2505
  /**
2552
2506
  * validates if a given cache entry is "Telemetry", parses <key,value>
2553
2507
  * @param key
@@ -2662,7 +2616,6 @@ var CacheHelpers = /*#__PURE__*/Object.freeze({
2662
2616
  createRefreshTokenEntity: createRefreshTokenEntity,
2663
2617
  generateAppMetadataKey: generateAppMetadataKey,
2664
2618
  generateAuthorityMetadataExpiresAt: generateAuthorityMetadataExpiresAt,
2665
- generateCredentialKey: generateCredentialKey,
2666
2619
  isAccessTokenEntity: isAccessTokenEntity,
2667
2620
  isAppMetadataEntity: isAppMetadataEntity,
2668
2621
  isAuthorityMetadataEntity: isAuthorityMetadataEntity,
@@ -3900,7 +3853,7 @@ class Logger {
3900
3853
 
3901
3854
  /* eslint-disable header/header */
3902
3855
  const name = "@azure/msal-common";
3903
- const version = "15.9.0";
3856
+ const version = "15.10.0";
3904
3857
 
3905
3858
  /*
3906
3859
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -4091,44 +4044,6 @@ class ScopeSet {
4091
4044
  }
4092
4045
  }
4093
4046
 
4094
- /*
4095
- * Copyright (c) Microsoft Corporation. All rights reserved.
4096
- * Licensed under the MIT License.
4097
- */
4098
- /**
4099
- * Function to build a client info object from server clientInfo string
4100
- * @param rawClientInfo
4101
- * @param crypto
4102
- */
4103
- function buildClientInfo(rawClientInfo, base64Decode) {
4104
- if (!rawClientInfo) {
4105
- throw createClientAuthError(clientInfoEmptyError);
4106
- }
4107
- try {
4108
- const decodedClientInfo = base64Decode(rawClientInfo);
4109
- return JSON.parse(decodedClientInfo);
4110
- }
4111
- catch (e) {
4112
- throw createClientAuthError(clientInfoDecodingError);
4113
- }
4114
- }
4115
- /**
4116
- * Function to build a client info object from cached homeAccountId string
4117
- * @param homeAccountId
4118
- */
4119
- function buildClientInfoFromHomeAccountId(homeAccountId) {
4120
- if (!homeAccountId) {
4121
- throw createClientAuthError(clientInfoDecodingError);
4122
- }
4123
- const clientInfoParts = homeAccountId.split(Separators.CLIENT_INFO_SEPARATOR, 2);
4124
- return {
4125
- uid: clientInfoParts[0],
4126
- utid: clientInfoParts.length < 2
4127
- ? Constants.EMPTY_STRING
4128
- : clientInfoParts[1],
4129
- };
4130
- }
4131
-
4132
4047
  /*
4133
4048
  * Copyright (c) Microsoft Corporation. All rights reserved.
4134
4049
  * Licensed under the MIT License.
@@ -4154,7 +4069,7 @@ function tenantIdMatchesHomeTenant(tenantId, homeAccountId) {
4154
4069
  */
4155
4070
  function buildTenantProfile(homeAccountId, localAccountId, tenantId, idTokenClaims) {
4156
4071
  if (idTokenClaims) {
4157
- const { oid, sub, tid, name, tfp, acr } = idTokenClaims;
4072
+ const { oid, sub, tid, name, tfp, acr, preferred_username, upn, login_hint, } = idTokenClaims;
4158
4073
  /**
4159
4074
  * Since there is no way to determine if the authority is AAD or B2C, we exhaust all the possible claims that can serve as tenant ID with the following precedence:
4160
4075
  * tid - TenantID claim that identifies the tenant that issued the token in AAD. Expected in all AAD ID tokens, not present in B2C ID Tokens.
@@ -4166,6 +4081,8 @@ function buildTenantProfile(homeAccountId, localAccountId, tenantId, idTokenClai
4166
4081
  tenantId: tenantId,
4167
4082
  localAccountId: oid || sub || "",
4168
4083
  name: name,
4084
+ username: preferred_username || upn || "",
4085
+ loginHint: login_hint,
4169
4086
  isHomeTenant: tenantIdMatchesHomeTenant(tenantId, homeAccountId),
4170
4087
  };
4171
4088
  }
@@ -4173,6 +4090,7 @@ function buildTenantProfile(homeAccountId, localAccountId, tenantId, idTokenClai
4173
4090
  return {
4174
4091
  tenantId,
4175
4092
  localAccountId,
4093
+ username: "",
4176
4094
  isHomeTenant: tenantIdMatchesHomeTenant(tenantId, homeAccountId),
4177
4095
  };
4178
4096
  }
@@ -4211,21 +4129,56 @@ function updateAccountTenantProfileData(baseAccountInfo, tenantProfile, idTokenC
4211
4129
  * Copyright (c) Microsoft Corporation. All rights reserved.
4212
4130
  * Licensed under the MIT License.
4213
4131
  */
4132
+ const cacheQuotaExceeded = "cache_quota_exceeded";
4133
+ const cacheErrorUnknown = "cache_error_unknown";
4134
+
4135
+ var CacheErrorCodes = /*#__PURE__*/Object.freeze({
4136
+ __proto__: null,
4137
+ cacheErrorUnknown: cacheErrorUnknown,
4138
+ cacheQuotaExceeded: cacheQuotaExceeded
4139
+ });
4140
+
4141
+ /*
4142
+ * Copyright (c) Microsoft Corporation. All rights reserved.
4143
+ * Licensed under the MIT License.
4144
+ */
4145
+ const CacheErrorMessages = {
4146
+ [cacheQuotaExceeded]: "Exceeded cache storage capacity.",
4147
+ [cacheErrorUnknown]: "Unexpected error occurred when using cache storage.",
4148
+ };
4214
4149
  /**
4215
- * Gets tenantId from available ID token claims to set as credential realm with the following precedence:
4216
- * 1. tid - if the token is acquired from an Azure AD tenant tid will be present
4217
- * 2. tfp - if the token is acquired from a modern B2C tenant tfp should be present
4218
- * 3. acr - if the token is acquired from a legacy B2C tenant acr should be present
4219
- * Downcased to match the realm case-insensitive comparison requirements
4220
- * @param idTokenClaims
4150
+ * Error thrown when there is an error with the cache
4151
+ */
4152
+ class CacheError extends AuthError {
4153
+ constructor(errorCode, errorMessage) {
4154
+ const message = errorMessage ||
4155
+ (CacheErrorMessages[errorCode]
4156
+ ? CacheErrorMessages[errorCode]
4157
+ : CacheErrorMessages[cacheErrorUnknown]);
4158
+ super(`${errorCode}: ${message}`);
4159
+ Object.setPrototypeOf(this, CacheError.prototype);
4160
+ this.name = "CacheError";
4161
+ this.errorCode = errorCode;
4162
+ this.errorMessage = message;
4163
+ }
4164
+ }
4165
+ /**
4166
+ * Helper function to wrap browser errors in a CacheError object
4167
+ * @param e
4221
4168
  * @returns
4222
4169
  */
4223
- function getTenantIdFromIdTokenClaims(idTokenClaims) {
4224
- if (idTokenClaims) {
4225
- const tenantId = idTokenClaims.tid || idTokenClaims.tfp || idTokenClaims.acr;
4226
- return tenantId || null;
4170
+ function createCacheError(e) {
4171
+ if (!(e instanceof Error)) {
4172
+ return new CacheError(cacheErrorUnknown);
4173
+ }
4174
+ if (e.name === "QuotaExceededError" ||
4175
+ e.name === "NS_ERROR_DOM_QUOTA_REACHED" ||
4176
+ e.message.includes("exceeded the quota")) {
4177
+ return new CacheError(cacheQuotaExceeded);
4178
+ }
4179
+ else {
4180
+ return new CacheError(e.name, e.message);
4227
4181
  }
4228
- return null;
4229
4182
  }
4230
4183
 
4231
4184
  /*
@@ -4233,383 +4186,86 @@ function getTenantIdFromIdTokenClaims(idTokenClaims) {
4233
4186
  * Licensed under the MIT License.
4234
4187
  */
4235
4188
  /**
4236
- * Type that defines required and optional parameters for an Account field (based on universal cache schema implemented by all MSALs).
4237
- *
4238
- * Key : Value Schema
4239
- *
4240
- * Key: <home_account_id>-<environment>-<realm*>
4241
- *
4242
- * Value Schema:
4243
- * {
4244
- * homeAccountId: home account identifier for the auth scheme,
4245
- * environment: entity that issued the token, represented as a full host
4246
- * realm: Full tenant or organizational identifier that the account belongs to
4247
- * localAccountId: Original tenant-specific accountID, usually used for legacy cases
4248
- * username: primary username that represents the user, usually corresponds to preferred_username in the v2 endpt
4249
- * authorityType: Accounts authority type as a string
4250
- * name: Full name for the account, including given name and family name,
4251
- * lastModificationTime: last time this entity was modified in the cache
4252
- * lastModificationApp:
4253
- * nativeAccountId: Account identifier on the native device
4254
- * tenantProfiles: Array of tenant profile objects for each tenant that the account has authenticated with in the browser
4255
- * }
4189
+ * Interface class which implement cache storage functions used by MSAL to perform validity checks, and store tokens.
4256
4190
  * @internal
4257
4191
  */
4258
- class AccountEntity {
4259
- /**
4260
- * Generate Account Id key component as per the schema: <home_account_id>-<environment>
4261
- */
4262
- generateAccountId() {
4263
- const accountId = [this.homeAccountId, this.environment];
4264
- return accountId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
4192
+ class CacheManager {
4193
+ constructor(clientId, cryptoImpl, logger, performanceClient, staticAuthorityOptions) {
4194
+ this.clientId = clientId;
4195
+ this.cryptoImpl = cryptoImpl;
4196
+ this.commonLogger = logger.clone(name, version);
4197
+ this.staticAuthorityOptions = staticAuthorityOptions;
4198
+ this.performanceClient = performanceClient;
4265
4199
  }
4266
4200
  /**
4267
- * Generate Account Cache Key as per the schema: <home_account_id>-<environment>-<realm*>
4201
+ * Returns all the accounts in the cache that match the optional filter. If no filter is provided, all accounts are returned.
4202
+ * @param accountFilter - (Optional) filter to narrow down the accounts returned
4203
+ * @returns Array of AccountInfo objects in cache
4268
4204
  */
4269
- generateAccountKey() {
4270
- return AccountEntity.generateAccountCacheKey({
4271
- homeAccountId: this.homeAccountId,
4272
- environment: this.environment,
4273
- tenantId: this.realm,
4274
- username: this.username,
4275
- localAccountId: this.localAccountId,
4276
- });
4205
+ getAllAccounts(accountFilter, correlationId) {
4206
+ return this.buildTenantProfiles(this.getAccountsFilteredBy(accountFilter, correlationId), correlationId, accountFilter);
4277
4207
  }
4278
4208
  /**
4279
- * Returns the AccountInfo interface for this account.
4209
+ * Gets first tenanted AccountInfo object found based on provided filters
4280
4210
  */
4281
- getAccountInfo() {
4282
- return {
4283
- homeAccountId: this.homeAccountId,
4284
- environment: this.environment,
4285
- tenantId: this.realm,
4286
- username: this.username,
4287
- localAccountId: this.localAccountId,
4288
- name: this.name,
4289
- nativeAccountId: this.nativeAccountId,
4290
- authorityType: this.authorityType,
4291
- // Deserialize tenant profiles array into a Map
4292
- tenantProfiles: new Map((this.tenantProfiles || []).map((tenantProfile) => {
4293
- return [tenantProfile.tenantId, tenantProfile];
4294
- })),
4295
- };
4211
+ getAccountInfoFilteredBy(accountFilter, correlationId) {
4212
+ const allAccounts = this.getAllAccounts(accountFilter, correlationId);
4213
+ if (allAccounts.length > 1) {
4214
+ // If one or more accounts are found, prioritize accounts that have an ID token
4215
+ const sortedAccounts = allAccounts.sort((account) => {
4216
+ return account.idTokenClaims ? -1 : 1;
4217
+ });
4218
+ return sortedAccounts[0];
4219
+ }
4220
+ else if (allAccounts.length === 1) {
4221
+ // If only one account is found, return it regardless of whether a matching ID token was found
4222
+ return allAccounts[0];
4223
+ }
4224
+ else {
4225
+ return null;
4226
+ }
4296
4227
  }
4297
4228
  /**
4298
- * Returns true if the account entity is in single tenant format (outdated), false otherwise
4229
+ * Returns a single matching
4230
+ * @param accountFilter
4231
+ * @returns
4299
4232
  */
4300
- isSingleTenant() {
4301
- return !this.tenantProfiles;
4233
+ getBaseAccountInfo(accountFilter, correlationId) {
4234
+ const accountEntities = this.getAccountsFilteredBy(accountFilter, correlationId);
4235
+ if (accountEntities.length > 0) {
4236
+ return accountEntities[0].getAccountInfo();
4237
+ }
4238
+ else {
4239
+ return null;
4240
+ }
4302
4241
  }
4303
4242
  /**
4304
- * Generates account key from interface
4305
- * @param accountInterface
4243
+ * Matches filtered account entities with cached ID tokens that match the tenant profile-specific account filters
4244
+ * and builds the account info objects from the matching ID token's claims
4245
+ * @param cachedAccounts
4246
+ * @param accountFilter
4247
+ * @returns Array of AccountInfo objects that match account and tenant profile filters
4306
4248
  */
4307
- static generateAccountCacheKey(accountInterface) {
4308
- const homeTenantId = accountInterface.homeAccountId.split(".")[1];
4309
- const accountKey = [
4310
- accountInterface.homeAccountId,
4311
- accountInterface.environment || "",
4312
- homeTenantId || accountInterface.tenantId || "",
4313
- ];
4314
- return accountKey.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
4249
+ buildTenantProfiles(cachedAccounts, correlationId, accountFilter) {
4250
+ return cachedAccounts.flatMap((accountEntity) => {
4251
+ return this.getTenantProfilesFromAccountEntity(accountEntity, correlationId, accountFilter?.tenantId, accountFilter);
4252
+ });
4315
4253
  }
4316
- /**
4317
- * Build Account cache from IdToken, clientInfo and authority/policy. Associated with AAD.
4318
- * @param accountDetails
4319
- */
4320
- static createAccount(accountDetails, authority, base64Decode) {
4321
- const account = new AccountEntity();
4322
- if (authority.authorityType === AuthorityType.Adfs) {
4323
- account.authorityType = CacheAccountType.ADFS_ACCOUNT_TYPE;
4324
- }
4325
- else if (authority.protocolMode === ProtocolMode.OIDC) {
4326
- account.authorityType = CacheAccountType.GENERIC_ACCOUNT_TYPE;
4327
- }
4328
- else {
4329
- account.authorityType = CacheAccountType.MSSTS_ACCOUNT_TYPE;
4254
+ getTenantedAccountInfoByFilter(accountInfo, tokenKeys, tenantProfile, correlationId, tenantProfileFilter) {
4255
+ let tenantedAccountInfo = null;
4256
+ let idTokenClaims;
4257
+ if (tenantProfileFilter) {
4258
+ if (!this.tenantProfileMatchesFilter(tenantProfile, tenantProfileFilter)) {
4259
+ return null;
4260
+ }
4330
4261
  }
4331
- let clientInfo;
4332
- if (accountDetails.clientInfo && base64Decode) {
4333
- clientInfo = buildClientInfo(accountDetails.clientInfo, base64Decode);
4334
- }
4335
- account.clientInfo = accountDetails.clientInfo;
4336
- account.homeAccountId = accountDetails.homeAccountId;
4337
- account.nativeAccountId = accountDetails.nativeAccountId;
4338
- const env = accountDetails.environment ||
4339
- (authority && authority.getPreferredCache());
4340
- if (!env) {
4341
- throw createClientAuthError(invalidCacheEnvironment);
4342
- }
4343
- account.environment = env;
4344
- // non AAD scenarios can have empty realm
4345
- account.realm =
4346
- clientInfo?.utid ||
4347
- getTenantIdFromIdTokenClaims(accountDetails.idTokenClaims) ||
4348
- "";
4349
- // How do you account for MSA CID here?
4350
- account.localAccountId =
4351
- clientInfo?.uid ||
4352
- accountDetails.idTokenClaims?.oid ||
4353
- accountDetails.idTokenClaims?.sub ||
4354
- "";
4355
- /*
4356
- * In B2C scenarios the emails claim is used instead of preferred_username and it is an array.
4357
- * In most cases it will contain a single email. This field should not be relied upon if a custom
4358
- * policy is configured to return more than 1 email.
4359
- */
4360
- const preferredUsername = accountDetails.idTokenClaims?.preferred_username ||
4361
- accountDetails.idTokenClaims?.upn;
4362
- const email = accountDetails.idTokenClaims?.emails
4363
- ? accountDetails.idTokenClaims.emails[0]
4364
- : null;
4365
- account.username = preferredUsername || email || "";
4366
- account.name = accountDetails.idTokenClaims?.name || "";
4367
- account.cloudGraphHostName = accountDetails.cloudGraphHostName;
4368
- account.msGraphHost = accountDetails.msGraphHost;
4369
- if (accountDetails.tenantProfiles) {
4370
- account.tenantProfiles = accountDetails.tenantProfiles;
4371
- }
4372
- else {
4373
- const tenantProfile = buildTenantProfile(accountDetails.homeAccountId, account.localAccountId, account.realm, accountDetails.idTokenClaims);
4374
- account.tenantProfiles = [tenantProfile];
4375
- }
4376
- return account;
4377
- }
4378
- /**
4379
- * Creates an AccountEntity object from AccountInfo
4380
- * @param accountInfo
4381
- * @param cloudGraphHostName
4382
- * @param msGraphHost
4383
- * @returns
4384
- */
4385
- static createFromAccountInfo(accountInfo, cloudGraphHostName, msGraphHost) {
4386
- const account = new AccountEntity();
4387
- account.authorityType =
4388
- accountInfo.authorityType || CacheAccountType.GENERIC_ACCOUNT_TYPE;
4389
- account.homeAccountId = accountInfo.homeAccountId;
4390
- account.localAccountId = accountInfo.localAccountId;
4391
- account.nativeAccountId = accountInfo.nativeAccountId;
4392
- account.realm = accountInfo.tenantId;
4393
- account.environment = accountInfo.environment;
4394
- account.username = accountInfo.username;
4395
- account.name = accountInfo.name;
4396
- account.cloudGraphHostName = cloudGraphHostName;
4397
- account.msGraphHost = msGraphHost;
4398
- // Serialize tenant profiles map into an array
4399
- account.tenantProfiles = Array.from(accountInfo.tenantProfiles?.values() || []);
4400
- return account;
4401
- }
4402
- /**
4403
- * Generate HomeAccountId from server response
4404
- * @param serverClientInfo
4405
- * @param authType
4406
- */
4407
- static generateHomeAccountId(serverClientInfo, authType, logger, cryptoObj, idTokenClaims) {
4408
- // since ADFS/DSTS do not have tid and does not set client_info
4409
- if (!(authType === AuthorityType.Adfs ||
4410
- authType === AuthorityType.Dsts)) {
4411
- // for cases where there is clientInfo
4412
- if (serverClientInfo) {
4413
- try {
4414
- const clientInfo = buildClientInfo(serverClientInfo, cryptoObj.base64Decode);
4415
- if (clientInfo.uid && clientInfo.utid) {
4416
- return `${clientInfo.uid}.${clientInfo.utid}`;
4417
- }
4418
- }
4419
- catch (e) { }
4420
- }
4421
- logger.warning("No client info in response");
4422
- }
4423
- // default to "sub" claim
4424
- return idTokenClaims?.sub || "";
4425
- }
4426
- /**
4427
- * Validates an entity: checks for all expected params
4428
- * @param entity
4429
- */
4430
- static isAccountEntity(entity) {
4431
- if (!entity) {
4432
- return false;
4433
- }
4434
- return (entity.hasOwnProperty("homeAccountId") &&
4435
- entity.hasOwnProperty("environment") &&
4436
- entity.hasOwnProperty("realm") &&
4437
- entity.hasOwnProperty("localAccountId") &&
4438
- entity.hasOwnProperty("username") &&
4439
- entity.hasOwnProperty("authorityType"));
4440
- }
4441
- /**
4442
- * Helper function to determine whether 2 accountInfo objects represent the same account
4443
- * @param accountA
4444
- * @param accountB
4445
- * @param compareClaims - If set to true idTokenClaims will also be compared to determine account equality
4446
- */
4447
- static accountInfoIsEqual(accountA, accountB, compareClaims) {
4448
- if (!accountA || !accountB) {
4449
- return false;
4450
- }
4451
- let claimsMatch = true; // default to true so as to not fail comparison below if compareClaims: false
4452
- if (compareClaims) {
4453
- const accountAClaims = (accountA.idTokenClaims ||
4454
- {});
4455
- const accountBClaims = (accountB.idTokenClaims ||
4456
- {});
4457
- // issued at timestamp and nonce are expected to change each time a new id token is acquired
4458
- claimsMatch =
4459
- accountAClaims.iat === accountBClaims.iat &&
4460
- accountAClaims.nonce === accountBClaims.nonce;
4461
- }
4462
- return (accountA.homeAccountId === accountB.homeAccountId &&
4463
- accountA.localAccountId === accountB.localAccountId &&
4464
- accountA.username === accountB.username &&
4465
- accountA.tenantId === accountB.tenantId &&
4466
- accountA.environment === accountB.environment &&
4467
- accountA.nativeAccountId === accountB.nativeAccountId &&
4468
- claimsMatch);
4469
- }
4470
- }
4471
-
4472
- /*
4473
- * Copyright (c) Microsoft Corporation. All rights reserved.
4474
- * Licensed under the MIT License.
4475
- */
4476
- const cacheQuotaExceeded = "cache_quota_exceeded";
4477
- const cacheErrorUnknown = "cache_error_unknown";
4478
-
4479
- var CacheErrorCodes = /*#__PURE__*/Object.freeze({
4480
- __proto__: null,
4481
- cacheErrorUnknown: cacheErrorUnknown,
4482
- cacheQuotaExceeded: cacheQuotaExceeded
4483
- });
4484
-
4485
- /*
4486
- * Copyright (c) Microsoft Corporation. All rights reserved.
4487
- * Licensed under the MIT License.
4488
- */
4489
- const CacheErrorMessages = {
4490
- [cacheQuotaExceeded]: "Exceeded cache storage capacity.",
4491
- [cacheErrorUnknown]: "Unexpected error occurred when using cache storage.",
4492
- };
4493
- /**
4494
- * Error thrown when there is an error with the cache
4495
- */
4496
- class CacheError extends AuthError {
4497
- constructor(errorCode, errorMessage) {
4498
- const message = errorMessage ||
4499
- (CacheErrorMessages[errorCode]
4500
- ? CacheErrorMessages[errorCode]
4501
- : CacheErrorMessages[cacheErrorUnknown]);
4502
- super(`${errorCode}: ${message}`);
4503
- Object.setPrototypeOf(this, CacheError.prototype);
4504
- this.name = "CacheError";
4505
- this.errorCode = errorCode;
4506
- this.errorMessage = message;
4507
- }
4508
- }
4509
- /**
4510
- * Helper function to wrap browser errors in a CacheError object
4511
- * @param e
4512
- * @returns
4513
- */
4514
- function createCacheError(e) {
4515
- if (!(e instanceof Error)) {
4516
- return new CacheError(cacheErrorUnknown);
4517
- }
4518
- if (e.name === "QuotaExceededError" ||
4519
- e.name === "NS_ERROR_DOM_QUOTA_REACHED" ||
4520
- e.message.includes("exceeded the quota")) {
4521
- return new CacheError(cacheQuotaExceeded);
4522
- }
4523
- else {
4524
- return new CacheError(e.name, e.message);
4525
- }
4526
- }
4527
-
4528
- /*
4529
- * Copyright (c) Microsoft Corporation. All rights reserved.
4530
- * Licensed under the MIT License.
4531
- */
4532
- /**
4533
- * Interface class which implement cache storage functions used by MSAL to perform validity checks, and store tokens.
4534
- * @internal
4535
- */
4536
- class CacheManager {
4537
- constructor(clientId, cryptoImpl, logger, performanceClient, staticAuthorityOptions) {
4538
- this.clientId = clientId;
4539
- this.cryptoImpl = cryptoImpl;
4540
- this.commonLogger = logger.clone(name, version);
4541
- this.staticAuthorityOptions = staticAuthorityOptions;
4542
- this.performanceClient = performanceClient;
4543
- }
4544
- /**
4545
- * Returns all the accounts in the cache that match the optional filter. If no filter is provided, all accounts are returned.
4546
- * @param accountFilter - (Optional) filter to narrow down the accounts returned
4547
- * @returns Array of AccountInfo objects in cache
4548
- */
4549
- getAllAccounts(accountFilter, correlationId) {
4550
- return this.buildTenantProfiles(this.getAccountsFilteredBy(accountFilter, correlationId), correlationId, accountFilter);
4551
- }
4552
- /**
4553
- * Gets first tenanted AccountInfo object found based on provided filters
4554
- */
4555
- getAccountInfoFilteredBy(accountFilter, correlationId) {
4556
- const allAccounts = this.getAllAccounts(accountFilter, correlationId);
4557
- if (allAccounts.length > 1) {
4558
- // If one or more accounts are found, prioritize accounts that have an ID token
4559
- const sortedAccounts = allAccounts.sort((account) => {
4560
- return account.idTokenClaims ? -1 : 1;
4561
- });
4562
- return sortedAccounts[0];
4563
- }
4564
- else if (allAccounts.length === 1) {
4565
- // If only one account is found, return it regardless of whether a matching ID token was found
4566
- return allAccounts[0];
4567
- }
4568
- else {
4569
- return null;
4570
- }
4571
- }
4572
- /**
4573
- * Returns a single matching
4574
- * @param accountFilter
4575
- * @returns
4576
- */
4577
- getBaseAccountInfo(accountFilter, correlationId) {
4578
- const accountEntities = this.getAccountsFilteredBy(accountFilter, correlationId);
4579
- if (accountEntities.length > 0) {
4580
- return accountEntities[0].getAccountInfo();
4581
- }
4582
- else {
4583
- return null;
4584
- }
4585
- }
4586
- /**
4587
- * Matches filtered account entities with cached ID tokens that match the tenant profile-specific account filters
4588
- * and builds the account info objects from the matching ID token's claims
4589
- * @param cachedAccounts
4590
- * @param accountFilter
4591
- * @returns Array of AccountInfo objects that match account and tenant profile filters
4592
- */
4593
- buildTenantProfiles(cachedAccounts, correlationId, accountFilter) {
4594
- return cachedAccounts.flatMap((accountEntity) => {
4595
- return this.getTenantProfilesFromAccountEntity(accountEntity, correlationId, accountFilter?.tenantId, accountFilter);
4596
- });
4597
- }
4598
- getTenantedAccountInfoByFilter(accountInfo, tokenKeys, tenantProfile, correlationId, tenantProfileFilter) {
4599
- let tenantedAccountInfo = null;
4600
- let idTokenClaims;
4601
- if (tenantProfileFilter) {
4602
- if (!this.tenantProfileMatchesFilter(tenantProfile, tenantProfileFilter)) {
4603
- return null;
4604
- }
4605
- }
4606
- const idToken = this.getIdToken(accountInfo, correlationId, tokenKeys, tenantProfile.tenantId);
4607
- if (idToken) {
4608
- idTokenClaims = extractTokenClaims(idToken.secret, this.cryptoImpl.base64Decode);
4609
- if (!this.idTokenClaimsMatchTenantProfileFilter(idTokenClaims, tenantProfileFilter)) {
4610
- // ID token sourced claims don't match so this tenant profile is not a match
4611
- return null;
4612
- }
4262
+ const idToken = this.getIdToken(accountInfo, correlationId, tokenKeys, tenantProfile.tenantId);
4263
+ if (idToken) {
4264
+ idTokenClaims = extractTokenClaims(idToken.secret, this.cryptoImpl.base64Decode);
4265
+ if (!this.idTokenClaimsMatchTenantProfileFilter(idTokenClaims, tenantProfileFilter)) {
4266
+ // ID token sourced claims don't match so this tenant profile is not a match
4267
+ return null;
4268
+ }
4613
4269
  }
4614
4270
  // Expand tenant profile into account info based on matching tenant profile and if available matching ID token claims
4615
4271
  tenantedAccountInfo = updateAccountTenantProfileData(accountInfo, tenantProfile, idTokenClaims, idToken?.secret);
@@ -4762,10 +4418,6 @@ class CacheManager {
4762
4418
  const allAccountKeys = this.getAccountKeys();
4763
4419
  const matchingAccounts = [];
4764
4420
  allAccountKeys.forEach((cacheKey) => {
4765
- if (!this.isAccountKey(cacheKey, accountFilter.homeAccountId)) {
4766
- // Don't parse value if the key doesn't match the account filters
4767
- return;
4768
- }
4769
4421
  const entity = this.getAccount(cacheKey, correlationId);
4770
4422
  // Match base account fields
4771
4423
  if (!entity) {
@@ -4811,64 +4463,6 @@ class CacheManager {
4811
4463
  });
4812
4464
  return matchingAccounts;
4813
4465
  }
4814
- /**
4815
- * Returns true if the given key matches our account key schema. Also matches homeAccountId and/or tenantId if provided
4816
- * @param key
4817
- * @param homeAccountId
4818
- * @param tenantId
4819
- * @returns
4820
- */
4821
- isAccountKey(key, homeAccountId, tenantId) {
4822
- if (key.split(Separators.CACHE_KEY_SEPARATOR).length < 3) {
4823
- // Account cache keys contain 3 items separated by '-' (each item may also contain '-')
4824
- return false;
4825
- }
4826
- if (homeAccountId &&
4827
- !key.toLowerCase().includes(homeAccountId.toLowerCase())) {
4828
- return false;
4829
- }
4830
- if (tenantId && !key.toLowerCase().includes(tenantId.toLowerCase())) {
4831
- return false;
4832
- }
4833
- // Do not check environment as aliasing can cause false negatives
4834
- return true;
4835
- }
4836
- /**
4837
- * Returns true if the given key matches our credential key schema.
4838
- * @param key
4839
- */
4840
- isCredentialKey(key) {
4841
- if (key.split(Separators.CACHE_KEY_SEPARATOR).length < 6) {
4842
- // Credential cache keys contain 6 items separated by '-' (each item may also contain '-')
4843
- return false;
4844
- }
4845
- const lowerCaseKey = key.toLowerCase();
4846
- // Credential keys must indicate what credential type they represent
4847
- if (lowerCaseKey.indexOf(CredentialType.ID_TOKEN.toLowerCase()) ===
4848
- -1 &&
4849
- lowerCaseKey.indexOf(CredentialType.ACCESS_TOKEN.toLowerCase()) ===
4850
- -1 &&
4851
- lowerCaseKey.indexOf(CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME.toLowerCase()) === -1 &&
4852
- lowerCaseKey.indexOf(CredentialType.REFRESH_TOKEN.toLowerCase()) ===
4853
- -1) {
4854
- return false;
4855
- }
4856
- if (lowerCaseKey.indexOf(CredentialType.REFRESH_TOKEN.toLowerCase()) >
4857
- -1) {
4858
- // Refresh tokens must contain the client id or family id
4859
- const clientIdValidation = `${CredentialType.REFRESH_TOKEN}${Separators.CACHE_KEY_SEPARATOR}${this.clientId}${Separators.CACHE_KEY_SEPARATOR}`;
4860
- const familyIdValidation = `${CredentialType.REFRESH_TOKEN}${Separators.CACHE_KEY_SEPARATOR}${THE_FAMILY_ID}${Separators.CACHE_KEY_SEPARATOR}`;
4861
- if (lowerCaseKey.indexOf(clientIdValidation.toLowerCase()) === -1 &&
4862
- lowerCaseKey.indexOf(familyIdValidation.toLowerCase()) === -1) {
4863
- return false;
4864
- }
4865
- }
4866
- else if (lowerCaseKey.indexOf(this.clientId.toLowerCase()) === -1) {
4867
- // Tokens must contain the clientId
4868
- return false;
4869
- }
4870
- return true;
4871
- }
4872
4466
  /**
4873
4467
  * Returns whether or not the given credential entity matches the filter
4874
4468
  * @param entity
@@ -4993,22 +4587,26 @@ class CacheManager {
4993
4587
  * Removes all accounts and related tokens from cache.
4994
4588
  */
4995
4589
  removeAllAccounts(correlationId) {
4996
- const allAccountKeys = this.getAccountKeys();
4997
- allAccountKeys.forEach((cacheKey) => {
4998
- this.removeAccount(cacheKey, correlationId);
4590
+ const accounts = this.getAllAccounts({}, correlationId);
4591
+ accounts.forEach((account) => {
4592
+ this.removeAccount(account, correlationId);
4999
4593
  });
5000
4594
  }
5001
4595
  /**
5002
4596
  * Removes the account and related tokens for a given account key
5003
4597
  * @param account
5004
4598
  */
5005
- removeAccount(accountKey, correlationId) {
5006
- const account = this.getAccount(accountKey, correlationId);
5007
- if (!account) {
5008
- return;
5009
- }
4599
+ removeAccount(account, correlationId) {
5010
4600
  this.removeAccountContext(account, correlationId);
5011
- this.removeItem(accountKey, correlationId);
4601
+ const accountKeys = this.getAccountKeys();
4602
+ const keyFilter = (key) => {
4603
+ return (key.includes(account.homeAccountId) &&
4604
+ key.includes(account.environment));
4605
+ };
4606
+ accountKeys.filter(keyFilter).forEach((key) => {
4607
+ this.removeItem(key, correlationId);
4608
+ this.performanceClient.incrementFields({ accountsRemoved: 1 }, correlationId);
4609
+ });
5012
4610
  }
5013
4611
  /**
5014
4612
  * Removes credentials associated with the provided account
@@ -5016,21 +4614,18 @@ class CacheManager {
5016
4614
  */
5017
4615
  removeAccountContext(account, correlationId) {
5018
4616
  const allTokenKeys = this.getTokenKeys();
5019
- const accountId = account.generateAccountId();
5020
- allTokenKeys.idToken.forEach((key) => {
5021
- if (key.indexOf(accountId) === 0) {
5022
- this.removeIdToken(key, correlationId);
5023
- }
4617
+ const keyFilter = (key) => {
4618
+ return (key.includes(account.homeAccountId) &&
4619
+ key.includes(account.environment));
4620
+ };
4621
+ allTokenKeys.idToken.filter(keyFilter).forEach((key) => {
4622
+ this.removeIdToken(key, correlationId);
5024
4623
  });
5025
- allTokenKeys.accessToken.forEach((key) => {
5026
- if (key.indexOf(accountId) === 0) {
5027
- this.removeAccessToken(key, correlationId);
5028
- }
4624
+ allTokenKeys.accessToken.filter(keyFilter).forEach((key) => {
4625
+ this.removeAccessToken(key, correlationId);
5029
4626
  });
5030
- allTokenKeys.refreshToken.forEach((key) => {
5031
- if (key.indexOf(accountId) === 0) {
5032
- this.removeRefreshToken(key, correlationId);
5033
- }
4627
+ allTokenKeys.refreshToken.filter(keyFilter).forEach((key) => {
4628
+ this.removeRefreshToken(key, correlationId);
5034
4629
  });
5035
4630
  }
5036
4631
  /**
@@ -5070,14 +4665,6 @@ class CacheManager {
5070
4665
  });
5071
4666
  return true;
5072
4667
  }
5073
- /**
5074
- * Retrieve AccountEntity from cache
5075
- * @param account
5076
- */
5077
- readAccountFromCache(account, correlationId) {
5078
- const accountKey = AccountEntity.generateAccountCacheKey(account);
5079
- return this.getAccount(accountKey, correlationId);
5080
- }
5081
4668
  /**
5082
4669
  * Retrieve IdTokenEntity from cache
5083
4670
  * @param account {AccountInfo}
@@ -5247,7 +4834,7 @@ class CacheManager {
5247
4834
  else if (numAccessTokens > 1) {
5248
4835
  this.commonLogger.info("CacheManager:getAccessToken - Multiple access tokens found, clearing them", correlationId);
5249
4836
  accessTokens.forEach((accessToken) => {
5250
- this.removeAccessToken(generateCredentialKey(accessToken), correlationId);
4837
+ this.removeAccessToken(this.generateCredentialKey(accessToken), correlationId);
5251
4838
  });
5252
4839
  this.performanceClient.addFields({ multiMatchedAT: accessTokens.length }, correlationId);
5253
4840
  return null;
@@ -5688,6 +5275,12 @@ class DefaultStorageClass extends CacheManager {
5688
5275
  getTokenKeys() {
5689
5276
  throw createClientAuthError(methodNotImplemented);
5690
5277
  }
5278
+ generateCredentialKey() {
5279
+ throw createClientAuthError(methodNotImplemented);
5280
+ }
5281
+ generateAccountKey() {
5282
+ throw createClientAuthError(methodNotImplemented);
5283
+ }
5691
5284
  }
5692
5285
 
5693
5286
  /*
@@ -5858,22 +5451,60 @@ function buildAuthOptions(authOptions) {
5858
5451
  };
5859
5452
  }
5860
5453
  /**
5861
- * Returns true if config has protocolMode set to ProtocolMode.OIDC, false otherwise
5862
- * @param ClientConfiguration
5454
+ * Returns true if config has protocolMode set to ProtocolMode.OIDC, false otherwise
5455
+ * @param ClientConfiguration
5456
+ */
5457
+ function isOidcProtocolMode(config) {
5458
+ return (config.authOptions.authority.options.protocolMode === ProtocolMode.OIDC);
5459
+ }
5460
+
5461
+ /*
5462
+ * Copyright (c) Microsoft Corporation. All rights reserved.
5463
+ * Licensed under the MIT License.
5464
+ */
5465
+ const CcsCredentialType = {
5466
+ HOME_ACCOUNT_ID: "home_account_id",
5467
+ UPN: "UPN",
5468
+ };
5469
+
5470
+ /*
5471
+ * Copyright (c) Microsoft Corporation. All rights reserved.
5472
+ * Licensed under the MIT License.
5473
+ */
5474
+ /**
5475
+ * Function to build a client info object from server clientInfo string
5476
+ * @param rawClientInfo
5477
+ * @param crypto
5478
+ */
5479
+ function buildClientInfo(rawClientInfo, base64Decode) {
5480
+ if (!rawClientInfo) {
5481
+ throw createClientAuthError(clientInfoEmptyError);
5482
+ }
5483
+ try {
5484
+ const decodedClientInfo = base64Decode(rawClientInfo);
5485
+ return JSON.parse(decodedClientInfo);
5486
+ }
5487
+ catch (e) {
5488
+ throw createClientAuthError(clientInfoDecodingError);
5489
+ }
5490
+ }
5491
+ /**
5492
+ * Function to build a client info object from cached homeAccountId string
5493
+ * @param homeAccountId
5863
5494
  */
5864
- function isOidcProtocolMode(config) {
5865
- return (config.authOptions.authority.options.protocolMode === ProtocolMode.OIDC);
5495
+ function buildClientInfoFromHomeAccountId(homeAccountId) {
5496
+ if (!homeAccountId) {
5497
+ throw createClientAuthError(clientInfoDecodingError);
5498
+ }
5499
+ const clientInfoParts = homeAccountId.split(Separators.CLIENT_INFO_SEPARATOR, 2);
5500
+ return {
5501
+ uid: clientInfoParts[0],
5502
+ utid: clientInfoParts.length < 2
5503
+ ? Constants.EMPTY_STRING
5504
+ : clientInfoParts[1],
5505
+ };
5866
5506
  }
5867
5507
 
5868
- /*
5869
- * Copyright (c) Microsoft Corporation. All rights reserved.
5870
- * Licensed under the MIT License.
5871
- */
5872
- const CcsCredentialType = {
5873
- HOME_ACCOUNT_ID: "home_account_id",
5874
- UPN: "UPN",
5875
- };
5876
-
5877
5508
  /*
5878
5509
  * Copyright (c) Microsoft Corporation. All rights reserved.
5879
5510
  * Licensed under the MIT License.
@@ -6634,6 +6265,240 @@ class BaseClient {
6634
6265
  }
6635
6266
  }
6636
6267
 
6268
+ /*
6269
+ * Copyright (c) Microsoft Corporation. All rights reserved.
6270
+ * Licensed under the MIT License.
6271
+ */
6272
+ /**
6273
+ * Gets tenantId from available ID token claims to set as credential realm with the following precedence:
6274
+ * 1. tid - if the token is acquired from an Azure AD tenant tid will be present
6275
+ * 2. tfp - if the token is acquired from a modern B2C tenant tfp should be present
6276
+ * 3. acr - if the token is acquired from a legacy B2C tenant acr should be present
6277
+ * Downcased to match the realm case-insensitive comparison requirements
6278
+ * @param idTokenClaims
6279
+ * @returns
6280
+ */
6281
+ function getTenantIdFromIdTokenClaims(idTokenClaims) {
6282
+ if (idTokenClaims) {
6283
+ const tenantId = idTokenClaims.tid || idTokenClaims.tfp || idTokenClaims.acr;
6284
+ return tenantId || null;
6285
+ }
6286
+ return null;
6287
+ }
6288
+
6289
+ /*
6290
+ * Copyright (c) Microsoft Corporation. All rights reserved.
6291
+ * Licensed under the MIT License.
6292
+ */
6293
+ /**
6294
+ * Type that defines required and optional parameters for an Account field (based on universal cache schema implemented by all MSALs).
6295
+ *
6296
+ * Key : Value Schema
6297
+ *
6298
+ * Key: <home_account_id>-<environment>-<realm*>
6299
+ *
6300
+ * Value Schema:
6301
+ * {
6302
+ * homeAccountId: home account identifier for the auth scheme,
6303
+ * environment: entity that issued the token, represented as a full host
6304
+ * realm: Full tenant or organizational identifier that the account belongs to
6305
+ * localAccountId: Original tenant-specific accountID, usually used for legacy cases
6306
+ * username: primary username that represents the user, usually corresponds to preferred_username in the v2 endpt
6307
+ * authorityType: Accounts authority type as a string
6308
+ * name: Full name for the account, including given name and family name,
6309
+ * lastModificationTime: last time this entity was modified in the cache
6310
+ * lastModificationApp:
6311
+ * nativeAccountId: Account identifier on the native device
6312
+ * tenantProfiles: Array of tenant profile objects for each tenant that the account has authenticated with in the browser
6313
+ * }
6314
+ * @internal
6315
+ */
6316
+ class AccountEntity {
6317
+ /**
6318
+ * Returns the AccountInfo interface for this account.
6319
+ */
6320
+ getAccountInfo() {
6321
+ return {
6322
+ homeAccountId: this.homeAccountId,
6323
+ environment: this.environment,
6324
+ tenantId: this.realm,
6325
+ username: this.username,
6326
+ localAccountId: this.localAccountId,
6327
+ loginHint: this.loginHint,
6328
+ name: this.name,
6329
+ nativeAccountId: this.nativeAccountId,
6330
+ authorityType: this.authorityType,
6331
+ // Deserialize tenant profiles array into a Map
6332
+ tenantProfiles: new Map((this.tenantProfiles || []).map((tenantProfile) => {
6333
+ return [tenantProfile.tenantId, tenantProfile];
6334
+ })),
6335
+ };
6336
+ }
6337
+ /**
6338
+ * Returns true if the account entity is in single tenant format (outdated), false otherwise
6339
+ */
6340
+ isSingleTenant() {
6341
+ return !this.tenantProfiles;
6342
+ }
6343
+ /**
6344
+ * Build Account cache from IdToken, clientInfo and authority/policy. Associated with AAD.
6345
+ * @param accountDetails
6346
+ */
6347
+ static createAccount(accountDetails, authority, base64Decode) {
6348
+ const account = new AccountEntity();
6349
+ if (authority.authorityType === AuthorityType.Adfs) {
6350
+ account.authorityType = CacheAccountType.ADFS_ACCOUNT_TYPE;
6351
+ }
6352
+ else if (authority.protocolMode === ProtocolMode.OIDC) {
6353
+ account.authorityType = CacheAccountType.GENERIC_ACCOUNT_TYPE;
6354
+ }
6355
+ else {
6356
+ account.authorityType = CacheAccountType.MSSTS_ACCOUNT_TYPE;
6357
+ }
6358
+ let clientInfo;
6359
+ if (accountDetails.clientInfo && base64Decode) {
6360
+ clientInfo = buildClientInfo(accountDetails.clientInfo, base64Decode);
6361
+ }
6362
+ account.clientInfo = accountDetails.clientInfo;
6363
+ account.homeAccountId = accountDetails.homeAccountId;
6364
+ account.nativeAccountId = accountDetails.nativeAccountId;
6365
+ const env = accountDetails.environment ||
6366
+ (authority && authority.getPreferredCache());
6367
+ if (!env) {
6368
+ throw createClientAuthError(invalidCacheEnvironment);
6369
+ }
6370
+ account.environment = env;
6371
+ // non AAD scenarios can have empty realm
6372
+ account.realm =
6373
+ clientInfo?.utid ||
6374
+ getTenantIdFromIdTokenClaims(accountDetails.idTokenClaims) ||
6375
+ "";
6376
+ // How do you account for MSA CID here?
6377
+ account.localAccountId =
6378
+ clientInfo?.uid ||
6379
+ accountDetails.idTokenClaims?.oid ||
6380
+ accountDetails.idTokenClaims?.sub ||
6381
+ "";
6382
+ /*
6383
+ * In B2C scenarios the emails claim is used instead of preferred_username and it is an array.
6384
+ * In most cases it will contain a single email. This field should not be relied upon if a custom
6385
+ * policy is configured to return more than 1 email.
6386
+ */
6387
+ const preferredUsername = accountDetails.idTokenClaims?.preferred_username ||
6388
+ accountDetails.idTokenClaims?.upn;
6389
+ const email = accountDetails.idTokenClaims?.emails
6390
+ ? accountDetails.idTokenClaims.emails[0]
6391
+ : null;
6392
+ account.username = preferredUsername || email || "";
6393
+ account.loginHint = accountDetails.idTokenClaims?.login_hint;
6394
+ account.name = accountDetails.idTokenClaims?.name || "";
6395
+ account.cloudGraphHostName = accountDetails.cloudGraphHostName;
6396
+ account.msGraphHost = accountDetails.msGraphHost;
6397
+ if (accountDetails.tenantProfiles) {
6398
+ account.tenantProfiles = accountDetails.tenantProfiles;
6399
+ }
6400
+ else {
6401
+ const tenantProfile = buildTenantProfile(accountDetails.homeAccountId, account.localAccountId, account.realm, accountDetails.idTokenClaims);
6402
+ account.tenantProfiles = [tenantProfile];
6403
+ }
6404
+ return account;
6405
+ }
6406
+ /**
6407
+ * Creates an AccountEntity object from AccountInfo
6408
+ * @param accountInfo
6409
+ * @param cloudGraphHostName
6410
+ * @param msGraphHost
6411
+ * @returns
6412
+ */
6413
+ static createFromAccountInfo(accountInfo, cloudGraphHostName, msGraphHost) {
6414
+ const account = new AccountEntity();
6415
+ account.authorityType =
6416
+ accountInfo.authorityType || CacheAccountType.GENERIC_ACCOUNT_TYPE;
6417
+ account.homeAccountId = accountInfo.homeAccountId;
6418
+ account.localAccountId = accountInfo.localAccountId;
6419
+ account.nativeAccountId = accountInfo.nativeAccountId;
6420
+ account.realm = accountInfo.tenantId;
6421
+ account.environment = accountInfo.environment;
6422
+ account.username = accountInfo.username;
6423
+ account.name = accountInfo.name;
6424
+ account.loginHint = accountInfo.loginHint;
6425
+ account.cloudGraphHostName = cloudGraphHostName;
6426
+ account.msGraphHost = msGraphHost;
6427
+ // Serialize tenant profiles map into an array
6428
+ account.tenantProfiles = Array.from(accountInfo.tenantProfiles?.values() || []);
6429
+ return account;
6430
+ }
6431
+ /**
6432
+ * Generate HomeAccountId from server response
6433
+ * @param serverClientInfo
6434
+ * @param authType
6435
+ */
6436
+ static generateHomeAccountId(serverClientInfo, authType, logger, cryptoObj, idTokenClaims) {
6437
+ // since ADFS/DSTS do not have tid and does not set client_info
6438
+ if (!(authType === AuthorityType.Adfs ||
6439
+ authType === AuthorityType.Dsts)) {
6440
+ // for cases where there is clientInfo
6441
+ if (serverClientInfo) {
6442
+ try {
6443
+ const clientInfo = buildClientInfo(serverClientInfo, cryptoObj.base64Decode);
6444
+ if (clientInfo.uid && clientInfo.utid) {
6445
+ return `${clientInfo.uid}.${clientInfo.utid}`;
6446
+ }
6447
+ }
6448
+ catch (e) { }
6449
+ }
6450
+ logger.warning("No client info in response");
6451
+ }
6452
+ // default to "sub" claim
6453
+ return idTokenClaims?.sub || "";
6454
+ }
6455
+ /**
6456
+ * Validates an entity: checks for all expected params
6457
+ * @param entity
6458
+ */
6459
+ static isAccountEntity(entity) {
6460
+ if (!entity) {
6461
+ return false;
6462
+ }
6463
+ return (entity.hasOwnProperty("homeAccountId") &&
6464
+ entity.hasOwnProperty("environment") &&
6465
+ entity.hasOwnProperty("realm") &&
6466
+ entity.hasOwnProperty("localAccountId") &&
6467
+ entity.hasOwnProperty("username") &&
6468
+ entity.hasOwnProperty("authorityType"));
6469
+ }
6470
+ /**
6471
+ * Helper function to determine whether 2 accountInfo objects represent the same account
6472
+ * @param accountA
6473
+ * @param accountB
6474
+ * @param compareClaims - If set to true idTokenClaims will also be compared to determine account equality
6475
+ */
6476
+ static accountInfoIsEqual(accountA, accountB, compareClaims) {
6477
+ if (!accountA || !accountB) {
6478
+ return false;
6479
+ }
6480
+ let claimsMatch = true; // default to true so as to not fail comparison below if compareClaims: false
6481
+ if (compareClaims) {
6482
+ const accountAClaims = (accountA.idTokenClaims ||
6483
+ {});
6484
+ const accountBClaims = (accountB.idTokenClaims ||
6485
+ {});
6486
+ // issued at timestamp and nonce are expected to change each time a new id token is acquired
6487
+ claimsMatch =
6488
+ accountAClaims.iat === accountBClaims.iat &&
6489
+ accountAClaims.nonce === accountBClaims.nonce;
6490
+ }
6491
+ return (accountA.homeAccountId === accountB.homeAccountId &&
6492
+ accountA.localAccountId === accountB.localAccountId &&
6493
+ accountA.username === accountB.username &&
6494
+ accountA.tenantId === accountB.tenantId &&
6495
+ accountA.loginHint === accountB.loginHint &&
6496
+ accountA.environment === accountB.environment &&
6497
+ accountA.nativeAccountId === accountB.nativeAccountId &&
6498
+ claimsMatch);
6499
+ }
6500
+ }
6501
+
6637
6502
  /*
6638
6503
  * Copyright (c) Microsoft Corporation. All rights reserved.
6639
6504
  * Licensed under the MIT License.
@@ -7035,7 +6900,7 @@ class ResponseHandler {
7035
6900
  if (handlingRefreshTokenResponse &&
7036
6901
  !forceCacheRefreshTokenResponse &&
7037
6902
  cacheRecord.account) {
7038
- const key = cacheRecord.account.generateAccountKey();
6903
+ const key = this.cacheStorage.generateAccountKey(cacheRecord.account.getAccountInfo());
7039
6904
  const account = this.cacheStorage.getAccount(key, request.correlationId);
7040
6905
  if (!account) {
7041
6906
  this.logger.warning("Account used to refresh tokens not in persistence, refreshed tokens will not be stored in the cache");
@@ -7609,7 +7474,7 @@ class RefreshTokenClient extends BaseClient {
7609
7474
  if (e.subError === badToken) {
7610
7475
  // Remove bad refresh token from cache
7611
7476
  this.logger.verbose("acquireTokenWithRefreshToken: bad refresh token, removing from cache");
7612
- const badRefreshTokenKey = generateCredentialKey(refreshToken);
7477
+ const badRefreshTokenKey = this.cacheManager.generateCredentialKey(refreshToken);
7613
7478
  this.cacheManager.removeRefreshToken(badRefreshTokenKey, request.correlationId);
7614
7479
  }
7615
7480
  }
@@ -7766,7 +7631,7 @@ class SilentFlowClient extends BaseClient {
7766
7631
  }
7767
7632
  const environment = request.authority || this.authority.getPreferredCache();
7768
7633
  const cacheRecord = {
7769
- account: this.cacheManager.readAccountFromCache(request.account, request.correlationId),
7634
+ account: this.cacheManager.getAccount(this.cacheManager.generateAccountKey(request.account), request.correlationId),
7770
7635
  accessToken: cachedAccessToken,
7771
7636
  idToken: this.cacheManager.getIdToken(request.account, request.correlationId, tokenKeys, requestTenantId, this.performanceClient),
7772
7637
  refreshToken: null,
@@ -8044,7 +7909,7 @@ function extractAccountSid(account) {
8044
7909
  return account.idTokenClaims?.sid || null;
8045
7910
  }
8046
7911
  function extractLoginHint(account) {
8047
- return account.idTokenClaims?.login_hint || null;
7912
+ return account.loginHint || account.idTokenClaims?.login_hint || null;
8048
7913
  }
8049
7914
 
8050
7915
  var Authorize = /*#__PURE__*/Object.freeze({
@@ -8476,4 +8341,4 @@ exports.invokeAsync = invokeAsync;
8476
8341
  exports.tenantIdMatchesHomeTenant = tenantIdMatchesHomeTenant;
8477
8342
  exports.updateAccountTenantProfileData = updateAccountTenantProfileData;
8478
8343
  exports.version = version;
8479
- //# sourceMappingURL=index-node-C5c-lcoe.js.map
8344
+ //# sourceMappingURL=index-node-Dy4fVJGl.js.map