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