@azure/msal-common 14.4.1-beta.1 → 14.6.0-alpha.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 (209) hide show
  1. package/dist/account/AccountInfo.d.ts +27 -0
  2. package/dist/account/AccountInfo.d.ts.map +1 -1
  3. package/dist/account/AccountInfo.mjs +64 -0
  4. package/dist/account/AccountInfo.mjs.map +1 -0
  5. package/dist/account/AuthToken.mjs +1 -1
  6. package/dist/account/AuthToken.mjs.map +1 -1
  7. package/dist/account/CcsCredential.mjs +1 -1
  8. package/dist/account/CcsCredential.mjs.map +1 -1
  9. package/dist/account/ClientInfo.d.ts +1 -2
  10. package/dist/account/ClientInfo.d.ts.map +1 -1
  11. package/dist/account/ClientInfo.mjs +3 -3
  12. package/dist/account/ClientInfo.mjs.map +1 -1
  13. package/dist/account/TokenClaims.d.ts +18 -0
  14. package/dist/account/TokenClaims.d.ts.map +1 -1
  15. package/dist/account/TokenClaims.mjs +25 -0
  16. package/dist/account/TokenClaims.mjs.map +1 -0
  17. package/dist/authority/Authority.d.ts +7 -2
  18. package/dist/authority/Authority.d.ts.map +1 -1
  19. package/dist/authority/Authority.mjs +34 -7
  20. package/dist/authority/Authority.mjs.map +1 -1
  21. package/dist/authority/AuthorityFactory.mjs +1 -1
  22. package/dist/authority/AuthorityFactory.mjs.map +1 -1
  23. package/dist/authority/AuthorityMetadata.mjs +1 -1
  24. package/dist/authority/AuthorityMetadata.mjs.map +1 -1
  25. package/dist/authority/AuthorityOptions.mjs +1 -1
  26. package/dist/authority/AuthorityOptions.mjs.map +1 -1
  27. package/dist/authority/AuthorityType.mjs +1 -1
  28. package/dist/authority/AuthorityType.mjs.map +1 -1
  29. package/dist/authority/CloudInstanceDiscoveryErrorResponse.mjs +1 -1
  30. package/dist/authority/CloudInstanceDiscoveryErrorResponse.mjs.map +1 -1
  31. package/dist/authority/CloudInstanceDiscoveryResponse.mjs +1 -1
  32. package/dist/authority/CloudInstanceDiscoveryResponse.mjs.map +1 -1
  33. package/dist/authority/OpenIdConfigResponse.mjs +1 -1
  34. package/dist/authority/OpenIdConfigResponse.mjs.map +1 -1
  35. package/dist/authority/ProtocolMode.mjs +1 -1
  36. package/dist/authority/ProtocolMode.mjs.map +1 -1
  37. package/dist/authority/RegionDiscovery.mjs +1 -1
  38. package/dist/authority/RegionDiscovery.mjs.map +1 -1
  39. package/dist/cache/CacheManager.d.ts +50 -27
  40. package/dist/cache/CacheManager.d.ts.map +1 -1
  41. package/dist/cache/CacheManager.mjs +243 -107
  42. package/dist/cache/CacheManager.mjs.map +1 -1
  43. package/dist/cache/entities/AccountEntity.d.ts +9 -4
  44. package/dist/cache/entities/AccountEntity.d.ts.map +1 -1
  45. package/dist/cache/entities/AccountEntity.mjs +56 -28
  46. package/dist/cache/entities/AccountEntity.mjs.map +1 -1
  47. package/dist/cache/entities/AppMetadataEntity.mjs +1 -1
  48. package/dist/cache/entities/AppMetadataEntity.mjs.map +1 -1
  49. package/dist/cache/entities/AuthorityMetadataEntity.mjs +1 -1
  50. package/dist/cache/entities/AuthorityMetadataEntity.mjs.map +1 -1
  51. package/dist/cache/entities/CacheRecord.mjs +1 -1
  52. package/dist/cache/entities/CacheRecord.mjs.map +1 -1
  53. package/dist/cache/entities/ThrottlingEntity.d.ts +2 -8
  54. package/dist/cache/entities/ThrottlingEntity.d.ts.map +1 -1
  55. package/dist/cache/persistence/TokenCacheContext.mjs +1 -1
  56. package/dist/cache/persistence/TokenCacheContext.mjs.map +1 -1
  57. package/dist/cache/utils/CacheHelpers.d.ts +7 -1
  58. package/dist/cache/utils/CacheHelpers.d.ts.map +1 -1
  59. package/dist/cache/utils/CacheHelpers.mjs +20 -4
  60. package/dist/cache/utils/CacheHelpers.mjs.map +1 -1
  61. package/dist/cache/utils/CacheTypes.d.ts +2 -0
  62. package/dist/cache/utils/CacheTypes.d.ts.map +1 -1
  63. package/dist/client/AuthorizationCodeClient.d.ts.map +1 -1
  64. package/dist/client/AuthorizationCodeClient.mjs +10 -9
  65. package/dist/client/AuthorizationCodeClient.mjs.map +1 -1
  66. package/dist/client/BaseClient.mjs +1 -1
  67. package/dist/client/BaseClient.mjs.map +1 -1
  68. package/dist/client/RefreshTokenClient.d.ts.map +1 -1
  69. package/dist/client/RefreshTokenClient.mjs +25 -11
  70. package/dist/client/RefreshTokenClient.mjs.map +1 -1
  71. package/dist/client/SilentFlowClient.d.ts.map +1 -1
  72. package/dist/client/SilentFlowClient.mjs +20 -9
  73. package/dist/client/SilentFlowClient.mjs.map +1 -1
  74. package/dist/config/ClientConfiguration.d.ts.map +1 -1
  75. package/dist/config/ClientConfiguration.mjs +2 -4
  76. package/dist/config/ClientConfiguration.mjs.map +1 -1
  77. package/dist/constants/AADServerParamKeys.d.ts +53 -0
  78. package/dist/constants/AADServerParamKeys.d.ts.map +1 -0
  79. package/dist/constants/AADServerParamKeys.mjs +61 -0
  80. package/dist/constants/AADServerParamKeys.mjs.map +1 -0
  81. package/dist/crypto/ICrypto.mjs +1 -1
  82. package/dist/crypto/ICrypto.mjs.map +1 -1
  83. package/dist/crypto/JoseHeader.mjs +1 -1
  84. package/dist/crypto/JoseHeader.mjs.map +1 -1
  85. package/dist/crypto/PopTokenGenerator.mjs +2 -2
  86. package/dist/crypto/PopTokenGenerator.mjs.map +1 -1
  87. package/dist/error/AuthError.mjs +1 -1
  88. package/dist/error/AuthError.mjs.map +1 -1
  89. package/dist/error/AuthErrorCodes.mjs +1 -1
  90. package/dist/error/AuthErrorCodes.mjs.map +1 -1
  91. package/dist/error/ClientAuthError.mjs +1 -1
  92. package/dist/error/ClientAuthError.mjs.map +1 -1
  93. package/dist/error/ClientAuthErrorCodes.mjs +1 -1
  94. package/dist/error/ClientAuthErrorCodes.mjs.map +1 -1
  95. package/dist/error/ClientConfigurationError.mjs +1 -1
  96. package/dist/error/ClientConfigurationError.mjs.map +1 -1
  97. package/dist/error/ClientConfigurationErrorCodes.mjs +1 -1
  98. package/dist/error/ClientConfigurationErrorCodes.mjs.map +1 -1
  99. package/dist/error/InteractionRequiredAuthError.d.ts +4 -0
  100. package/dist/error/InteractionRequiredAuthError.d.ts.map +1 -1
  101. package/dist/error/InteractionRequiredAuthError.mjs +10 -3
  102. package/dist/error/InteractionRequiredAuthError.mjs.map +1 -1
  103. package/dist/error/InteractionRequiredAuthErrorCodes.d.ts +1 -0
  104. package/dist/error/InteractionRequiredAuthErrorCodes.d.ts.map +1 -1
  105. package/dist/error/InteractionRequiredAuthErrorCodes.mjs +4 -3
  106. package/dist/error/InteractionRequiredAuthErrorCodes.mjs.map +1 -1
  107. package/dist/error/JoseHeaderError.mjs +1 -1
  108. package/dist/error/JoseHeaderError.mjs.map +1 -1
  109. package/dist/error/JoseHeaderErrorCodes.mjs +1 -1
  110. package/dist/error/JoseHeaderErrorCodes.mjs.map +1 -1
  111. package/dist/error/ServerError.mjs +1 -1
  112. package/dist/error/ServerError.mjs.map +1 -1
  113. package/dist/index.cjs +797 -416
  114. package/dist/index.cjs.map +1 -1
  115. package/dist/index.d.ts +5 -4
  116. package/dist/index.d.ts.map +1 -1
  117. package/dist/index.mjs +7 -4
  118. package/dist/index.mjs.map +1 -1
  119. package/dist/logger/Logger.mjs +1 -1
  120. package/dist/logger/Logger.mjs.map +1 -1
  121. package/dist/network/INetworkModule.mjs +1 -1
  122. package/dist/network/INetworkModule.mjs.map +1 -1
  123. package/dist/network/NetworkManager.mjs +1 -1
  124. package/dist/network/NetworkManager.mjs.map +1 -1
  125. package/dist/network/ThrottlingUtils.mjs +1 -1
  126. package/dist/network/ThrottlingUtils.mjs.map +1 -1
  127. package/dist/packageMetadata.d.ts +1 -1
  128. package/dist/packageMetadata.d.ts.map +1 -1
  129. package/dist/packageMetadata.mjs +2 -2
  130. package/dist/packageMetadata.mjs.map +1 -1
  131. package/dist/request/AuthenticationHeaderParser.mjs +1 -1
  132. package/dist/request/AuthenticationHeaderParser.mjs.map +1 -1
  133. package/dist/request/CommonRefreshTokenRequest.d.ts +0 -1
  134. package/dist/request/CommonRefreshTokenRequest.d.ts.map +1 -1
  135. package/dist/request/CommonSilentFlowRequest.d.ts +7 -1
  136. package/dist/request/CommonSilentFlowRequest.d.ts.map +1 -1
  137. package/dist/request/RequestParameterBuilder.d.ts.map +1 -1
  138. package/dist/request/RequestParameterBuilder.mjs +46 -45
  139. package/dist/request/RequestParameterBuilder.mjs.map +1 -1
  140. package/dist/request/RequestValidator.mjs +1 -1
  141. package/dist/request/RequestValidator.mjs.map +1 -1
  142. package/dist/request/ScopeSet.mjs +1 -1
  143. package/dist/request/ScopeSet.mjs.map +1 -1
  144. package/dist/response/ResponseHandler.d.ts +3 -1
  145. package/dist/response/ResponseHandler.d.ts.map +1 -1
  146. package/dist/response/ResponseHandler.mjs +56 -20
  147. package/dist/response/ResponseHandler.mjs.map +1 -1
  148. package/dist/response/ServerAuthorizationTokenResponse.d.ts +1 -0
  149. package/dist/response/ServerAuthorizationTokenResponse.d.ts.map +1 -1
  150. package/dist/telemetry/performance/IPerformanceClient.d.ts +6 -0
  151. package/dist/telemetry/performance/IPerformanceClient.d.ts.map +1 -1
  152. package/dist/telemetry/performance/PerformanceClient.d.ts +9 -2
  153. package/dist/telemetry/performance/PerformanceClient.d.ts.map +1 -1
  154. package/dist/telemetry/performance/PerformanceClient.mjs +17 -13
  155. package/dist/telemetry/performance/PerformanceClient.mjs.map +1 -1
  156. package/dist/telemetry/performance/PerformanceEvent.mjs +1 -1
  157. package/dist/telemetry/performance/PerformanceEvent.mjs.map +1 -1
  158. package/dist/telemetry/performance/StubPerformanceClient.d.ts.map +1 -1
  159. package/dist/telemetry/performance/StubPerformanceClient.mjs +1 -1
  160. package/dist/telemetry/performance/StubPerformanceClient.mjs.map +1 -1
  161. package/dist/telemetry/server/ServerTelemetryManager.mjs +1 -1
  162. package/dist/telemetry/server/ServerTelemetryManager.mjs.map +1 -1
  163. package/dist/url/UrlString.mjs +1 -1
  164. package/dist/url/UrlString.mjs.map +1 -1
  165. package/dist/utils/Constants.d.ts +2 -69
  166. package/dist/utils/Constants.d.ts.map +1 -1
  167. package/dist/utils/Constants.mjs +6 -70
  168. package/dist/utils/Constants.mjs.map +1 -1
  169. package/dist/utils/FunctionWrappers.mjs +1 -1
  170. package/dist/utils/FunctionWrappers.mjs.map +1 -1
  171. package/dist/utils/ProtocolUtils.mjs +1 -1
  172. package/dist/utils/ProtocolUtils.mjs.map +1 -1
  173. package/dist/utils/StringUtils.mjs +1 -1
  174. package/dist/utils/StringUtils.mjs.map +1 -1
  175. package/dist/utils/TimeUtils.mjs +1 -1
  176. package/dist/utils/TimeUtils.mjs.map +1 -1
  177. package/dist/utils/UrlUtils.mjs +1 -1
  178. package/dist/utils/UrlUtils.mjs.map +1 -1
  179. package/package.json +93 -92
  180. package/src/account/AccountInfo.ts +96 -0
  181. package/src/account/ClientInfo.ts +2 -3
  182. package/src/account/TokenClaims.ts +28 -0
  183. package/src/authority/Authority.ts +38 -5
  184. package/src/cache/CacheManager.ts +410 -162
  185. package/src/cache/entities/AccountEntity.ts +84 -33
  186. package/src/cache/entities/ThrottlingEntity.ts +2 -24
  187. package/src/cache/utils/CacheHelpers.ts +22 -2
  188. package/src/cache/utils/CacheTypes.ts +11 -0
  189. package/src/client/AuthorizationCodeClient.ts +4 -5
  190. package/src/client/RefreshTokenClient.ts +35 -14
  191. package/src/client/SilentFlowClient.ts +31 -11
  192. package/src/config/ClientConfiguration.ts +4 -4
  193. package/src/constants/AADServerParamKeys.ts +57 -0
  194. package/src/crypto/PopTokenGenerator.ts +1 -1
  195. package/src/error/InteractionRequiredAuthError.ts +12 -2
  196. package/src/error/InteractionRequiredAuthErrorCodes.ts +1 -0
  197. package/src/index.ts +18 -5
  198. package/src/packageMetadata.ts +1 -1
  199. package/src/request/CommonRefreshTokenRequest.ts +0 -1
  200. package/src/request/CommonSilentFlowRequest.ts +7 -1
  201. package/src/request/RequestParameterBuilder.ts +7 -5
  202. package/src/response/ResponseHandler.ts +109 -25
  203. package/src/response/ServerAuthorizationTokenResponse.ts +1 -0
  204. package/src/telemetry/performance/IPerformanceClient.ts +6 -0
  205. package/src/telemetry/performance/PerformanceClient.ts +24 -31
  206. package/src/telemetry/performance/StubPerformanceClient.ts +0 -1
  207. package/src/utils/Constants.ts +4 -72
  208. package/dist/cache/entities/ThrottlingEntity.mjs +0 -30
  209. package/dist/cache/entities/ThrottlingEntity.mjs.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! @azure/msal-common v14.4.1-beta.1 2023-11-14 */
1
+ /*! @azure/msal-common v14.6.0-alpha.0 2023-12-15 */
2
2
  'use strict';
3
3
  'use strict';
4
4
 
@@ -69,6 +69,7 @@ const HttpStatus = {
69
69
  SUCCESS_RANGE_END: 299,
70
70
  REDIRECT: 302,
71
71
  CLIENT_ERROR_RANGE_START: 400,
72
+ UNAUTHORIZED: 401,
72
73
  CLIENT_ERROR_RANGE_END: 499,
73
74
  SERVER_ERROR_RANGE_START: 500,
74
75
  SERVER_ERROR_RANGE_END: 599,
@@ -111,59 +112,6 @@ const AADAuthorityConstants = {
111
112
  ORGANIZATIONS: "organizations",
112
113
  CONSUMERS: "consumers",
113
114
  };
114
- /**
115
- * Keys in the hashParams sent by AAD Server
116
- */
117
- const AADServerParamKeys = {
118
- CLIENT_ID: "client_id",
119
- REDIRECT_URI: "redirect_uri",
120
- RESPONSE_TYPE: "response_type",
121
- RESPONSE_MODE: "response_mode",
122
- GRANT_TYPE: "grant_type",
123
- CLAIMS: "claims",
124
- SCOPE: "scope",
125
- ERROR: "error",
126
- ERROR_DESCRIPTION: "error_description",
127
- ACCESS_TOKEN: "access_token",
128
- ID_TOKEN: "id_token",
129
- REFRESH_TOKEN: "refresh_token",
130
- EXPIRES_IN: "expires_in",
131
- STATE: "state",
132
- NONCE: "nonce",
133
- PROMPT: "prompt",
134
- SESSION_STATE: "session_state",
135
- CLIENT_INFO: "client_info",
136
- CODE: "code",
137
- CODE_CHALLENGE: "code_challenge",
138
- CODE_CHALLENGE_METHOD: "code_challenge_method",
139
- CODE_VERIFIER: "code_verifier",
140
- CLIENT_REQUEST_ID: "client-request-id",
141
- X_CLIENT_SKU: "x-client-SKU",
142
- X_CLIENT_VER: "x-client-VER",
143
- X_CLIENT_OS: "x-client-OS",
144
- X_CLIENT_CPU: "x-client-CPU",
145
- X_CLIENT_CURR_TELEM: "x-client-current-telemetry",
146
- X_CLIENT_LAST_TELEM: "x-client-last-telemetry",
147
- X_MS_LIB_CAPABILITY: "x-ms-lib-capability",
148
- X_APP_NAME: "x-app-name",
149
- X_APP_VER: "x-app-ver",
150
- POST_LOGOUT_URI: "post_logout_redirect_uri",
151
- ID_TOKEN_HINT: "id_token_hint",
152
- DEVICE_CODE: "device_code",
153
- CLIENT_SECRET: "client_secret",
154
- CLIENT_ASSERTION: "client_assertion",
155
- CLIENT_ASSERTION_TYPE: "client_assertion_type",
156
- TOKEN_TYPE: "token_type",
157
- REQ_CNF: "req_cnf",
158
- OBO_ASSERTION: "assertion",
159
- REQUESTED_TOKEN_USE: "requested_token_use",
160
- ON_BEHALF_OF: "on_behalf_of",
161
- FOCI: "foci",
162
- CCS_HEADER: "X-AnchorMailbox",
163
- RETURN_SPA_CODE: "return_spa_code",
164
- NATIVE_BROKER: "nativebroker",
165
- LOGOUT_HINT: "logout_hint",
166
- };
167
115
  /**
168
116
  * Claims request keys
169
117
  */
@@ -184,20 +132,6 @@ const PromptValue = {
184
132
  CREATE: "create",
185
133
  NO_SESSION: "no_session",
186
134
  };
187
- /**
188
- * SSO Types - generated to populate hints
189
- */
190
- const SSOTypes = {
191
- ACCOUNT: "account",
192
- SID: "sid",
193
- LOGIN_HINT: "login_hint",
194
- ID_TOKEN: "id_token",
195
- DOMAIN_HINT: "domain_hint",
196
- ORGANIZATIONS: "organizations",
197
- CONSUMERS: "consumers",
198
- ACCOUNT_ID: "accountIdentifier",
199
- HOMEACCOUNT_ID: "homeAccountIdentifier",
200
- };
201
135
  /**
202
136
  * allowed values for codeVerifier
203
137
  */
@@ -274,7 +208,7 @@ const CacheType = {
274
208
  * More Cache related constants
275
209
  */
276
210
  const APP_METADATA = "appmetadata";
277
- const CLIENT_INFO = "client_info";
211
+ const CLIENT_INFO$1 = "client_info";
278
212
  const THE_FAMILY_ID = "1";
279
213
  const AUTHORITY_METADATA_CONSTANTS = {
280
214
  CACHE_KEY: "authority-metadata",
@@ -376,7 +310,9 @@ const JsonWebTokenTypes = {
376
310
  Jwk: "JWK",
377
311
  Pop: "pop",
378
312
  };
379
- const ONE_DAY_IN_MS = 86400000;
313
+ const ONE_DAY_IN_MS = 86400000;
314
+ // Token renewal offset default in seconds
315
+ const DEFAULT_TOKEN_RENEWAL_OFFSET_SEC = 300;
380
316
 
381
317
  /*
382
318
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -1010,7 +946,7 @@ class Logger {
1010
946
 
1011
947
  /* eslint-disable header/header */
1012
948
  const name = "@azure/msal-common";
1013
- const version = "14.4.1-beta.1";
949
+ const version = "14.6.0-alpha.0";
1014
950
 
1015
951
  /*
1016
952
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -1262,7 +1198,7 @@ function createRefreshTokenEntity(homeAccountId, environment, refreshToken, clie
1262
1198
  rtEntity.familyId = familyId;
1263
1199
  }
1264
1200
  if (expiresOn) {
1265
- rtEntity.expiresOn = expiresOn;
1201
+ rtEntity.expiresOn = expiresOn.toString();
1266
1202
  }
1267
1203
  return rtEntity;
1268
1204
  }
@@ -1376,6 +1312,22 @@ function isServerTelemetryEntity(key, entity) {
1376
1312
  entity.hasOwnProperty("cacheHits");
1377
1313
  }
1378
1314
  return validateKey && validateEntity;
1315
+ }
1316
+ /**
1317
+ * validates if a given cache entry is "Throttling", parses <key,value>
1318
+ * @param key
1319
+ * @param entity
1320
+ */
1321
+ function isThrottlingEntity(key, entity) {
1322
+ let validateKey = false;
1323
+ if (key) {
1324
+ validateKey = key.indexOf(ThrottlingConstants.THROTTLING_PREFIX) === 0;
1325
+ }
1326
+ let validateEntity = true;
1327
+ if (entity) {
1328
+ validateEntity = entity.hasOwnProperty("throttleTime");
1329
+ }
1330
+ return validateKey && validateEntity;
1379
1331
  }
1380
1332
 
1381
1333
  var CacheHelpers = /*#__PURE__*/Object.freeze({
@@ -1388,7 +1340,8 @@ var CacheHelpers = /*#__PURE__*/Object.freeze({
1388
1340
  isCredentialEntity: isCredentialEntity,
1389
1341
  isIdTokenEntity: isIdTokenEntity,
1390
1342
  isRefreshTokenEntity: isRefreshTokenEntity,
1391
- isServerTelemetryEntity: isServerTelemetryEntity
1343
+ isServerTelemetryEntity: isServerTelemetryEntity,
1344
+ isThrottlingEntity: isThrottlingEntity
1392
1345
  });
1393
1346
 
1394
1347
  /*
@@ -1883,12 +1836,12 @@ class ScopeSet {
1883
1836
  * @param rawClientInfo
1884
1837
  * @param crypto
1885
1838
  */
1886
- function buildClientInfo(rawClientInfo, crypto) {
1839
+ function buildClientInfo(rawClientInfo, base64Decode) {
1887
1840
  if (!rawClientInfo) {
1888
1841
  throw createClientAuthError(clientInfoEmptyError);
1889
1842
  }
1890
1843
  try {
1891
- const decodedClientInfo = crypto.base64Decode(rawClientInfo);
1844
+ const decodedClientInfo = base64Decode(rawClientInfo);
1892
1845
  return JSON.parse(decodedClientInfo);
1893
1846
  }
1894
1847
  catch (e) {
@@ -1912,6 +1865,66 @@ function buildClientInfoFromHomeAccountId(homeAccountId) {
1912
1865
  };
1913
1866
  }
1914
1867
 
1868
+ /*
1869
+ * Copyright (c) Microsoft Corporation. All rights reserved.
1870
+ * Licensed under the MIT License.
1871
+ */
1872
+ /**
1873
+ * Returns true if tenantId matches the utid portion of homeAccountId
1874
+ * @param tenantId
1875
+ * @param homeAccountId
1876
+ * @returns
1877
+ */
1878
+ function tenantIdMatchesHomeTenant(tenantId, homeAccountId) {
1879
+ return (!!tenantId &&
1880
+ !!homeAccountId &&
1881
+ tenantId === homeAccountId.split(".")[1]);
1882
+ }
1883
+ function buildTenantProfileFromIdTokenClaims(homeAccountId, idTokenClaims) {
1884
+ const { oid, sub, tid, name, tfp, acr } = idTokenClaims;
1885
+ /**
1886
+ * 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:
1887
+ * 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.
1888
+ * tfp - Trust Framework Policy claim that identifies the policy that was used to authenticate the user. Functions as tenant for B2C scenarios.
1889
+ * acr - Authentication Context Class Reference claim used only with older B2C policies. Fallback in case tfp is not present, but likely won't be present anyway.
1890
+ */
1891
+ const tenantId = tid || tfp || acr || "";
1892
+ return {
1893
+ tenantId: tenantId,
1894
+ localAccountId: oid || sub || "",
1895
+ name: name,
1896
+ isHomeTenant: tenantIdMatchesHomeTenant(tenantId, homeAccountId),
1897
+ };
1898
+ }
1899
+ /**
1900
+ * Replaces account info that varies by tenant profile sourced from the ID token claims passed in with the tenant-specific account info
1901
+ * @param baseAccountInfo
1902
+ * @param idTokenClaims
1903
+ * @returns
1904
+ */
1905
+ function updateAccountTenantProfileData(baseAccountInfo, tenantProfile, idTokenClaims) {
1906
+ let updatedAccountInfo = baseAccountInfo;
1907
+ // Tenant Profile overrides passed in account info
1908
+ if (tenantProfile) {
1909
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1910
+ const { isHomeTenant, ...tenantProfileOverride } = tenantProfile;
1911
+ updatedAccountInfo = { ...baseAccountInfo, ...tenantProfileOverride };
1912
+ }
1913
+ // ID token claims override passed in account info and tenant profile
1914
+ if (idTokenClaims) {
1915
+ // Ignore isHomeTenant, loginHint, and sid which are part of tenant profile but not base account info
1916
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1917
+ const { isHomeTenant, ...claimsSourcedTenantProfile } = buildTenantProfileFromIdTokenClaims(baseAccountInfo.homeAccountId, idTokenClaims);
1918
+ updatedAccountInfo = {
1919
+ ...updatedAccountInfo,
1920
+ ...claimsSourcedTenantProfile,
1921
+ idTokenClaims: idTokenClaims,
1922
+ };
1923
+ return updatedAccountInfo;
1924
+ }
1925
+ return updatedAccountInfo;
1926
+ }
1927
+
1915
1928
  /*
1916
1929
  * Copyright (c) Microsoft Corporation. All rights reserved.
1917
1930
  * Licensed under the MIT License.
@@ -1926,6 +1939,27 @@ const AuthorityType = {
1926
1939
  Ciam: 3,
1927
1940
  };
1928
1941
 
1942
+ /*
1943
+ * Copyright (c) Microsoft Corporation. All rights reserved.
1944
+ * Licensed under the MIT License.
1945
+ */
1946
+ /**
1947
+ * Gets tenantId from available ID token claims to set as credential realm with the following precedence:
1948
+ * 1. tid - if the token is acquired from an Azure AD tenant tid will be present
1949
+ * 2. tfp - if the token is acquired from a modern B2C tenant tfp should be present
1950
+ * 3. acr - if the token is acquired from a legacy B2C tenant acr should be present
1951
+ * Downcased to match the realm case-insensitive comparison requirements
1952
+ * @param idTokenClaims
1953
+ * @returns
1954
+ */
1955
+ function getTenantIdFromIdTokenClaims(idTokenClaims) {
1956
+ if (idTokenClaims) {
1957
+ const tenantId = idTokenClaims.tid || idTokenClaims.tfp || idTokenClaims.acr;
1958
+ return tenantId || null;
1959
+ }
1960
+ return null;
1961
+ }
1962
+
1929
1963
  /*
1930
1964
  * Copyright (c) Microsoft Corporation. All rights reserved.
1931
1965
  * Licensed under the MIT License.
@@ -1960,8 +1994,8 @@ const ProtocolMode = {
1960
1994
  * name: Full name for the account, including given name and family name,
1961
1995
  * lastModificationTime: last time this entity was modified in the cache
1962
1996
  * lastModificationApp:
1963
- * idTokenClaims: Object containing claims parsed from ID token
1964
1997
  * nativeAccountId: Account identifier on the native device
1998
+ * tenantProfiles: Array of tenant profile objects for each tenant that the account has authenticated with in the browser
1965
1999
  * }
1966
2000
  * @internal
1967
2001
  */
@@ -1996,20 +2030,30 @@ class AccountEntity {
1996
2030
  username: this.username,
1997
2031
  localAccountId: this.localAccountId,
1998
2032
  name: this.name,
1999
- idTokenClaims: this.idTokenClaims,
2000
2033
  nativeAccountId: this.nativeAccountId,
2001
2034
  authorityType: this.authorityType,
2035
+ // Deserialize tenant profiles array into a Map
2036
+ tenantProfiles: new Map((this.tenantProfiles || []).map((tenantProfile) => {
2037
+ return [tenantProfile.tenantId, tenantProfile];
2038
+ })),
2002
2039
  };
2003
2040
  }
2041
+ /**
2042
+ * Returns true if the account entity is in single tenant format (outdated), false otherwise
2043
+ */
2044
+ isSingleTenant() {
2045
+ return !this.tenantProfiles;
2046
+ }
2004
2047
  /**
2005
2048
  * Generates account key from interface
2006
2049
  * @param accountInterface
2007
2050
  */
2008
2051
  static generateAccountCacheKey(accountInterface) {
2052
+ const homeTenantId = accountInterface.homeAccountId.split(".")[1];
2009
2053
  const accountKey = [
2010
2054
  accountInterface.homeAccountId,
2011
- accountInterface.environment || Constants.EMPTY_STRING,
2012
- accountInterface.tenantId || Constants.EMPTY_STRING,
2055
+ accountInterface.environment || "",
2056
+ homeTenantId || accountInterface.tenantId || "",
2013
2057
  ];
2014
2058
  return accountKey.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
2015
2059
  }
@@ -2017,7 +2061,7 @@ class AccountEntity {
2017
2061
  * Build Account cache from IdToken, clientInfo and authority/policy. Associated with AAD.
2018
2062
  * @param accountDetails
2019
2063
  */
2020
- static createAccount(accountDetails, authority) {
2064
+ static createAccount(accountDetails, authority, base64Decode) {
2021
2065
  const account = new AccountEntity();
2022
2066
  if (authority.authorityType === AuthorityType.Adfs) {
2023
2067
  account.authorityType = CacheAccountType.ADFS_ACCOUNT_TYPE;
@@ -2028,6 +2072,10 @@ class AccountEntity {
2028
2072
  else {
2029
2073
  account.authorityType = CacheAccountType.GENERIC_ACCOUNT_TYPE;
2030
2074
  }
2075
+ let clientInfo;
2076
+ if (accountDetails.clientInfo && base64Decode) {
2077
+ clientInfo = buildClientInfo(accountDetails.clientInfo, base64Decode);
2078
+ }
2031
2079
  account.clientInfo = accountDetails.clientInfo;
2032
2080
  account.homeAccountId = accountDetails.homeAccountId;
2033
2081
  account.nativeAccountId = accountDetails.nativeAccountId;
@@ -2039,12 +2087,15 @@ class AccountEntity {
2039
2087
  account.environment = env;
2040
2088
  // non AAD scenarios can have empty realm
2041
2089
  account.realm =
2042
- accountDetails.idTokenClaims.tid || Constants.EMPTY_STRING;
2090
+ clientInfo?.utid ||
2091
+ getTenantIdFromIdTokenClaims(accountDetails.idTokenClaims) ||
2092
+ "";
2043
2093
  // How do you account for MSA CID here?
2044
2094
  account.localAccountId =
2045
- accountDetails.idTokenClaims.oid ||
2095
+ clientInfo?.uid ||
2096
+ accountDetails.idTokenClaims.oid ||
2046
2097
  accountDetails.idTokenClaims.sub ||
2047
- Constants.EMPTY_STRING;
2098
+ "";
2048
2099
  /*
2049
2100
  * In B2C scenarios the emails claim is used instead of preferred_username and it is an array.
2050
2101
  * In most cases it will contain a single email. This field should not be relied upon if a custom
@@ -2055,10 +2106,21 @@ class AccountEntity {
2055
2106
  const email = accountDetails.idTokenClaims.emails
2056
2107
  ? accountDetails.idTokenClaims.emails[0]
2057
2108
  : null;
2058
- account.username = preferredUsername || email || Constants.EMPTY_STRING;
2109
+ account.username = preferredUsername || email || "";
2059
2110
  account.name = accountDetails.idTokenClaims.name;
2060
2111
  account.cloudGraphHostName = accountDetails.cloudGraphHostName;
2061
2112
  account.msGraphHost = accountDetails.msGraphHost;
2113
+ if (accountDetails.tenantProfiles) {
2114
+ account.tenantProfiles = accountDetails.tenantProfiles;
2115
+ }
2116
+ else {
2117
+ const tenantProfiles = [];
2118
+ if (accountDetails.idTokenClaims) {
2119
+ const tenantProfile = buildTenantProfileFromIdTokenClaims(accountDetails.homeAccountId, accountDetails.idTokenClaims);
2120
+ tenantProfiles.push(tenantProfile);
2121
+ }
2122
+ account.tenantProfiles = tenantProfiles;
2123
+ }
2062
2124
  return account;
2063
2125
  }
2064
2126
  /**
@@ -2081,6 +2143,8 @@ class AccountEntity {
2081
2143
  account.name = accountInfo.name;
2082
2144
  account.cloudGraphHostName = cloudGraphHostName;
2083
2145
  account.msGraphHost = msGraphHost;
2146
+ // Serialize tenant profiles map into an array
2147
+ account.tenantProfiles = Array.from(accountInfo.tenantProfiles?.values() || []);
2084
2148
  return account;
2085
2149
  }
2086
2150
  /**
@@ -2089,27 +2153,23 @@ class AccountEntity {
2089
2153
  * @param authType
2090
2154
  */
2091
2155
  static generateHomeAccountId(serverClientInfo, authType, logger, cryptoObj, idTokenClaims) {
2092
- const accountId = idTokenClaims?.sub
2093
- ? idTokenClaims.sub
2094
- : Constants.EMPTY_STRING;
2095
- // since ADFS does not have tid and does not set client_info
2096
- if (authType === AuthorityType.Adfs ||
2097
- authType === AuthorityType.Dsts) {
2098
- return accountId;
2099
- }
2100
- // for cases where there is clientInfo
2101
- if (serverClientInfo) {
2102
- try {
2103
- const clientInfo = buildClientInfo(serverClientInfo, cryptoObj);
2104
- if (clientInfo.uid && clientInfo.utid) {
2105
- return `${clientInfo.uid}${Separators.CLIENT_INFO_SEPARATOR}${clientInfo.utid}`;
2156
+ // since ADFS/DSTS do not have tid and does not set client_info
2157
+ if (!(authType === AuthorityType.Adfs ||
2158
+ authType === AuthorityType.Dsts)) {
2159
+ // for cases where there is clientInfo
2160
+ if (serverClientInfo) {
2161
+ try {
2162
+ const clientInfo = buildClientInfo(serverClientInfo, cryptoObj.base64Decode);
2163
+ if (clientInfo.uid && clientInfo.utid) {
2164
+ return `${clientInfo.uid}.${clientInfo.utid}`;
2165
+ }
2106
2166
  }
2167
+ catch (e) { }
2107
2168
  }
2108
- catch (e) { }
2169
+ logger.warning("No client info in response");
2109
2170
  }
2110
2171
  // default to "sub" claim
2111
- logger.verbose("No client info in response");
2112
- return accountId;
2172
+ return idTokenClaims?.sub || "";
2113
2173
  }
2114
2174
  /**
2115
2175
  * Validates an entity: checks for all expected params
@@ -2995,25 +3055,19 @@ class CacheManager {
2995
3055
  * @returns Array of AccountInfo objects in cache
2996
3056
  */
2997
3057
  getAllAccounts(accountFilter) {
2998
- const validAccounts = [];
2999
- this.getAccountsFilteredBy(accountFilter || {}).forEach((accountEntity) => {
3000
- const accountInfo = this.getAccountInfoFromEntity(accountEntity, accountFilter);
3001
- if (accountInfo) {
3002
- validAccounts.push(accountInfo);
3003
- }
3004
- });
3005
- return validAccounts;
3058
+ return this.buildTenantProfiles(this.getAccountsFilteredBy(accountFilter || {}), accountFilter);
3006
3059
  }
3007
3060
  /**
3008
- * Gets accountInfo object based on provided filters
3061
+ * Gets first tenanted AccountInfo object found based on provided filters
3009
3062
  */
3010
3063
  getAccountInfoFilteredBy(accountFilter) {
3011
3064
  const allAccounts = this.getAllAccounts(accountFilter);
3012
3065
  if (allAccounts.length > 1) {
3013
- // If one or more accounts are found, further filter to the first account that has an ID token
3014
- return allAccounts.filter((account) => {
3015
- return !!account.idTokenClaims;
3016
- })[0];
3066
+ // If one or more accounts are found, prioritize accounts that have an ID token
3067
+ const sortedAccounts = allAccounts.sort((account) => {
3068
+ return account.idTokenClaims ? -1 : 1;
3069
+ });
3070
+ return sortedAccounts[0];
3017
3071
  }
3018
3072
  else if (allAccounts.length === 1) {
3019
3073
  // If only one account is found, return it regardless of whether a matching ID token was found
@@ -3037,27 +3091,104 @@ class CacheManager {
3037
3091
  return null;
3038
3092
  }
3039
3093
  }
3040
- getAccountInfoFromEntity(accountEntity, accountFilter) {
3041
- const accountInfo = accountEntity.getAccountInfo();
3042
- const idToken = this.getIdToken(accountInfo);
3094
+ /**
3095
+ * Matches filtered account entities with cached ID tokens that match the tenant profile-specific account filters
3096
+ * and builds the account info objects from the matching ID token's claims
3097
+ * @param cachedAccounts
3098
+ * @param accountFilter
3099
+ * @returns Array of AccountInfo objects that match account and tenant profile filters
3100
+ */
3101
+ buildTenantProfiles(cachedAccounts, accountFilter) {
3102
+ return cachedAccounts.flatMap((accountEntity) => {
3103
+ return this.getAccountInfoForTenantProfiles(accountEntity, accountFilter);
3104
+ });
3105
+ }
3106
+ getAccountInfoForTenantProfiles(accountEntity, accountFilter) {
3107
+ return this.getTenantProfilesFromAccountEntity(accountEntity, accountFilter?.tenantId, accountFilter);
3108
+ }
3109
+ getTenantedAccountInfoByFilter(accountInfo, tokenKeys, tenantProfile, tenantProfileFilter) {
3110
+ let tenantedAccountInfo = null;
3111
+ let idTokenClaims;
3112
+ if (tenantProfileFilter) {
3113
+ if (!this.tenantProfileMatchesFilter(tenantProfile, tenantProfileFilter)) {
3114
+ return null;
3115
+ }
3116
+ }
3117
+ const idToken = this.getIdToken(accountInfo, tokenKeys, tenantProfile.tenantId);
3043
3118
  if (idToken) {
3044
- const idTokenClaims = extractTokenClaims(idToken.secret, this.cryptoImpl.base64Decode);
3045
- if (this.idTokenClaimsMatchAccountFilter(idTokenClaims, accountFilter)) {
3046
- accountInfo.idToken = idToken.secret;
3047
- accountInfo.idTokenClaims = idTokenClaims;
3048
- return accountInfo;
3119
+ idTokenClaims = extractTokenClaims(idToken.secret, this.cryptoImpl.base64Decode);
3120
+ if (!this.idTokenClaimsMatchTenantProfileFilter(idTokenClaims, tenantProfileFilter)) {
3121
+ // ID token sourced claims don't match so this tenant profile is not a match
3122
+ return null;
3049
3123
  }
3050
3124
  }
3051
- return accountInfo;
3125
+ // Expand tenant profile into account info based on matching tenant profile and if available matching ID token claims
3126
+ tenantedAccountInfo = updateAccountTenantProfileData(accountInfo, tenantProfile, idTokenClaims);
3127
+ return tenantedAccountInfo;
3052
3128
  }
3053
- idTokenClaimsMatchAccountFilter(idTokenClaims, accountFilter) {
3054
- if (accountFilter) {
3055
- if (!!accountFilter.loginHint &&
3056
- !this.matchLoginHint(idTokenClaims, accountFilter.loginHint)) {
3129
+ getTenantProfilesFromAccountEntity(accountEntity, targetTenantId, tenantProfileFilter) {
3130
+ const accountInfo = accountEntity.getAccountInfo();
3131
+ let searchTenantProfiles = accountInfo.tenantProfiles || new Map();
3132
+ const tokenKeys = this.getTokenKeys();
3133
+ // If a tenant ID was provided, only return the tenant profile for that tenant ID if it exists
3134
+ if (targetTenantId) {
3135
+ const tenantProfile = searchTenantProfiles.get(targetTenantId);
3136
+ if (tenantProfile) {
3137
+ // Reduce search field to just this tenant profile
3138
+ searchTenantProfiles = new Map([
3139
+ [targetTenantId, tenantProfile],
3140
+ ]);
3141
+ }
3142
+ else {
3143
+ // No tenant profile for search tenant ID, return empty array
3144
+ return [];
3145
+ }
3146
+ }
3147
+ const matchingTenantProfiles = [];
3148
+ searchTenantProfiles.forEach((tenantProfile) => {
3149
+ const tenantedAccountInfo = this.getTenantedAccountInfoByFilter(accountInfo, tokenKeys, tenantProfile, tenantProfileFilter);
3150
+ if (tenantedAccountInfo) {
3151
+ matchingTenantProfiles.push(tenantedAccountInfo);
3152
+ }
3153
+ });
3154
+ return matchingTenantProfiles;
3155
+ }
3156
+ tenantProfileMatchesFilter(tenantProfile, tenantProfileFilter) {
3157
+ if (!!tenantProfileFilter.localAccountId &&
3158
+ !this.matchLocalAccountIdFromTenantProfile(tenantProfile, tenantProfileFilter.localAccountId)) {
3159
+ return false;
3160
+ }
3161
+ if (!!tenantProfileFilter.name &&
3162
+ !(tenantProfile.name === tenantProfileFilter.name)) {
3163
+ return false;
3164
+ }
3165
+ if (tenantProfileFilter.isHomeTenant !== undefined &&
3166
+ !(tenantProfile.isHomeTenant === tenantProfileFilter.isHomeTenant)) {
3167
+ return false;
3168
+ }
3169
+ return true;
3170
+ }
3171
+ idTokenClaimsMatchTenantProfileFilter(idTokenClaims, tenantProfileFilter) {
3172
+ // Tenant Profile filtering
3173
+ if (tenantProfileFilter) {
3174
+ if (!!tenantProfileFilter.localAccountId &&
3175
+ !this.matchLocalAccountIdFromTokenClaims(idTokenClaims, tenantProfileFilter.localAccountId)) {
3176
+ return false;
3177
+ }
3178
+ if (!!tenantProfileFilter.loginHint &&
3179
+ !this.matchLoginHintFromTokenClaims(idTokenClaims, tenantProfileFilter.loginHint)) {
3180
+ return false;
3181
+ }
3182
+ if (!!tenantProfileFilter.username &&
3183
+ !this.matchUsername(idTokenClaims.preferred_username, tenantProfileFilter.username)) {
3184
+ return false;
3185
+ }
3186
+ if (!!tenantProfileFilter.name &&
3187
+ !this.matchName(idTokenClaims, tenantProfileFilter.name)) {
3057
3188
  return false;
3058
3189
  }
3059
- if (!!accountFilter.sid &&
3060
- !this.matchSid(idTokenClaims, accountFilter.sid)) {
3190
+ if (!!tenantProfileFilter.sid &&
3191
+ !this.matchSid(idTokenClaims, tenantProfileFilter.sid)) {
3061
3192
  return false;
3062
3193
  }
3063
3194
  }
@@ -3122,7 +3253,7 @@ class CacheManager {
3122
3253
  this.setAccessTokenCredential(credential);
3123
3254
  }
3124
3255
  /**
3125
- * Retrieve accounts matching all provided filters; if no filter is set, get all accounts
3256
+ * Retrieve account entities matching all provided tenant-agnostic filters; if no filter is set, get all account entities in the cache
3126
3257
  * Not checking for casing as keys are all generated in lower case, remember to convert to lower case if object properties are compared
3127
3258
  * @param accountFilter - An object containing Account properties to filter by
3128
3259
  */
@@ -3130,11 +3261,12 @@ class CacheManager {
3130
3261
  const allAccountKeys = this.getAccountKeys();
3131
3262
  const matchingAccounts = [];
3132
3263
  allAccountKeys.forEach((cacheKey) => {
3133
- if (!this.isAccountKey(cacheKey, accountFilter.homeAccountId, accountFilter.tenantId)) {
3264
+ if (!this.isAccountKey(cacheKey, accountFilter.homeAccountId)) {
3134
3265
  // Don't parse value if the key doesn't match the account filters
3135
3266
  return;
3136
3267
  }
3137
- const entity = this.getAccount(cacheKey);
3268
+ const entity = this.getAccount(cacheKey, this.commonLogger);
3269
+ // Match base account fields
3138
3270
  if (!entity) {
3139
3271
  return;
3140
3272
  }
@@ -3142,12 +3274,8 @@ class CacheManager {
3142
3274
  !this.matchHomeAccountId(entity, accountFilter.homeAccountId)) {
3143
3275
  return;
3144
3276
  }
3145
- if (!!accountFilter.localAccountId &&
3146
- !this.matchLocalAccountId(entity, accountFilter.localAccountId)) {
3147
- return;
3148
- }
3149
3277
  if (!!accountFilter.username &&
3150
- !this.matchUsername(entity, accountFilter.username)) {
3278
+ !this.matchUsername(entity.username, accountFilter.username)) {
3151
3279
  return;
3152
3280
  }
3153
3281
  if (!!accountFilter.environment &&
@@ -3158,11 +3286,6 @@ class CacheManager {
3158
3286
  !this.matchRealm(entity, accountFilter.realm)) {
3159
3287
  return;
3160
3288
  }
3161
- // tenantId is another name for realm
3162
- if (!!accountFilter.tenantId &&
3163
- !this.matchRealm(entity, accountFilter.tenantId)) {
3164
- return;
3165
- }
3166
3289
  if (!!accountFilter.nativeAccountId &&
3167
3290
  !this.matchNativeAccountId(entity, accountFilter.nativeAccountId)) {
3168
3291
  return;
@@ -3171,8 +3294,16 @@ class CacheManager {
3171
3294
  !this.matchAuthorityType(entity, accountFilter.authorityType)) {
3172
3295
  return;
3173
3296
  }
3174
- if (!!accountFilter.name &&
3175
- !this.matchName(entity, accountFilter.name)) {
3297
+ // If at least one tenant profile matches the tenant profile filter, add the account to the list of matching accounts
3298
+ const tenantProfileFilter = {
3299
+ localAccountId: accountFilter?.localAccountId,
3300
+ name: accountFilter?.name,
3301
+ };
3302
+ const matchingTenantProfiles = entity.tenantProfiles?.filter((tenantProfile) => {
3303
+ return this.tenantProfileMatchesFilter(tenantProfile, tenantProfileFilter);
3304
+ });
3305
+ if (matchingTenantProfiles && matchingTenantProfiles.length === 0) {
3306
+ // No tenant profile for this account matches filter, don't add to list of matching accounts
3176
3307
  return;
3177
3308
  }
3178
3309
  matchingAccounts.push(entity);
@@ -3379,7 +3510,7 @@ class CacheManager {
3379
3510
  * @param account
3380
3511
  */
3381
3512
  async removeAccount(accountKey) {
3382
- const account = this.getAccount(accountKey);
3513
+ const account = this.getAccount(accountKey, this.commonLogger);
3383
3514
  if (!account) {
3384
3515
  return;
3385
3516
  }
@@ -3411,6 +3542,61 @@ class CacheManager {
3411
3542
  });
3412
3543
  await Promise.all(removedCredentials);
3413
3544
  }
3545
+ /**
3546
+ * Migrates a single-tenant account and all it's associated alternate cross-tenant account objects in the
3547
+ * cache into a condensed multi-tenant account object with tenant profiles.
3548
+ * @param accountKey
3549
+ * @param accountEntity
3550
+ * @param logger
3551
+ * @returns
3552
+ */
3553
+ updateOutdatedCachedAccount(accountKey, accountEntity, logger) {
3554
+ // Only update if account entity is defined and has no tenantProfiles object (is outdated)
3555
+ if (accountEntity && accountEntity.isSingleTenant()) {
3556
+ this.commonLogger?.verbose("updateOutdatedCachedAccount: Found a single-tenant (outdated) account entity in the cache, migrating to multi-tenant account entity");
3557
+ // Get keys of all accounts belonging to user
3558
+ const matchingAccountKeys = this.getAccountKeys().filter((key) => {
3559
+ return key.startsWith(accountEntity.homeAccountId);
3560
+ });
3561
+ // Get all account entities belonging to user
3562
+ const accountsToMerge = [];
3563
+ matchingAccountKeys.forEach((key) => {
3564
+ const account = this.getCachedAccountEntity(key);
3565
+ if (account) {
3566
+ accountsToMerge.push(account);
3567
+ }
3568
+ });
3569
+ // Set base account to home account if available, any account if not
3570
+ const baseAccount = accountsToMerge.find((account) => {
3571
+ return tenantIdMatchesHomeTenant(account.realm, account.homeAccountId);
3572
+ }) || accountsToMerge[0];
3573
+ // Populate tenant profiles built from each account entity belonging to the user
3574
+ baseAccount.tenantProfiles = accountsToMerge.map((account) => {
3575
+ return {
3576
+ tenantId: account.realm,
3577
+ localAccountId: account.localAccountId,
3578
+ name: account.name,
3579
+ isHomeTenant: tenantIdMatchesHomeTenant(account.realm, account.homeAccountId),
3580
+ };
3581
+ });
3582
+ const updatedAccount = CacheManager.toObject(new AccountEntity(), {
3583
+ ...baseAccount,
3584
+ });
3585
+ const newAccountKey = updatedAccount.generateAccountKey();
3586
+ // Clear cache of legacy account objects that have been collpsed into tenant profiles
3587
+ matchingAccountKeys.forEach((key) => {
3588
+ if (key !== newAccountKey) {
3589
+ this.removeOutdatedAccount(accountKey);
3590
+ }
3591
+ });
3592
+ // Cache updated account object
3593
+ this.setAccount(updatedAccount);
3594
+ logger?.verbose("Updated an outdated account entity in the cache");
3595
+ return updatedAccount;
3596
+ }
3597
+ // No update is necessary
3598
+ return accountEntity;
3599
+ }
3414
3600
  /**
3415
3601
  * returns a boolean if the given credential is removed
3416
3602
  * @param credential
@@ -3450,74 +3636,73 @@ class CacheManager {
3450
3636
  });
3451
3637
  return true;
3452
3638
  }
3453
- /**
3454
- * Retrieve the cached credentials into a cacherecord
3455
- * @param account {AccountInfo}
3456
- * @param request {BaseAuthRequest}
3457
- * @param environment {string}
3458
- * @param performanceClient {?IPerformanceClient}
3459
- * @param correlationId {?string}
3460
- */
3461
- readCacheRecord(account, request, environment, performanceClient, correlationId) {
3462
- const tokenKeys = this.getTokenKeys();
3463
- const cachedAccount = this.readAccountFromCache(account);
3464
- const cachedIdToken = this.getIdToken(account, tokenKeys, performanceClient, correlationId);
3465
- const cachedAccessToken = this.getAccessToken(account, request, tokenKeys, performanceClient, correlationId);
3466
- const cachedRefreshToken = this.getRefreshToken(account, false, tokenKeys, performanceClient, correlationId);
3467
- const cachedAppMetadata = this.readAppMetadataFromCache(environment);
3468
- if (cachedAccount && cachedIdToken) {
3469
- cachedAccount.idTokenClaims = extractTokenClaims(cachedIdToken.secret, this.cryptoImpl.base64Decode);
3470
- }
3471
- return {
3472
- account: cachedAccount,
3473
- idToken: cachedIdToken,
3474
- accessToken: cachedAccessToken,
3475
- refreshToken: cachedRefreshToken,
3476
- appMetadata: cachedAppMetadata,
3477
- };
3478
- }
3479
3639
  /**
3480
3640
  * Retrieve AccountEntity from cache
3481
3641
  * @param account
3482
3642
  */
3483
3643
  readAccountFromCache(account) {
3484
3644
  const accountKey = AccountEntity.generateAccountCacheKey(account);
3485
- return this.getAccount(accountKey);
3645
+ return this.getAccount(accountKey, this.commonLogger);
3486
3646
  }
3487
3647
  /**
3488
3648
  * Retrieve IdTokenEntity from cache
3489
3649
  * @param account {AccountInfo}
3490
3650
  * @param tokenKeys {?TokenKeys}
3651
+ * @param targetRealm {?string}
3491
3652
  * @param performanceClient {?IPerformanceClient}
3492
3653
  * @param correlationId {?string}
3493
3654
  */
3494
- getIdToken(account, tokenKeys, performanceClient, correlationId) {
3655
+ getIdToken(account, tokenKeys, targetRealm, performanceClient, correlationId) {
3495
3656
  this.commonLogger.trace("CacheManager - getIdToken called");
3496
3657
  const idTokenFilter = {
3497
3658
  homeAccountId: account.homeAccountId,
3498
3659
  environment: account.environment,
3499
3660
  credentialType: CredentialType.ID_TOKEN,
3500
3661
  clientId: this.clientId,
3501
- realm: account.tenantId,
3662
+ realm: targetRealm,
3502
3663
  };
3503
- const idTokens = this.getIdTokensByFilter(idTokenFilter, tokenKeys);
3504
- const numIdTokens = idTokens.length;
3664
+ const idTokenMap = this.getIdTokensByFilter(idTokenFilter, tokenKeys);
3665
+ const numIdTokens = idTokenMap.size;
3505
3666
  if (numIdTokens < 1) {
3506
3667
  this.commonLogger.info("CacheManager:getIdToken - No token found");
3507
3668
  return null;
3508
3669
  }
3509
3670
  else if (numIdTokens > 1) {
3510
- this.commonLogger.info("CacheManager:getIdToken - Multiple id tokens found, clearing them");
3511
- idTokens.forEach((idToken) => {
3512
- this.removeIdToken(generateCredentialKey(idToken));
3671
+ let tokensToBeRemoved = idTokenMap;
3672
+ // Multiple tenant profiles and no tenant specified, pick home account
3673
+ if (!targetRealm) {
3674
+ const homeIdTokenMap = new Map();
3675
+ idTokenMap.forEach((idToken, key) => {
3676
+ if (idToken.realm === account.tenantId) {
3677
+ homeIdTokenMap.set(key, idToken);
3678
+ }
3679
+ });
3680
+ const numHomeIdTokens = homeIdTokenMap.size;
3681
+ if (numHomeIdTokens < 1) {
3682
+ this.commonLogger.info("CacheManager:getIdToken - Multiple ID tokens found for account but none match account entity tenant id, returning first result");
3683
+ return idTokenMap.values().next().value;
3684
+ }
3685
+ else if (numHomeIdTokens === 1) {
3686
+ this.commonLogger.info("CacheManager:getIdToken - Multiple ID tokens found for account, defaulting to home tenant profile");
3687
+ return homeIdTokenMap.values().next().value;
3688
+ }
3689
+ else {
3690
+ // Multiple ID tokens for home tenant profile, remove all and return null
3691
+ tokensToBeRemoved = homeIdTokenMap;
3692
+ }
3693
+ }
3694
+ // Multiple tokens for a single tenant profile, remove all and return null
3695
+ this.commonLogger.info("CacheManager:getIdToken - Multiple matching ID tokens found, clearing them");
3696
+ tokensToBeRemoved.forEach((idToken, key) => {
3697
+ this.removeIdToken(key);
3513
3698
  });
3514
3699
  if (performanceClient && correlationId) {
3515
- performanceClient.addFields({ multiMatchedID: idTokens.length }, correlationId);
3700
+ performanceClient.addFields({ multiMatchedID: idTokenMap.size }, correlationId);
3516
3701
  }
3517
3702
  return null;
3518
3703
  }
3519
- this.commonLogger.info("CacheManager:getIdToken - Returning id token");
3520
- return idTokens[0];
3704
+ this.commonLogger.info("CacheManager:getIdToken - Returning ID token");
3705
+ return idTokenMap.values().next().value;
3521
3706
  }
3522
3707
  /**
3523
3708
  * Gets all idTokens matching the given filter
@@ -3526,7 +3711,7 @@ class CacheManager {
3526
3711
  */
3527
3712
  getIdTokensByFilter(filter, tokenKeys) {
3528
3713
  const idTokenKeys = (tokenKeys && tokenKeys.idToken) || this.getTokenKeys().idToken;
3529
- const idTokens = [];
3714
+ const idTokens = new Map();
3530
3715
  idTokenKeys.forEach((key) => {
3531
3716
  if (!this.idTokenKeyMatchesFilter(key, {
3532
3717
  clientId: this.clientId,
@@ -3536,7 +3721,7 @@ class CacheManager {
3536
3721
  }
3537
3722
  const idToken = this.getIdTokenCredential(key);
3538
3723
  if (idToken && this.credentialMatchesFilter(idToken, filter)) {
3539
- idTokens.push(idToken);
3724
+ idTokens.set(key, idToken);
3540
3725
  }
3541
3726
  });
3542
3727
  return idTokens;
@@ -3581,7 +3766,7 @@ class CacheManager {
3581
3766
  * @param performanceClient {?IPerformanceClient}
3582
3767
  * @param correlationId {?string}
3583
3768
  */
3584
- getAccessToken(account, request, tokenKeys, performanceClient, correlationId) {
3769
+ getAccessToken(account, request, tokenKeys, targetRealm, performanceClient, correlationId) {
3585
3770
  this.commonLogger.trace("CacheManager - getAccessToken called");
3586
3771
  const scopes = ScopeSet.createSearchScopes(request.scopes);
3587
3772
  const authScheme = request.authenticationScheme || AuthenticationScheme.BEARER;
@@ -3599,7 +3784,7 @@ class CacheManager {
3599
3784
  environment: account.environment,
3600
3785
  credentialType: credentialType,
3601
3786
  clientId: this.clientId,
3602
- realm: account.tenantId,
3787
+ realm: targetRealm || account.tenantId,
3603
3788
  target: scopes,
3604
3789
  tokenType: authScheme,
3605
3790
  keyId: request.sshKid,
@@ -3808,19 +3993,12 @@ class CacheManager {
3808
3993
  * @param localAccountId
3809
3994
  * @returns
3810
3995
  */
3811
- matchLocalAccountId(entity, localAccountId) {
3812
- return !!(typeof entity.localAccountId === "string" &&
3813
- localAccountId === entity.localAccountId);
3996
+ matchLocalAccountIdFromTokenClaims(tokenClaims, localAccountId) {
3997
+ const idTokenLocalAccountId = tokenClaims.oid || tokenClaims.sub;
3998
+ return localAccountId === idTokenLocalAccountId;
3814
3999
  }
3815
- /**
3816
- * helper to match usernames
3817
- * @param entity
3818
- * @param username
3819
- * @returns
3820
- */
3821
- matchUsername(entity, username) {
3822
- return !!(typeof entity.username === "string" &&
3823
- username.toLowerCase() === entity.username.toLowerCase());
4000
+ matchLocalAccountIdFromTenantProfile(tenantProfile, localAccountId) {
4001
+ return tenantProfile.localAccountId === localAccountId;
3824
4002
  }
3825
4003
  /**
3826
4004
  * helper to match names
@@ -3828,8 +4006,19 @@ class CacheManager {
3828
4006
  * @param name
3829
4007
  * @returns true if the downcased name properties are present and match in the filter and the entity
3830
4008
  */
3831
- matchName(entity, name) {
3832
- return !!(name.toLowerCase() === entity.name?.toLowerCase());
4009
+ matchName(claims, name) {
4010
+ return !!(name.toLowerCase() === claims.name?.toLowerCase());
4011
+ }
4012
+ /**
4013
+ * helper to match usernames
4014
+ * @param entity
4015
+ * @param username
4016
+ * @returns
4017
+ */
4018
+ matchUsername(cachedUsername, filterUsername) {
4019
+ return !!(cachedUsername &&
4020
+ typeof cachedUsername === "string" &&
4021
+ filterUsername?.toLowerCase() === cachedUsername.toLowerCase());
3833
4022
  }
3834
4023
  /**
3835
4024
  * helper to match assertion
@@ -3893,7 +4082,7 @@ class CacheManager {
3893
4082
  * @param realm
3894
4083
  */
3895
4084
  matchRealm(entity, realm) {
3896
- return !!(entity.realm && realm === entity.realm);
4085
+ return !!(entity.realm?.toLowerCase() === realm.toLowerCase());
3897
4086
  }
3898
4087
  /**
3899
4088
  * helper to match nativeAccountId
@@ -3913,26 +4102,26 @@ class CacheManager {
3913
4102
  * @param loginHint
3914
4103
  * @returns
3915
4104
  */
3916
- matchLoginHint(idTokenClaims, loginHint) {
3917
- if (idTokenClaims?.login_hint === loginHint) {
4105
+ matchLoginHintFromTokenClaims(tokenClaims, loginHint) {
4106
+ if (tokenClaims.login_hint === loginHint) {
3918
4107
  return true;
3919
4108
  }
3920
- if (idTokenClaims.preferred_username === loginHint) {
4109
+ if (tokenClaims.preferred_username === loginHint) {
3921
4110
  return true;
3922
4111
  }
3923
- if (idTokenClaims?.upn === loginHint) {
4112
+ if (tokenClaims.upn === loginHint) {
3924
4113
  return true;
3925
4114
  }
3926
4115
  return false;
3927
4116
  }
3928
4117
  /**
3929
4118
  * Helper to match sid
3930
- * @param idTokenClaims
4119
+ * @param entity
3931
4120
  * @param sid
3932
4121
  * @returns true if the sid claim is present and matches the filter
3933
4122
  */
3934
4123
  matchSid(idTokenClaims, sid) {
3935
- return !!(idTokenClaims?.sid && idTokenClaims.sid === sid);
4124
+ return idTokenClaims.sid === sid;
3936
4125
  }
3937
4126
  matchAuthorityType(entity, authorityType) {
3938
4127
  return !!(entity.authorityType &&
@@ -4009,6 +4198,9 @@ class DefaultStorageClass extends CacheManager {
4009
4198
  getAccount() {
4010
4199
  throw createClientAuthError(methodNotImplemented);
4011
4200
  }
4201
+ getCachedAccountEntity() {
4202
+ throw createClientAuthError(methodNotImplemented);
4203
+ }
4012
4204
  setIdTokenCredential() {
4013
4205
  throw createClientAuthError(methodNotImplemented);
4014
4206
  }
@@ -4075,14 +4267,15 @@ class DefaultStorageClass extends CacheManager {
4075
4267
  updateCredentialCacheKey() {
4076
4268
  throw createClientAuthError(methodNotImplemented);
4077
4269
  }
4270
+ removeOutdatedAccount() {
4271
+ throw createClientAuthError(methodNotImplemented);
4272
+ }
4078
4273
  }
4079
4274
 
4080
4275
  /*
4081
4276
  * Copyright (c) Microsoft Corporation. All rights reserved.
4082
4277
  * Licensed under the MIT License.
4083
4278
  */
4084
- // Token renewal offset default in seconds
4085
- const DEFAULT_TOKEN_RENEWAL_OFFSET_SEC = 300;
4086
4279
  const DEFAULT_SYSTEM_OPTIONS = {
4087
4280
  tokenRenewalOffsetSeconds: DEFAULT_TOKEN_RENEWAL_OFFSET_SEC,
4088
4281
  preventCorsPreflight: false,
@@ -4330,6 +4523,119 @@ const CcsCredentialType = {
4330
4523
  UPN: "UPN",
4331
4524
  };
4332
4525
 
4526
+ /*
4527
+ * Copyright (c) Microsoft Corporation. All rights reserved.
4528
+ * Licensed under the MIT License.
4529
+ */
4530
+ const CLIENT_ID = "client_id";
4531
+ const REDIRECT_URI = "redirect_uri";
4532
+ const RESPONSE_TYPE = "response_type";
4533
+ const RESPONSE_MODE = "response_mode";
4534
+ const GRANT_TYPE = "grant_type";
4535
+ const CLAIMS = "claims";
4536
+ const SCOPE = "scope";
4537
+ const ERROR = "error";
4538
+ const ERROR_DESCRIPTION = "error_description";
4539
+ const ACCESS_TOKEN = "access_token";
4540
+ const ID_TOKEN = "id_token";
4541
+ const REFRESH_TOKEN = "refresh_token";
4542
+ const EXPIRES_IN = "expires_in";
4543
+ const REFRESH_TOKEN_EXPIRES_IN = "refresh_token_expires_in";
4544
+ const STATE = "state";
4545
+ const NONCE = "nonce";
4546
+ const PROMPT = "prompt";
4547
+ const SESSION_STATE = "session_state";
4548
+ const CLIENT_INFO = "client_info";
4549
+ const CODE = "code";
4550
+ const CODE_CHALLENGE = "code_challenge";
4551
+ const CODE_CHALLENGE_METHOD = "code_challenge_method";
4552
+ const CODE_VERIFIER = "code_verifier";
4553
+ const CLIENT_REQUEST_ID = "client-request-id";
4554
+ const X_CLIENT_SKU = "x-client-SKU";
4555
+ const X_CLIENT_VER = "x-client-VER";
4556
+ const X_CLIENT_OS = "x-client-OS";
4557
+ const X_CLIENT_CPU = "x-client-CPU";
4558
+ const X_CLIENT_CURR_TELEM = "x-client-current-telemetry";
4559
+ const X_CLIENT_LAST_TELEM = "x-client-last-telemetry";
4560
+ const X_MS_LIB_CAPABILITY = "x-ms-lib-capability";
4561
+ const X_APP_NAME = "x-app-name";
4562
+ const X_APP_VER = "x-app-ver";
4563
+ const POST_LOGOUT_URI = "post_logout_redirect_uri";
4564
+ const ID_TOKEN_HINT = "id_token_hint";
4565
+ const DEVICE_CODE = "device_code";
4566
+ const CLIENT_SECRET = "client_secret";
4567
+ const CLIENT_ASSERTION = "client_assertion";
4568
+ const CLIENT_ASSERTION_TYPE = "client_assertion_type";
4569
+ const TOKEN_TYPE = "token_type";
4570
+ const REQ_CNF = "req_cnf";
4571
+ const OBO_ASSERTION = "assertion";
4572
+ const REQUESTED_TOKEN_USE = "requested_token_use";
4573
+ const ON_BEHALF_OF = "on_behalf_of";
4574
+ const FOCI = "foci";
4575
+ const CCS_HEADER = "X-AnchorMailbox";
4576
+ const RETURN_SPA_CODE = "return_spa_code";
4577
+ const NATIVE_BROKER = "nativebroker";
4578
+ const LOGOUT_HINT = "logout_hint";
4579
+ const SID = "sid";
4580
+ const LOGIN_HINT = "login_hint";
4581
+ const DOMAIN_HINT = "domain_hint";
4582
+
4583
+ var AADServerParamKeys = /*#__PURE__*/Object.freeze({
4584
+ __proto__: null,
4585
+ ACCESS_TOKEN: ACCESS_TOKEN,
4586
+ CCS_HEADER: CCS_HEADER,
4587
+ CLAIMS: CLAIMS,
4588
+ CLIENT_ASSERTION: CLIENT_ASSERTION,
4589
+ CLIENT_ASSERTION_TYPE: CLIENT_ASSERTION_TYPE,
4590
+ CLIENT_ID: CLIENT_ID,
4591
+ CLIENT_INFO: CLIENT_INFO,
4592
+ CLIENT_REQUEST_ID: CLIENT_REQUEST_ID,
4593
+ CLIENT_SECRET: CLIENT_SECRET,
4594
+ CODE: CODE,
4595
+ CODE_CHALLENGE: CODE_CHALLENGE,
4596
+ CODE_CHALLENGE_METHOD: CODE_CHALLENGE_METHOD,
4597
+ CODE_VERIFIER: CODE_VERIFIER,
4598
+ DEVICE_CODE: DEVICE_CODE,
4599
+ DOMAIN_HINT: DOMAIN_HINT,
4600
+ ERROR: ERROR,
4601
+ ERROR_DESCRIPTION: ERROR_DESCRIPTION,
4602
+ EXPIRES_IN: EXPIRES_IN,
4603
+ FOCI: FOCI,
4604
+ GRANT_TYPE: GRANT_TYPE,
4605
+ ID_TOKEN: ID_TOKEN,
4606
+ ID_TOKEN_HINT: ID_TOKEN_HINT,
4607
+ LOGIN_HINT: LOGIN_HINT,
4608
+ LOGOUT_HINT: LOGOUT_HINT,
4609
+ NATIVE_BROKER: NATIVE_BROKER,
4610
+ NONCE: NONCE,
4611
+ OBO_ASSERTION: OBO_ASSERTION,
4612
+ ON_BEHALF_OF: ON_BEHALF_OF,
4613
+ POST_LOGOUT_URI: POST_LOGOUT_URI,
4614
+ PROMPT: PROMPT,
4615
+ REDIRECT_URI: REDIRECT_URI,
4616
+ REFRESH_TOKEN: REFRESH_TOKEN,
4617
+ REFRESH_TOKEN_EXPIRES_IN: REFRESH_TOKEN_EXPIRES_IN,
4618
+ REQUESTED_TOKEN_USE: REQUESTED_TOKEN_USE,
4619
+ REQ_CNF: REQ_CNF,
4620
+ RESPONSE_MODE: RESPONSE_MODE,
4621
+ RESPONSE_TYPE: RESPONSE_TYPE,
4622
+ RETURN_SPA_CODE: RETURN_SPA_CODE,
4623
+ SCOPE: SCOPE,
4624
+ SESSION_STATE: SESSION_STATE,
4625
+ SID: SID,
4626
+ STATE: STATE,
4627
+ TOKEN_TYPE: TOKEN_TYPE,
4628
+ X_APP_NAME: X_APP_NAME,
4629
+ X_APP_VER: X_APP_VER,
4630
+ X_CLIENT_CPU: X_CLIENT_CPU,
4631
+ X_CLIENT_CURR_TELEM: X_CLIENT_CURR_TELEM,
4632
+ X_CLIENT_LAST_TELEM: X_CLIENT_LAST_TELEM,
4633
+ X_CLIENT_OS: X_CLIENT_OS,
4634
+ X_CLIENT_SKU: X_CLIENT_SKU,
4635
+ X_CLIENT_VER: X_CLIENT_VER,
4636
+ X_MS_LIB_CAPABILITY: X_MS_LIB_CAPABILITY
4637
+ });
4638
+
4333
4639
  /*
4334
4640
  * Copyright (c) Microsoft Corporation. All rights reserved.
4335
4641
  * Licensed under the MIT License.
@@ -4425,26 +4731,26 @@ class RequestParameterBuilder {
4425
4731
  * add response_type = code
4426
4732
  */
4427
4733
  addResponseTypeCode() {
4428
- this.parameters.set(AADServerParamKeys.RESPONSE_TYPE, encodeURIComponent(Constants.CODE_RESPONSE_TYPE));
4734
+ this.parameters.set(RESPONSE_TYPE, encodeURIComponent(Constants.CODE_RESPONSE_TYPE));
4429
4735
  }
4430
4736
  /**
4431
4737
  * add response_type = token id_token
4432
4738
  */
4433
4739
  addResponseTypeForTokenAndIdToken() {
4434
- this.parameters.set(AADServerParamKeys.RESPONSE_TYPE, encodeURIComponent(`${Constants.TOKEN_RESPONSE_TYPE} ${Constants.ID_TOKEN_RESPONSE_TYPE}`));
4740
+ this.parameters.set(RESPONSE_TYPE, encodeURIComponent(`${Constants.TOKEN_RESPONSE_TYPE} ${Constants.ID_TOKEN_RESPONSE_TYPE}`));
4435
4741
  }
4436
4742
  /**
4437
4743
  * add response_mode. defaults to query.
4438
4744
  * @param responseMode
4439
4745
  */
4440
4746
  addResponseMode(responseMode) {
4441
- this.parameters.set(AADServerParamKeys.RESPONSE_MODE, encodeURIComponent(responseMode ? responseMode : ResponseMode.QUERY));
4747
+ this.parameters.set(RESPONSE_MODE, encodeURIComponent(responseMode ? responseMode : ResponseMode.QUERY));
4442
4748
  }
4443
4749
  /**
4444
4750
  * Add flag to indicate STS should attempt to use WAM if available
4445
4751
  */
4446
4752
  addNativeBroker() {
4447
- this.parameters.set(AADServerParamKeys.NATIVE_BROKER, encodeURIComponent("1"));
4753
+ this.parameters.set(NATIVE_BROKER, encodeURIComponent("1"));
4448
4754
  }
4449
4755
  /**
4450
4756
  * add scopes. set addOidcScopes to false to prevent default scopes in non-user scenarios
@@ -4462,14 +4768,14 @@ class RequestParameterBuilder {
4462
4768
  ? [...(scopes || []), ...defaultScopes]
4463
4769
  : scopes || [];
4464
4770
  const scopeSet = new ScopeSet(requestScopes);
4465
- this.parameters.set(AADServerParamKeys.SCOPE, encodeURIComponent(scopeSet.printScopes()));
4771
+ this.parameters.set(SCOPE, encodeURIComponent(scopeSet.printScopes()));
4466
4772
  }
4467
4773
  /**
4468
4774
  * add clientId
4469
4775
  * @param clientId
4470
4776
  */
4471
4777
  addClientId(clientId) {
4472
- this.parameters.set(AADServerParamKeys.CLIENT_ID, encodeURIComponent(clientId));
4778
+ this.parameters.set(CLIENT_ID, encodeURIComponent(clientId));
4473
4779
  }
4474
4780
  /**
4475
4781
  * add redirect_uri
@@ -4477,7 +4783,7 @@ class RequestParameterBuilder {
4477
4783
  */
4478
4784
  addRedirectUri(redirectUri) {
4479
4785
  RequestValidator.validateRedirectUri(redirectUri);
4480
- this.parameters.set(AADServerParamKeys.REDIRECT_URI, encodeURIComponent(redirectUri));
4786
+ this.parameters.set(REDIRECT_URI, encodeURIComponent(redirectUri));
4481
4787
  }
4482
4788
  /**
4483
4789
  * add post logout redirectUri
@@ -4485,28 +4791,28 @@ class RequestParameterBuilder {
4485
4791
  */
4486
4792
  addPostLogoutRedirectUri(redirectUri) {
4487
4793
  RequestValidator.validateRedirectUri(redirectUri);
4488
- this.parameters.set(AADServerParamKeys.POST_LOGOUT_URI, encodeURIComponent(redirectUri));
4794
+ this.parameters.set(POST_LOGOUT_URI, encodeURIComponent(redirectUri));
4489
4795
  }
4490
4796
  /**
4491
4797
  * add id_token_hint to logout request
4492
4798
  * @param idTokenHint
4493
4799
  */
4494
4800
  addIdTokenHint(idTokenHint) {
4495
- this.parameters.set(AADServerParamKeys.ID_TOKEN_HINT, encodeURIComponent(idTokenHint));
4801
+ this.parameters.set(ID_TOKEN_HINT, encodeURIComponent(idTokenHint));
4496
4802
  }
4497
4803
  /**
4498
4804
  * add domain_hint
4499
4805
  * @param domainHint
4500
4806
  */
4501
4807
  addDomainHint(domainHint) {
4502
- this.parameters.set(SSOTypes.DOMAIN_HINT, encodeURIComponent(domainHint));
4808
+ this.parameters.set(DOMAIN_HINT, encodeURIComponent(domainHint));
4503
4809
  }
4504
4810
  /**
4505
4811
  * add login_hint
4506
4812
  * @param loginHint
4507
4813
  */
4508
4814
  addLoginHint(loginHint) {
4509
- this.parameters.set(SSOTypes.LOGIN_HINT, encodeURIComponent(loginHint));
4815
+ this.parameters.set(LOGIN_HINT, encodeURIComponent(loginHint));
4510
4816
  }
4511
4817
  /**
4512
4818
  * Adds the CCS (Cache Credential Service) query parameter for login_hint
@@ -4527,7 +4833,7 @@ class RequestParameterBuilder {
4527
4833
  * @param sid
4528
4834
  */
4529
4835
  addSid(sid) {
4530
- this.parameters.set(SSOTypes.SID, encodeURIComponent(sid));
4836
+ this.parameters.set(SID, encodeURIComponent(sid));
4531
4837
  }
4532
4838
  /**
4533
4839
  * add claims
@@ -4536,14 +4842,14 @@ class RequestParameterBuilder {
4536
4842
  addClaims(claims, clientCapabilities) {
4537
4843
  const mergedClaims = this.addClientCapabilitiesToClaims(claims, clientCapabilities);
4538
4844
  RequestValidator.validateClaims(mergedClaims);
4539
- this.parameters.set(AADServerParamKeys.CLAIMS, encodeURIComponent(mergedClaims));
4845
+ this.parameters.set(CLAIMS, encodeURIComponent(mergedClaims));
4540
4846
  }
4541
4847
  /**
4542
4848
  * add correlationId
4543
4849
  * @param correlationId
4544
4850
  */
4545
4851
  addCorrelationId(correlationId) {
4546
- this.parameters.set(AADServerParamKeys.CLIENT_REQUEST_ID, encodeURIComponent(correlationId));
4852
+ this.parameters.set(CLIENT_REQUEST_ID, encodeURIComponent(correlationId));
4547
4853
  }
4548
4854
  /**
4549
4855
  * add library info query params
@@ -4551,13 +4857,13 @@ class RequestParameterBuilder {
4551
4857
  */
4552
4858
  addLibraryInfo(libraryInfo) {
4553
4859
  // Telemetry Info
4554
- this.parameters.set(AADServerParamKeys.X_CLIENT_SKU, libraryInfo.sku);
4555
- this.parameters.set(AADServerParamKeys.X_CLIENT_VER, libraryInfo.version);
4860
+ this.parameters.set(X_CLIENT_SKU, libraryInfo.sku);
4861
+ this.parameters.set(X_CLIENT_VER, libraryInfo.version);
4556
4862
  if (libraryInfo.os) {
4557
- this.parameters.set(AADServerParamKeys.X_CLIENT_OS, libraryInfo.os);
4863
+ this.parameters.set(X_CLIENT_OS, libraryInfo.os);
4558
4864
  }
4559
4865
  if (libraryInfo.cpu) {
4560
- this.parameters.set(AADServerParamKeys.X_CLIENT_CPU, libraryInfo.cpu);
4866
+ this.parameters.set(X_CLIENT_CPU, libraryInfo.cpu);
4561
4867
  }
4562
4868
  }
4563
4869
  /**
@@ -4566,10 +4872,10 @@ class RequestParameterBuilder {
4566
4872
  */
4567
4873
  addApplicationTelemetry(appTelemetry) {
4568
4874
  if (appTelemetry?.appName) {
4569
- this.parameters.set(AADServerParamKeys.X_APP_NAME, appTelemetry.appName);
4875
+ this.parameters.set(X_APP_NAME, appTelemetry.appName);
4570
4876
  }
4571
4877
  if (appTelemetry?.appVersion) {
4572
- this.parameters.set(AADServerParamKeys.X_APP_VER, appTelemetry.appVersion);
4878
+ this.parameters.set(X_APP_VER, appTelemetry.appVersion);
4573
4879
  }
4574
4880
  }
4575
4881
  /**
@@ -4578,7 +4884,7 @@ class RequestParameterBuilder {
4578
4884
  */
4579
4885
  addPrompt(prompt) {
4580
4886
  RequestValidator.validatePrompt(prompt);
4581
- this.parameters.set(`${AADServerParamKeys.PROMPT}`, encodeURIComponent(prompt));
4887
+ this.parameters.set(`${PROMPT}`, encodeURIComponent(prompt));
4582
4888
  }
4583
4889
  /**
4584
4890
  * add state
@@ -4586,7 +4892,7 @@ class RequestParameterBuilder {
4586
4892
  */
4587
4893
  addState(state) {
4588
4894
  if (state) {
4589
- this.parameters.set(AADServerParamKeys.STATE, encodeURIComponent(state));
4895
+ this.parameters.set(STATE, encodeURIComponent(state));
4590
4896
  }
4591
4897
  }
4592
4898
  /**
@@ -4594,7 +4900,7 @@ class RequestParameterBuilder {
4594
4900
  * @param nonce
4595
4901
  */
4596
4902
  addNonce(nonce) {
4597
- this.parameters.set(AADServerParamKeys.NONCE, encodeURIComponent(nonce));
4903
+ this.parameters.set(NONCE, encodeURIComponent(nonce));
4598
4904
  }
4599
4905
  /**
4600
4906
  * add code_challenge and code_challenge_method
@@ -4605,8 +4911,8 @@ class RequestParameterBuilder {
4605
4911
  addCodeChallengeParams(codeChallenge, codeChallengeMethod) {
4606
4912
  RequestValidator.validateCodeChallengeParams(codeChallenge, codeChallengeMethod);
4607
4913
  if (codeChallenge && codeChallengeMethod) {
4608
- this.parameters.set(AADServerParamKeys.CODE_CHALLENGE, encodeURIComponent(codeChallenge));
4609
- this.parameters.set(AADServerParamKeys.CODE_CHALLENGE_METHOD, encodeURIComponent(codeChallengeMethod));
4914
+ this.parameters.set(CODE_CHALLENGE, encodeURIComponent(codeChallenge));
4915
+ this.parameters.set(CODE_CHALLENGE_METHOD, encodeURIComponent(codeChallengeMethod));
4610
4916
  }
4611
4917
  else {
4612
4918
  throw createClientConfigurationError(pkceParamsMissing);
@@ -4617,35 +4923,35 @@ class RequestParameterBuilder {
4617
4923
  * @param code
4618
4924
  */
4619
4925
  addAuthorizationCode(code) {
4620
- this.parameters.set(AADServerParamKeys.CODE, encodeURIComponent(code));
4926
+ this.parameters.set(CODE, encodeURIComponent(code));
4621
4927
  }
4622
4928
  /**
4623
4929
  * add the `authorization_code` passed by the user to exchange for a token
4624
4930
  * @param code
4625
4931
  */
4626
4932
  addDeviceCode(code) {
4627
- this.parameters.set(AADServerParamKeys.DEVICE_CODE, encodeURIComponent(code));
4933
+ this.parameters.set(DEVICE_CODE, encodeURIComponent(code));
4628
4934
  }
4629
4935
  /**
4630
4936
  * add the `refreshToken` passed by the user
4631
4937
  * @param refreshToken
4632
4938
  */
4633
4939
  addRefreshToken(refreshToken) {
4634
- this.parameters.set(AADServerParamKeys.REFRESH_TOKEN, encodeURIComponent(refreshToken));
4940
+ this.parameters.set(REFRESH_TOKEN, encodeURIComponent(refreshToken));
4635
4941
  }
4636
4942
  /**
4637
4943
  * add the `code_verifier` passed by the user to exchange for a token
4638
4944
  * @param codeVerifier
4639
4945
  */
4640
4946
  addCodeVerifier(codeVerifier) {
4641
- this.parameters.set(AADServerParamKeys.CODE_VERIFIER, encodeURIComponent(codeVerifier));
4947
+ this.parameters.set(CODE_VERIFIER, encodeURIComponent(codeVerifier));
4642
4948
  }
4643
4949
  /**
4644
4950
  * add client_secret
4645
4951
  * @param clientSecret
4646
4952
  */
4647
4953
  addClientSecret(clientSecret) {
4648
- this.parameters.set(AADServerParamKeys.CLIENT_SECRET, encodeURIComponent(clientSecret));
4954
+ this.parameters.set(CLIENT_SECRET, encodeURIComponent(clientSecret));
4649
4955
  }
4650
4956
  /**
4651
4957
  * add clientAssertion for confidential client flows
@@ -4653,7 +4959,7 @@ class RequestParameterBuilder {
4653
4959
  */
4654
4960
  addClientAssertion(clientAssertion) {
4655
4961
  if (clientAssertion) {
4656
- this.parameters.set(AADServerParamKeys.CLIENT_ASSERTION, encodeURIComponent(clientAssertion));
4962
+ this.parameters.set(CLIENT_ASSERTION, encodeURIComponent(clientAssertion));
4657
4963
  }
4658
4964
  }
4659
4965
  /**
@@ -4662,7 +4968,7 @@ class RequestParameterBuilder {
4662
4968
  */
4663
4969
  addClientAssertionType(clientAssertionType) {
4664
4970
  if (clientAssertionType) {
4665
- this.parameters.set(AADServerParamKeys.CLIENT_ASSERTION_TYPE, encodeURIComponent(clientAssertionType));
4971
+ this.parameters.set(CLIENT_ASSERTION_TYPE, encodeURIComponent(clientAssertionType));
4666
4972
  }
4667
4973
  }
4668
4974
  /**
@@ -4670,28 +4976,28 @@ class RequestParameterBuilder {
4670
4976
  * @param clientAssertion
4671
4977
  */
4672
4978
  addOboAssertion(oboAssertion) {
4673
- this.parameters.set(AADServerParamKeys.OBO_ASSERTION, encodeURIComponent(oboAssertion));
4979
+ this.parameters.set(OBO_ASSERTION, encodeURIComponent(oboAssertion));
4674
4980
  }
4675
4981
  /**
4676
4982
  * add grant type
4677
4983
  * @param grantType
4678
4984
  */
4679
4985
  addRequestTokenUse(tokenUse) {
4680
- this.parameters.set(AADServerParamKeys.REQUESTED_TOKEN_USE, encodeURIComponent(tokenUse));
4986
+ this.parameters.set(REQUESTED_TOKEN_USE, encodeURIComponent(tokenUse));
4681
4987
  }
4682
4988
  /**
4683
4989
  * add grant type
4684
4990
  * @param grantType
4685
4991
  */
4686
4992
  addGrantType(grantType) {
4687
- this.parameters.set(AADServerParamKeys.GRANT_TYPE, encodeURIComponent(grantType));
4993
+ this.parameters.set(GRANT_TYPE, encodeURIComponent(grantType));
4688
4994
  }
4689
4995
  /**
4690
4996
  * add client info
4691
4997
  *
4692
4998
  */
4693
4999
  addClientInfo() {
4694
- this.parameters.set(CLIENT_INFO, "1");
5000
+ this.parameters.set(CLIENT_INFO$1, "1");
4695
5001
  }
4696
5002
  /**
4697
5003
  * add extraQueryParams
@@ -4749,8 +5055,8 @@ class RequestParameterBuilder {
4749
5055
  */
4750
5056
  addPopToken(cnfString) {
4751
5057
  if (cnfString) {
4752
- this.parameters.set(AADServerParamKeys.TOKEN_TYPE, AuthenticationScheme.POP);
4753
- this.parameters.set(AADServerParamKeys.REQ_CNF, encodeURIComponent(cnfString));
5058
+ this.parameters.set(TOKEN_TYPE, AuthenticationScheme.POP);
5059
+ this.parameters.set(REQ_CNF, encodeURIComponent(cnfString));
4754
5060
  }
4755
5061
  }
4756
5062
  /**
@@ -4758,8 +5064,8 @@ class RequestParameterBuilder {
4758
5064
  */
4759
5065
  addSshJwk(sshJwkString) {
4760
5066
  if (sshJwkString) {
4761
- this.parameters.set(AADServerParamKeys.TOKEN_TYPE, AuthenticationScheme.SSH);
4762
- this.parameters.set(AADServerParamKeys.REQ_CNF, encodeURIComponent(sshJwkString));
5067
+ this.parameters.set(TOKEN_TYPE, AuthenticationScheme.SSH);
5068
+ this.parameters.set(REQ_CNF, encodeURIComponent(sshJwkString));
4763
5069
  }
4764
5070
  }
4765
5071
  /**
@@ -4767,20 +5073,20 @@ class RequestParameterBuilder {
4767
5073
  * @param serverTelemetryManager
4768
5074
  */
4769
5075
  addServerTelemetry(serverTelemetryManager) {
4770
- this.parameters.set(AADServerParamKeys.X_CLIENT_CURR_TELEM, serverTelemetryManager.generateCurrentRequestHeaderValue());
4771
- this.parameters.set(AADServerParamKeys.X_CLIENT_LAST_TELEM, serverTelemetryManager.generateLastRequestHeaderValue());
5076
+ this.parameters.set(X_CLIENT_CURR_TELEM, serverTelemetryManager.generateCurrentRequestHeaderValue());
5077
+ this.parameters.set(X_CLIENT_LAST_TELEM, serverTelemetryManager.generateLastRequestHeaderValue());
4772
5078
  }
4773
5079
  /**
4774
5080
  * Adds parameter that indicates to the server that throttling is supported
4775
5081
  */
4776
5082
  addThrottling() {
4777
- this.parameters.set(AADServerParamKeys.X_MS_LIB_CAPABILITY, ThrottlingConstants.X_MS_LIB_CAPABILITY_VALUE);
5083
+ this.parameters.set(X_MS_LIB_CAPABILITY, ThrottlingConstants.X_MS_LIB_CAPABILITY_VALUE);
4778
5084
  }
4779
5085
  /**
4780
5086
  * Adds logout_hint parameter for "silent" logout which prevent server account picker
4781
5087
  */
4782
5088
  addLogoutHint(logoutHint) {
4783
- this.parameters.set(AADServerParamKeys.LOGOUT_HINT, encodeURIComponent(logoutHint));
5089
+ this.parameters.set(LOGOUT_HINT, encodeURIComponent(logoutHint));
4784
5090
  }
4785
5091
  /**
4786
5092
  * Utility to create a URL from the params map
@@ -5358,7 +5664,7 @@ RegionDiscovery.IMDS_OPTIONS = {
5358
5664
  * @internal
5359
5665
  */
5360
5666
  class Authority {
5361
- constructor(authority, networkInterface, cacheManager, authorityOptions, logger, performanceClient, correlationId) {
5667
+ constructor(authority, networkInterface, cacheManager, authorityOptions, logger, performanceClient, correlationId, managedIdentity) {
5362
5668
  this.canonicalAuthority = authority;
5363
5669
  this._canonicalAuthority.validateAsUri();
5364
5670
  this.networkInterface = networkInterface;
@@ -5372,6 +5678,7 @@ class Authority {
5372
5678
  this.logger = logger;
5373
5679
  this.performanceClient = performanceClient;
5374
5680
  this.correlationId = correlationId;
5681
+ this.managedIdentity = managedIdentity || false;
5375
5682
  this.regionDiscovery = new RegionDiscovery(networkInterface, this.logger, this.performanceClient, this.correlationId);
5376
5683
  }
5377
5684
  /**
@@ -5577,7 +5884,7 @@ class Authority {
5577
5884
  return `${this.canonicalAuthority}v2.0/.well-known/openid-configuration`;
5578
5885
  }
5579
5886
  /**
5580
- * Boolean that returns whethr or not tenant discovery has been completed.
5887
+ * Boolean that returns whether or not tenant discovery has been completed.
5581
5888
  */
5582
5889
  discoveryComplete() {
5583
5890
  return !!this.metadata;
@@ -5971,8 +6278,9 @@ class Authority {
5971
6278
  */
5972
6279
  isInKnownAuthorities() {
5973
6280
  const matches = this.authorityOptions.knownAuthorities.filter((authority) => {
5974
- return (UrlString.getDomainFromUrl(authority).toLowerCase() ===
5975
- this.hostnameAndPort);
6281
+ return (authority &&
6282
+ UrlString.getDomainFromUrl(authority).toLowerCase() ===
6283
+ this.hostnameAndPort);
5976
6284
  });
5977
6285
  return matches.length > 0;
5978
6286
  }
@@ -6009,7 +6317,10 @@ class Authority {
6009
6317
  * helper function to generate environment from authority object
6010
6318
  */
6011
6319
  getPreferredCache() {
6012
- if (this.discoveryComplete()) {
6320
+ if (this.managedIdentity) {
6321
+ return Constants.DEFAULT_AUTHORITY_HOST;
6322
+ }
6323
+ else if (this.discoveryComplete()) {
6013
6324
  return this.metadata.preferred_cache;
6014
6325
  }
6015
6326
  else {
@@ -6112,6 +6423,28 @@ Authority.reservedTenantDomains = new Set([
6112
6423
  AADAuthorityConstants.CONSUMERS,
6113
6424
  AADAuthorityConstants.ORGANIZATIONS,
6114
6425
  ]);
6426
+ /**
6427
+ * Extract tenantId from authority
6428
+ */
6429
+ function getTenantFromAuthorityString(authority) {
6430
+ const authorityUrl = new UrlString(authority);
6431
+ const authorityUrlComponents = authorityUrl.getUrlComponents();
6432
+ /**
6433
+ * For credential matching purposes, tenantId is the last path segment of the authority URL:
6434
+ * AAD Authority - domain/tenantId -> Credentials are cached with realm = tenantId
6435
+ * B2C Authority - domain/{tenantId}?/.../policy -> Credentials are cached with realm = policy
6436
+ * tenantId is downcased because B2C policies can have mixed case but tfp claim is downcased
6437
+ */
6438
+ const tenantId = authorityUrlComponents.PathSegments.slice(-1)[0].toLowerCase();
6439
+ switch (tenantId) {
6440
+ case AADAuthorityConstants.COMMON:
6441
+ case AADAuthorityConstants.ORGANIZATIONS:
6442
+ case AADAuthorityConstants.CONSUMERS:
6443
+ return undefined;
6444
+ default:
6445
+ return tenantId;
6446
+ }
6447
+ }
6115
6448
  function formatAuthorityUri(authorityUri) {
6116
6449
  return authorityUri.endsWith(Constants.FORWARD_SLASH)
6117
6450
  ? authorityUri
@@ -6297,10 +6630,12 @@ const refreshTokenExpired = "refresh_token_expired";
6297
6630
  // Codes potentially returned by server
6298
6631
  const interactionRequired = "interaction_required";
6299
6632
  const consentRequired = "consent_required";
6300
- const loginRequired = "login_required";
6633
+ const loginRequired = "login_required";
6634
+ const badToken = "bad_token";
6301
6635
 
6302
6636
  var InteractionRequiredAuthErrorCodes = /*#__PURE__*/Object.freeze({
6303
6637
  __proto__: null,
6638
+ badToken: badToken,
6304
6639
  consentRequired: consentRequired,
6305
6640
  interactionRequired: interactionRequired,
6306
6641
  loginRequired: loginRequired,
@@ -6320,6 +6655,7 @@ const InteractionRequiredServerErrorMessage = [
6320
6655
  interactionRequired,
6321
6656
  consentRequired,
6322
6657
  loginRequired,
6658
+ badToken,
6323
6659
  ];
6324
6660
  const InteractionRequiredAuthSubErrorMessage = [
6325
6661
  "message_only",
@@ -6327,11 +6663,13 @@ const InteractionRequiredAuthSubErrorMessage = [
6327
6663
  "basic_action",
6328
6664
  "user_password_expired",
6329
6665
  "consent_required",
6666
+ "bad_token",
6330
6667
  ];
6331
6668
  const InteractionRequiredAuthErrorMessages = {
6332
6669
  [noTokensFound]: "No refresh token found in the cache. Please sign-in.",
6333
- [refreshTokenExpired]: "Refresh token has expired.",
6334
6670
  [nativeAccountUnavailable]: "The requested account is not available in the native broker. It may have been deleted or logged out. Please sign-in again using an interactive API.",
6671
+ [refreshTokenExpired]: "Refresh token has expired.",
6672
+ [badToken]: "Identity provider returned bad_token due to an expired or invalid refresh token. Please invoke an interactive API to resolve.",
6335
6673
  };
6336
6674
  /**
6337
6675
  * Interaction required errors defined by the SDK
@@ -6346,6 +6684,10 @@ const InteractionRequiredAuthErrorMessage = {
6346
6684
  code: nativeAccountUnavailable,
6347
6685
  desc: InteractionRequiredAuthErrorMessages[nativeAccountUnavailable],
6348
6686
  },
6687
+ bad_token: {
6688
+ code: badToken,
6689
+ desc: InteractionRequiredAuthErrorMessages[badToken],
6690
+ },
6349
6691
  };
6350
6692
  /**
6351
6693
  * Error thrown when user interaction is required.
@@ -6539,7 +6881,7 @@ class PopTokenGenerator {
6539
6881
  ? new UrlString(resourceRequestUri)
6540
6882
  : undefined;
6541
6883
  const resourceUrlComponents = resourceUrlString?.getUrlComponents();
6542
- return await this.cryptoUtils.signJwt({
6884
+ return this.cryptoUtils.signJwt({
6543
6885
  at: payload,
6544
6886
  ts: TimeUtils.nowSeconds(),
6545
6887
  m: resourceRequestMethod?.toUpperCase(),
@@ -6746,7 +7088,7 @@ class ResponseHandler {
6746
7088
  * @param serverTokenResponse
6747
7089
  * @param authority
6748
7090
  */
6749
- async handleServerTokenResponse(serverTokenResponse, authority, reqTimestamp, request, authCodePayload, userAssertionHash, handlingRefreshTokenResponse, forceCacheRefreshTokenResponse, serverRequestId, rtExpiresOn) {
7091
+ async handleServerTokenResponse(serverTokenResponse, authority, reqTimestamp, request, authCodePayload, userAssertionHash, handlingRefreshTokenResponse, forceCacheRefreshTokenResponse, serverRequestId) {
6750
7092
  this.performanceClient?.addQueueMeasurement(PerformanceEvents.HandleServerTokenResponse, serverTokenResponse.correlation_id);
6751
7093
  // create an idToken object (not entity)
6752
7094
  let idTokenClaims;
@@ -6777,7 +7119,7 @@ class ResponseHandler {
6777
7119
  // Add keyId from request to serverTokenResponse if defined
6778
7120
  serverTokenResponse.key_id =
6779
7121
  serverTokenResponse.key_id || request.sshKid || undefined;
6780
- const cacheRecord = this.generateCacheRecord(serverTokenResponse, authority, reqTimestamp, request, idTokenClaims, userAssertionHash, authCodePayload, rtExpiresOn);
7122
+ const cacheRecord = this.generateCacheRecord(serverTokenResponse, authority, reqTimestamp, request, idTokenClaims, userAssertionHash, authCodePayload);
6781
7123
  let cacheContext;
6782
7124
  try {
6783
7125
  if (this.persistencePlugin && this.serializableCache) {
@@ -6795,10 +7137,10 @@ class ResponseHandler {
6795
7137
  !forceCacheRefreshTokenResponse &&
6796
7138
  cacheRecord.account) {
6797
7139
  const key = cacheRecord.account.generateAccountKey();
6798
- const account = this.cacheStorage.getAccount(key);
7140
+ const account = this.cacheStorage.getAccount(key, this.logger);
6799
7141
  if (!account) {
6800
7142
  this.logger.warning("Account used to refresh tokens not in persistence, refreshed tokens will not be stored in the cache");
6801
- return ResponseHandler.generateAuthenticationResult(this.cryptoObj, authority, cacheRecord, false, request, idTokenClaims, requestStateObj, undefined, serverRequestId);
7143
+ return await ResponseHandler.generateAuthenticationResult(this.cryptoObj, authority, cacheRecord, false, request, idTokenClaims, requestStateObj, undefined, serverRequestId);
6802
7144
  }
6803
7145
  }
6804
7146
  await this.cacheStorage.saveCacheRecord(cacheRecord, request.storeInCache);
@@ -6819,23 +7161,19 @@ class ResponseHandler {
6819
7161
  * @param idTokenObj
6820
7162
  * @param authority
6821
7163
  */
6822
- generateCacheRecord(serverTokenResponse, authority, reqTimestamp, request, idTokenClaims, userAssertionHash, authCodePayload, rtExpiresOn) {
7164
+ generateCacheRecord(serverTokenResponse, authority, reqTimestamp, request, idTokenClaims, userAssertionHash, authCodePayload) {
6823
7165
  const env = authority.getPreferredCache();
6824
7166
  if (!env) {
6825
7167
  throw createClientAuthError(invalidCacheEnvironment);
6826
7168
  }
7169
+ const claimsTenantId = getTenantIdFromIdTokenClaims(idTokenClaims);
6827
7170
  // IdToken: non AAD scenarios can have empty realm
6828
7171
  let cachedIdToken;
6829
7172
  let cachedAccount;
6830
7173
  if (serverTokenResponse.id_token && !!idTokenClaims) {
6831
- cachedIdToken = createIdTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.id_token, this.clientId, idTokenClaims.tid || "");
6832
- cachedAccount = AccountEntity.createAccount({
6833
- homeAccountId: this.homeAccountIdentifier,
6834
- idTokenClaims: idTokenClaims,
6835
- clientInfo: serverTokenResponse.client_info,
6836
- cloudGraphHostName: authCodePayload?.cloud_graph_host_name,
6837
- msGraphHost: authCodePayload?.msgraph_host,
6838
- }, authority);
7174
+ cachedIdToken = createIdTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.id_token, this.clientId, claimsTenantId || "");
7175
+ cachedAccount = buildAccountToCache(this.cacheStorage, authority, this.homeAccountIdentifier, idTokenClaims, this.cryptoObj.base64Decode, serverTokenResponse.client_info, env, claimsTenantId, authCodePayload, undefined, // nativeAccountId
7176
+ this.logger);
6839
7177
  }
6840
7178
  // AccessToken
6841
7179
  let cachedAccessToken = null;
@@ -6863,11 +7201,19 @@ class ResponseHandler {
6863
7201
  ? reqTimestamp + refreshIn
6864
7202
  : undefined;
6865
7203
  // non AAD scenarios can have empty realm
6866
- cachedAccessToken = createAccessTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.access_token, this.clientId, idTokenClaims?.tid || authority.tenant, responseScopes.printScopes(), tokenExpirationSeconds, extendedTokenExpirationSeconds, this.cryptoObj.base64Decode, refreshOnSeconds, serverTokenResponse.token_type, userAssertionHash, serverTokenResponse.key_id, request.claims, request.requestedClaimsHash);
7204
+ cachedAccessToken = createAccessTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.access_token, this.clientId, claimsTenantId || authority.tenant, responseScopes.printScopes(), tokenExpirationSeconds, extendedTokenExpirationSeconds, this.cryptoObj.base64Decode, refreshOnSeconds, serverTokenResponse.token_type, userAssertionHash, serverTokenResponse.key_id, request.claims, request.requestedClaimsHash);
6867
7205
  }
6868
7206
  // refreshToken
6869
7207
  let cachedRefreshToken = null;
6870
7208
  if (serverTokenResponse.refresh_token) {
7209
+ let rtExpiresOn;
7210
+ if (serverTokenResponse.refresh_token_expires_in) {
7211
+ const rtExpiresIn = typeof serverTokenResponse.refresh_token_expires_in ===
7212
+ "string"
7213
+ ? parseInt(serverTokenResponse.refresh_token_expires_in, 10)
7214
+ : serverTokenResponse.refresh_token_expires_in;
7215
+ rtExpiresOn = reqTimestamp + rtExpiresIn;
7216
+ }
6871
7217
  cachedRefreshToken = createRefreshTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.refresh_token, this.clientId, serverTokenResponse.foci, userAssertionHash, rtExpiresOn);
6872
7218
  }
6873
7219
  // appMetadata
@@ -6927,10 +7273,8 @@ class ResponseHandler {
6927
7273
  serverTokenResponse?.spa_accountid;
6928
7274
  }
6929
7275
  const accountInfo = cacheRecord.account
6930
- ? {
6931
- ...cacheRecord.account.getAccountInfo(),
6932
- idTokenClaims,
6933
- }
7276
+ ? updateAccountTenantProfileData(cacheRecord.account.getAccountInfo(), undefined, // tenantProfile optional
7277
+ idTokenClaims)
6934
7278
  : null;
6935
7279
  return {
6936
7280
  authority: authority.canonicalAuthority,
@@ -6959,6 +7303,38 @@ class ResponseHandler {
6959
7303
  fromNativeBroker: false,
6960
7304
  };
6961
7305
  }
7306
+ }
7307
+ function buildAccountToCache(cacheStorage, authority, homeAccountId, idTokenClaims, base64Decode, clientInfo, environment, claimsTenantId, authCodePayload, nativeAccountId, logger) {
7308
+ logger?.verbose("setCachedAccount called");
7309
+ // Check if base account is already cached
7310
+ const accountKeys = cacheStorage.getAccountKeys();
7311
+ const baseAccountKey = accountKeys.find((accountKey) => {
7312
+ return accountKey.startsWith(homeAccountId);
7313
+ });
7314
+ let cachedAccount = null;
7315
+ if (baseAccountKey) {
7316
+ cachedAccount = cacheStorage.getAccount(baseAccountKey, logger);
7317
+ }
7318
+ const baseAccount = cachedAccount ||
7319
+ AccountEntity.createAccount({
7320
+ homeAccountId,
7321
+ idTokenClaims,
7322
+ clientInfo,
7323
+ environment,
7324
+ cloudGraphHostName: authCodePayload?.cloud_graph_host_name,
7325
+ msGraphHost: authCodePayload?.msgraph_host,
7326
+ nativeAccountId: nativeAccountId,
7327
+ }, authority, base64Decode);
7328
+ const tenantProfiles = baseAccount.tenantProfiles || [];
7329
+ if (claimsTenantId &&
7330
+ !tenantProfiles.find((tenantProfile) => {
7331
+ return tenantProfile.tenantId === claimsTenantId;
7332
+ })) {
7333
+ const newTenantProfile = buildTenantProfileFromIdTokenClaims(homeAccountId, idTokenClaims);
7334
+ tenantProfiles.push(newTenantProfile);
7335
+ }
7336
+ baseAccount.tenantProfiles = tenantProfiles;
7337
+ return baseAccount;
6962
7338
  }
6963
7339
 
6964
7340
  /*
@@ -7009,7 +7385,7 @@ class AuthorizationCodeClient extends BaseClient {
7009
7385
  const responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, this.config.serializableCache, this.config.persistencePlugin, this.performanceClient);
7010
7386
  // Validate response. This function throws a server error if an error is returned by the server.
7011
7387
  responseHandler.validateTokenResponse(response.body);
7012
- return invokeAsync(responseHandler.handleServerTokenResponse.bind(responseHandler), PerformanceEvents.HandleServerTokenResponse, this.logger, this.performanceClient, request.correlationId)(response.body, this.authority, reqTimestamp, request, authCodePayload, undefined, undefined, undefined, requestId, (TimeUtils.nowSeconds() + 24 * 60 * 60).toString());
7388
+ return invokeAsync(responseHandler.handleServerTokenResponse.bind(responseHandler), PerformanceEvents.HandleServerTokenResponse, this.logger, this.performanceClient, request.correlationId)(response.body, this.authority, reqTimestamp, request, authCodePayload, undefined, undefined, undefined, requestId);
7013
7389
  }
7014
7390
  /**
7015
7391
  * Handles the hash fragment response from public client code request. Returns a code response used by
@@ -7054,7 +7430,7 @@ class AuthorizationCodeClient extends BaseClient {
7054
7430
  let ccsCredential = undefined;
7055
7431
  if (request.clientInfo) {
7056
7432
  try {
7057
- const clientInfo = buildClientInfo(request.clientInfo, this.cryptoUtils);
7433
+ const clientInfo = buildClientInfo(request.clientInfo, this.cryptoUtils.base64Decode);
7058
7434
  ccsCredential = {
7059
7435
  credential: `${clientInfo.uid}${Separators.CLIENT_INFO_SEPARATOR}${clientInfo.utid}`,
7060
7436
  type: CcsCredentialType.HOME_ACCOUNT_ID,
@@ -7086,7 +7462,7 @@ class AuthorizationCodeClient extends BaseClient {
7086
7462
  async createTokenRequestBody(request) {
7087
7463
  this.performanceClient?.addQueueMeasurement(PerformanceEvents.AuthClientCreateTokenRequestBody, request.correlationId);
7088
7464
  const parameterBuilder = new RequestParameterBuilder();
7089
- parameterBuilder.addClientId(request.tokenBodyParameters?.[AADServerParamKeys.CLIENT_ID] ||
7465
+ parameterBuilder.addClientId(request.tokenBodyParameters?.[CLIENT_ID] ||
7090
7466
  this.config.authOptions.clientId);
7091
7467
  /*
7092
7468
  * For hybrid spa flow, there will be a code but no verifier
@@ -7150,7 +7526,7 @@ class AuthorizationCodeClient extends BaseClient {
7150
7526
  let ccsCred = undefined;
7151
7527
  if (request.clientInfo) {
7152
7528
  try {
7153
- const clientInfo = buildClientInfo(request.clientInfo, this.cryptoUtils);
7529
+ const clientInfo = buildClientInfo(request.clientInfo, this.cryptoUtils.base64Decode);
7154
7530
  ccsCred = {
7155
7531
  credential: `${clientInfo.uid}${Separators.CLIENT_INFO_SEPARATOR}${clientInfo.utid}`,
7156
7532
  type: CcsCredentialType.HOME_ACCOUNT_ID,
@@ -7187,9 +7563,9 @@ class AuthorizationCodeClient extends BaseClient {
7187
7563
  // Add hybrid spa parameters if not already provided
7188
7564
  if (request.enableSpaAuthorizationCode &&
7189
7565
  (!request.tokenBodyParameters ||
7190
- !request.tokenBodyParameters[AADServerParamKeys.RETURN_SPA_CODE])) {
7566
+ !request.tokenBodyParameters[RETURN_SPA_CODE])) {
7191
7567
  parameterBuilder.addExtraQueryParameters({
7192
- [AADServerParamKeys.RETURN_SPA_CODE]: "1",
7568
+ [RETURN_SPA_CODE]: "1",
7193
7569
  });
7194
7570
  }
7195
7571
  return parameterBuilder.createQueryString();
@@ -7201,7 +7577,7 @@ class AuthorizationCodeClient extends BaseClient {
7201
7577
  async createAuthCodeUrlQueryString(request) {
7202
7578
  this.performanceClient?.addQueueMeasurement(PerformanceEvents.AuthClientCreateQueryString, request.correlationId);
7203
7579
  const parameterBuilder = new RequestParameterBuilder();
7204
- parameterBuilder.addClientId(request.extraQueryParameters?.[AADServerParamKeys.CLIENT_ID] ||
7580
+ parameterBuilder.addClientId(request.extraQueryParameters?.[CLIENT_ID] ||
7205
7581
  this.config.authOptions.clientId);
7206
7582
  const requestScopes = [
7207
7583
  ...(request.scopes || []),
@@ -7368,6 +7744,7 @@ class AuthorizationCodeClient extends BaseClient {
7368
7744
  * Copyright (c) Microsoft Corporation. All rights reserved.
7369
7745
  * Licensed under the MIT License.
7370
7746
  */
7747
+ const DEFAULT_REFRESH_TOKEN_EXPIRATION_OFFSET_SECONDS = 300; // 5 Minutes
7371
7748
  /**
7372
7749
  * OAuth2.0 refresh token client
7373
7750
  * @internal
@@ -7384,7 +7761,7 @@ class RefreshTokenClient extends BaseClient {
7384
7761
  const requestId = response.headers?.[HeaderNames.X_MS_REQUEST_ID];
7385
7762
  const responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, this.config.serializableCache, this.config.persistencePlugin);
7386
7763
  responseHandler.validateTokenResponse(response.body);
7387
- return invokeAsync(responseHandler.handleServerTokenResponse.bind(responseHandler), PerformanceEvents.HandleServerTokenResponse, this.logger, this.performanceClient, request.correlationId)(response.body, this.authority, reqTimestamp, request, undefined, undefined, true, request.forceCache, requestId, request.expiresOn);
7764
+ return invokeAsync(responseHandler.handleServerTokenResponse.bind(responseHandler), PerformanceEvents.HandleServerTokenResponse, this.logger, this.performanceClient, request.correlationId)(response.body, this.authority, reqTimestamp, request, undefined, undefined, true, request.forceCache, requestId);
7388
7765
  }
7389
7766
  /**
7390
7767
  * Gets cached refresh token and attaches to request, then calls acquireToken API
@@ -7405,7 +7782,7 @@ class RefreshTokenClient extends BaseClient {
7405
7782
  // if the app is part of the family, retrive a Family refresh token if present and make a refreshTokenRequest
7406
7783
  if (isFOCI) {
7407
7784
  try {
7408
- return invokeAsync(this.acquireTokenWithCachedRefreshToken.bind(this), PerformanceEvents.RefreshTokenClientAcquireTokenWithCachedRefreshToken, this.logger, this.performanceClient, request.correlationId)(request, true);
7785
+ return await invokeAsync(this.acquireTokenWithCachedRefreshToken.bind(this), PerformanceEvents.RefreshTokenClientAcquireTokenWithCachedRefreshToken, this.logger, this.performanceClient, request.correlationId)(request, true);
7409
7786
  }
7410
7787
  catch (e) {
7411
7788
  const noFamilyRTInCache = e instanceof InteractionRequiredAuthError &&
@@ -7438,9 +7815,9 @@ class RefreshTokenClient extends BaseClient {
7438
7815
  if (!refreshToken) {
7439
7816
  throw createInteractionRequiredAuthError(noTokensFound);
7440
7817
  }
7441
- if (request.enableRTExpiryCheck &&
7442
- refreshToken.expiresOn &&
7443
- Number(refreshToken.expiresOn) < TimeUtils.nowSeconds() + 5 * 60) {
7818
+ if (refreshToken.expiresOn &&
7819
+ TimeUtils.isTokenExpired(refreshToken.expiresOn, request.refreshTokenExpirationOffsetSeconds ||
7820
+ DEFAULT_REFRESH_TOKEN_EXPIRATION_OFFSET_SECONDS)) {
7444
7821
  throw createInteractionRequiredAuthError(refreshTokenExpired);
7445
7822
  }
7446
7823
  // attach cached RT size to the current measurement
@@ -7452,9 +7829,20 @@ class RefreshTokenClient extends BaseClient {
7452
7829
  credential: request.account.homeAccountId,
7453
7830
  type: CcsCredentialType.HOME_ACCOUNT_ID,
7454
7831
  },
7455
- expiresOn: refreshToken.expiresOn,
7456
7832
  };
7457
- return invokeAsync(this.acquireToken.bind(this), PerformanceEvents.RefreshTokenClientAcquireToken, this.logger, this.performanceClient, request.correlationId)(refreshTokenRequest);
7833
+ try {
7834
+ return await invokeAsync(this.acquireToken.bind(this), PerformanceEvents.RefreshTokenClientAcquireToken, this.logger, this.performanceClient, request.correlationId)(refreshTokenRequest);
7835
+ }
7836
+ catch (e) {
7837
+ if (e instanceof InteractionRequiredAuthError &&
7838
+ e.subError === badToken) {
7839
+ // Remove bad refresh token from cache
7840
+ this.logger.verbose("acquireTokenWithRefreshToken: bad refresh token, removing from cache");
7841
+ const badRefreshTokenKey = generateCredentialKey(refreshToken);
7842
+ this.cacheManager.removeRefreshToken(badRefreshTokenKey);
7843
+ }
7844
+ throw e;
7845
+ }
7458
7846
  }
7459
7847
  /**
7460
7848
  * Constructs the network message and makes a NW call to the underlying secure token service
@@ -7489,7 +7877,7 @@ class RefreshTokenClient extends BaseClient {
7489
7877
  this.performanceClient?.addQueueMeasurement(PerformanceEvents.RefreshTokenClientCreateTokenRequestBody, request.correlationId);
7490
7878
  const correlationId = request.correlationId;
7491
7879
  const parameterBuilder = new RequestParameterBuilder();
7492
- parameterBuilder.addClientId(request.tokenBodyParameters?.[AADServerParamKeys.CLIENT_ID] ||
7880
+ parameterBuilder.addClientId(request.tokenBodyParameters?.[CLIENT_ID] ||
7493
7881
  this.config.authOptions.clientId);
7494
7882
  if (request.redirectUri) {
7495
7883
  parameterBuilder.addRedirectUri(request.redirectUri);
@@ -7617,25 +8005,35 @@ class SilentFlowClient extends BaseClient {
7617
8005
  if (!request.account) {
7618
8006
  throw createClientAuthError(noAccountInSilentRequest);
7619
8007
  }
7620
- const environment = request.authority || this.authority.getPreferredCache();
7621
- const cacheRecord = this.cacheManager.readCacheRecord(request.account, request, environment, this.performanceClient, request.correlationId);
7622
- if (!cacheRecord.accessToken) {
8008
+ const requestTenantId = request.account.tenantId ||
8009
+ getTenantFromAuthorityString(request.authority);
8010
+ const tokenKeys = this.cacheManager.getTokenKeys();
8011
+ const cachedAccessToken = this.cacheManager.getAccessToken(request.account, request, tokenKeys, requestTenantId, this.performanceClient, request.correlationId);
8012
+ if (!cachedAccessToken) {
7623
8013
  // must refresh due to non-existent access_token
7624
8014
  this.setCacheOutcome(CacheOutcome.NO_CACHED_ACCESS_TOKEN, request.correlationId);
7625
8015
  throw createClientAuthError(tokenRefreshRequired);
7626
8016
  }
7627
- else if (TimeUtils.wasClockTurnedBack(cacheRecord.accessToken.cachedAt) ||
7628
- TimeUtils.isTokenExpired(cacheRecord.accessToken.expiresOn, this.config.systemOptions.tokenRenewalOffsetSeconds)) {
8017
+ else if (TimeUtils.wasClockTurnedBack(cachedAccessToken.cachedAt) ||
8018
+ TimeUtils.isTokenExpired(cachedAccessToken.expiresOn, this.config.systemOptions.tokenRenewalOffsetSeconds)) {
7629
8019
  // must refresh due to the expires_in value
7630
8020
  this.setCacheOutcome(CacheOutcome.CACHED_ACCESS_TOKEN_EXPIRED, request.correlationId);
7631
8021
  throw createClientAuthError(tokenRefreshRequired);
7632
8022
  }
7633
- else if (cacheRecord.accessToken.refreshOn &&
7634
- TimeUtils.isTokenExpired(cacheRecord.accessToken.refreshOn, 0)) {
8023
+ else if (cachedAccessToken.refreshOn &&
8024
+ TimeUtils.isTokenExpired(cachedAccessToken.refreshOn, 0)) {
7635
8025
  // must refresh (in the background) due to the refresh_in value
7636
8026
  lastCacheOutcome = CacheOutcome.PROACTIVELY_REFRESHED;
7637
8027
  // don't throw ClientAuthError.createRefreshRequiredError(), return cached token instead
7638
8028
  }
8029
+ const environment = request.authority || this.authority.getPreferredCache();
8030
+ const cacheRecord = {
8031
+ account: this.cacheManager.readAccountFromCache(request.account),
8032
+ accessToken: cachedAccessToken,
8033
+ idToken: this.cacheManager.getIdToken(request.account, tokenKeys, requestTenantId, this.performanceClient, request.correlationId),
8034
+ refreshToken: null,
8035
+ appMetadata: this.cacheManager.readAppMetadataFromCache(environment),
8036
+ };
7639
8037
  this.setCacheOutcome(lastCacheOutcome, request.correlationId);
7640
8038
  if (this.config.serverTelemetryManager) {
7641
8039
  this.config.serverTelemetryManager.incrementCacheHits();
@@ -7672,31 +8070,7 @@ class SilentFlowClient extends BaseClient {
7672
8070
  }
7673
8071
  checkMaxAge(authTime, request.maxAge);
7674
8072
  }
7675
- return await ResponseHandler.generateAuthenticationResult(this.cryptoUtils, this.authority, cacheRecord, true, request, idTokenClaims);
7676
- }
7677
- }
7678
-
7679
- /*
7680
- * Copyright (c) Microsoft Corporation. All rights reserved.
7681
- * Licensed under the MIT License.
7682
- */
7683
- class ThrottlingEntity {
7684
- /**
7685
- * validates if a given cache entry is "Throttling", parses <key,value>
7686
- * @param key
7687
- * @param entity
7688
- */
7689
- static isThrottlingEntity(key, entity) {
7690
- let validateKey = false;
7691
- if (key) {
7692
- validateKey =
7693
- key.indexOf(ThrottlingConstants.THROTTLING_PREFIX) === 0;
7694
- }
7695
- let validateEntity = true;
7696
- if (entity) {
7697
- validateEntity = entity.hasOwnProperty("throttleTime");
7698
- }
7699
- return validateKey && validateEntity;
8073
+ return ResponseHandler.generateAuthenticationResult(this.cryptoUtils, this.authority, cacheRecord, true, request, idTokenClaims);
7700
8074
  }
7701
8075
  }
7702
8076
 
@@ -8039,6 +8413,83 @@ class ServerTelemetryManager {
8039
8413
  }
8040
8414
  }
8041
8415
 
8416
+ /*
8417
+ * Copyright (c) Microsoft Corporation. All rights reserved.
8418
+ * Licensed under the MIT License.
8419
+ */
8420
+ class StubPerformanceMeasurement {
8421
+ startMeasurement() {
8422
+ return;
8423
+ }
8424
+ endMeasurement() {
8425
+ return;
8426
+ }
8427
+ flushMeasurement() {
8428
+ return null;
8429
+ }
8430
+ }
8431
+ class StubPerformanceClient {
8432
+ generateId() {
8433
+ return "callback-id";
8434
+ }
8435
+ startMeasurement(measureName, correlationId) {
8436
+ return {
8437
+ end: () => null,
8438
+ discard: () => { },
8439
+ add: () => { },
8440
+ increment: () => { },
8441
+ event: {
8442
+ eventId: this.generateId(),
8443
+ status: PerformanceEventStatus.InProgress,
8444
+ authority: "",
8445
+ libraryName: "",
8446
+ libraryVersion: "",
8447
+ clientId: "",
8448
+ name: measureName,
8449
+ startTimeMs: Date.now(),
8450
+ correlationId: correlationId || "",
8451
+ },
8452
+ measurement: new StubPerformanceMeasurement(),
8453
+ };
8454
+ }
8455
+ startPerformanceMeasurement() {
8456
+ return new StubPerformanceMeasurement();
8457
+ }
8458
+ calculateQueuedTime() {
8459
+ return 0;
8460
+ }
8461
+ addQueueMeasurement() {
8462
+ return;
8463
+ }
8464
+ setPreQueueTime() {
8465
+ return;
8466
+ }
8467
+ endMeasurement() {
8468
+ return null;
8469
+ }
8470
+ discardMeasurements() {
8471
+ return;
8472
+ }
8473
+ removePerformanceCallback() {
8474
+ return true;
8475
+ }
8476
+ addPerformanceCallback() {
8477
+ return "";
8478
+ }
8479
+ emitEvents() {
8480
+ return;
8481
+ }
8482
+ addFields() {
8483
+ return;
8484
+ }
8485
+ incrementFields() {
8486
+ return;
8487
+ }
8488
+ cacheEventByCorrelationId() {
8489
+ return;
8490
+ }
8491
+ }
8492
+
8042
8493
  /*
8043
8494
  * Copyright (c) Microsoft Corporation. All rights reserved.
8044
8495
  * Licensed under the MIT License.
@@ -8080,6 +8531,7 @@ class PerformanceClient {
8080
8531
  * @param {string} measureName
8081
8532
  * @param {string} correlationId
8082
8533
  * @returns {IPerformanceMeasurement}
8534
+ * @deprecated This method will be removed in the next major version
8083
8535
  */
8084
8536
  startPerformanceMeasurement(measureName, // eslint-disable-line @typescript-eslint/no-unused-vars
8085
8537
  correlationId // eslint-disable-line @typescript-eslint/no-unused-vars
@@ -8185,8 +8637,6 @@ class PerformanceClient {
8185
8637
  this.logger.info(`PerformanceClient: No correlation id provided for ${measureName}, generating`, eventCorrelationId);
8186
8638
  }
8187
8639
  this.logger.trace(`PerformanceClient: Performance measurement started for ${measureName}`, eventCorrelationId);
8188
- const performanceMeasurement = this.startPerformanceMeasurement(measureName, eventCorrelationId);
8189
- performanceMeasurement.startMeasurement();
8190
8640
  const inProgressEvent = {
8191
8641
  eventId: this.generateId(),
8192
8642
  status: PerformanceEventStatus.InProgress,
@@ -8210,7 +8660,7 @@ class PerformanceClient {
8210
8660
  ...inProgressEvent,
8211
8661
  // Properties set when event ends
8212
8662
  ...event,
8213
- }, performanceMeasurement);
8663
+ });
8214
8664
  },
8215
8665
  discard: () => {
8216
8666
  return this.discardMeasurements(inProgressEvent.correlationId);
@@ -8221,8 +8671,8 @@ class PerformanceClient {
8221
8671
  increment: (fields) => {
8222
8672
  return this.incrementFields(fields, inProgressEvent.correlationId);
8223
8673
  },
8224
- measurement: performanceMeasurement,
8225
8674
  event: inProgressEvent,
8675
+ measurement: new StubPerformanceMeasurement(),
8226
8676
  };
8227
8677
  }
8228
8678
  /**
@@ -8235,7 +8685,7 @@ class PerformanceClient {
8235
8685
  * @param {IPerformanceMeasurement} measurement
8236
8686
  * @returns {(PerformanceEvent | null)}
8237
8687
  */
8238
- endMeasurement(event, measurement) {
8688
+ endMeasurement(event) {
8239
8689
  const rootEvent = this.eventsByCorrelationId.get(event.correlationId);
8240
8690
  if (!rootEvent) {
8241
8691
  this.logger.trace(`PerformanceClient: Measurement not found for ${event.eventId}`, event.correlationId);
@@ -8254,13 +8704,7 @@ class PerformanceClient {
8254
8704
  else {
8255
8705
  rootEvent.incompleteSubMeasurements?.delete(event.eventId);
8256
8706
  }
8257
- measurement?.endMeasurement();
8258
- const durationMs = measurement?.flushMeasurement();
8259
- // null indicates no measurement was taken (e.g. needed performance APIs not present)
8260
- if (!durationMs) {
8261
- this.logger.trace("PerformanceClient: Performance measurement not taken", rootEvent.correlationId);
8262
- return null;
8263
- }
8707
+ const durationMs = event.durationMs || this.getDurationMs(event.startTimeMs);
8264
8708
  this.logger.trace(`PerformanceClient: Performance measurement ended for ${event.name}: ${durationMs} ms`, event.correlationId);
8265
8709
  // Add sub-measurement attribute to root event.
8266
8710
  if (!isRoot) {
@@ -8447,82 +8891,15 @@ class PerformanceClient {
8447
8891
  }
8448
8892
  });
8449
8893
  }
8450
- }
8451
-
8452
- /*
8453
- * Copyright (c) Microsoft Corporation. All rights reserved.
8454
- * Licensed under the MIT License.
8455
- */
8456
- class StubPerformanceMeasurement {
8457
- startMeasurement() {
8458
- return;
8459
- }
8460
- endMeasurement() {
8461
- return;
8462
- }
8463
- flushMeasurement() {
8464
- return null;
8465
- }
8466
- }
8467
- class StubPerformanceClient {
8468
- generateId() {
8469
- return "callback-id";
8470
- }
8471
- startMeasurement(measureName, correlationId) {
8472
- return {
8473
- end: () => null,
8474
- discard: () => { },
8475
- add: () => { },
8476
- increment: () => { },
8477
- event: {
8478
- eventId: this.generateId(),
8479
- status: PerformanceEventStatus.InProgress,
8480
- authority: "",
8481
- libraryName: "",
8482
- libraryVersion: "",
8483
- clientId: "",
8484
- name: measureName,
8485
- startTimeMs: Date.now(),
8486
- correlationId: correlationId || "",
8487
- },
8488
- measurement: new StubPerformanceMeasurement(),
8489
- };
8490
- }
8491
- startPerformanceMeasurement() {
8492
- return new StubPerformanceMeasurement();
8493
- }
8494
- calculateQueuedTime() {
8495
- return 0;
8496
- }
8497
- addQueueMeasurement() {
8498
- return;
8499
- }
8500
- setPreQueueTime() {
8501
- return;
8502
- }
8503
- endMeasurement() {
8504
- return null;
8505
- }
8506
- discardMeasurements() {
8507
- return;
8508
- }
8509
- removePerformanceCallback() {
8510
- return true;
8511
- }
8512
- addPerformanceCallback() {
8513
- return "";
8514
- }
8515
- emitEvents() {
8516
- return;
8517
- }
8518
- addFields() {
8519
- return;
8520
- }
8521
- incrementFields() {
8522
- return;
8523
- }
8524
- cacheEventByCorrelationId() {
8525
- return;
8894
+ /**
8895
+ * Returns event duration in milliseconds
8896
+ * @param startTimeMs {number}
8897
+ * @returns {number}
8898
+ */
8899
+ getDurationMs(startTimeMs) {
8900
+ const durationMs = Date.now() - startTimeMs;
8901
+ // Handle clock skew
8902
+ return durationMs < 0 ? durationMs : 0;
8526
8903
  }
8527
8904
  }
8528
8905
 
@@ -8562,6 +8939,7 @@ exports.Constants = Constants;
8562
8939
  exports.CredentialType = CredentialType;
8563
8940
  exports.DEFAULT_CRYPTO_IMPLEMENTATION = DEFAULT_CRYPTO_IMPLEMENTATION;
8564
8941
  exports.DEFAULT_SYSTEM_OPTIONS = DEFAULT_SYSTEM_OPTIONS;
8942
+ exports.DEFAULT_TOKEN_RENEWAL_OFFSET_SEC = DEFAULT_TOKEN_RENEWAL_OFFSET_SEC;
8565
8943
  exports.DefaultStorageClass = DefaultStorageClass;
8566
8944
  exports.Errors = Errors;
8567
8945
  exports.GrantType = GrantType;
@@ -8590,7 +8968,6 @@ exports.RefreshTokenClient = RefreshTokenClient;
8590
8968
  exports.RequestParameterBuilder = RequestParameterBuilder;
8591
8969
  exports.ResponseHandler = ResponseHandler;
8592
8970
  exports.ResponseMode = ResponseMode;
8593
- exports.SSOTypes = SSOTypes;
8594
8971
  exports.ScopeSet = ScopeSet;
8595
8972
  exports.ServerError = ServerError;
8596
8973
  exports.ServerResponseType = ServerResponseType;
@@ -8601,21 +8978,25 @@ exports.StubPerformanceClient = StubPerformanceClient;
8601
8978
  exports.StubbedNetworkModule = StubbedNetworkModule;
8602
8979
  exports.THE_FAMILY_ID = THE_FAMILY_ID;
8603
8980
  exports.ThrottlingConstants = ThrottlingConstants;
8604
- exports.ThrottlingEntity = ThrottlingEntity;
8605
8981
  exports.ThrottlingUtils = ThrottlingUtils;
8606
8982
  exports.TimeUtils = TimeUtils;
8607
8983
  exports.TokenCacheContext = TokenCacheContext;
8608
8984
  exports.UrlString = UrlString;
8609
8985
  exports.UrlUtils = UrlUtils;
8986
+ exports.buildAccountToCache = buildAccountToCache;
8610
8987
  exports.buildClientInfo = buildClientInfo;
8611
8988
  exports.buildClientInfoFromHomeAccountId = buildClientInfoFromHomeAccountId;
8612
8989
  exports.buildStaticAuthorityOptions = buildStaticAuthorityOptions;
8990
+ exports.buildTenantProfileFromIdTokenClaims = buildTenantProfileFromIdTokenClaims;
8613
8991
  exports.createAuthError = createAuthError;
8614
8992
  exports.createClientAuthError = createClientAuthError;
8615
8993
  exports.createClientConfigurationError = createClientConfigurationError;
8616
8994
  exports.createInteractionRequiredAuthError = createInteractionRequiredAuthError;
8617
8995
  exports.formatAuthorityUri = formatAuthorityUri;
8996
+ exports.getTenantIdFromIdTokenClaims = getTenantIdFromIdTokenClaims;
8618
8997
  exports.invoke = invoke;
8619
8998
  exports.invokeAsync = invokeAsync;
8999
+ exports.tenantIdMatchesHomeTenant = tenantIdMatchesHomeTenant;
9000
+ exports.updateAccountTenantProfileData = updateAccountTenantProfileData;
8620
9001
  exports.version = version;
8621
9002
  //# sourceMappingURL=index.cjs.map