@azure/msal-common 15.9.0 → 15.11.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 +37 -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 +3 -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-CtW_2rqJ.js} +465 -595
- package/lib/index-node-CtW_2rqJ.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 +3 -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 +59 -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 +16 -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.11.0 2025-08-12 */
|
|
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.11.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,91 @@ 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
|
+
if (Object.keys(accountFilter).length === 0 ||
|
|
4213
|
+
Object.values(accountFilter).every((value) => !value)) {
|
|
4214
|
+
this.commonLogger.warning("getAccountInfoFilteredBy: Account filter is empty or invalid, returning null");
|
|
4215
|
+
return null;
|
|
4216
|
+
}
|
|
4217
|
+
const allAccounts = this.getAllAccounts(accountFilter, correlationId);
|
|
4218
|
+
if (allAccounts.length > 1) {
|
|
4219
|
+
// If one or more accounts are found, prioritize accounts that have an ID token
|
|
4220
|
+
const sortedAccounts = allAccounts.sort((account) => {
|
|
4221
|
+
return account.idTokenClaims ? -1 : 1;
|
|
4222
|
+
});
|
|
4223
|
+
return sortedAccounts[0];
|
|
4224
|
+
}
|
|
4225
|
+
else if (allAccounts.length === 1) {
|
|
4226
|
+
// If only one account is found, return it regardless of whether a matching ID token was found
|
|
4227
|
+
return allAccounts[0];
|
|
4228
|
+
}
|
|
4229
|
+
else {
|
|
4230
|
+
return null;
|
|
4231
|
+
}
|
|
4296
4232
|
}
|
|
4297
4233
|
/**
|
|
4298
|
-
* Returns
|
|
4234
|
+
* Returns a single matching
|
|
4235
|
+
* @param accountFilter
|
|
4236
|
+
* @returns
|
|
4299
4237
|
*/
|
|
4300
|
-
|
|
4301
|
-
|
|
4238
|
+
getBaseAccountInfo(accountFilter, correlationId) {
|
|
4239
|
+
const accountEntities = this.getAccountsFilteredBy(accountFilter, correlationId);
|
|
4240
|
+
if (accountEntities.length > 0) {
|
|
4241
|
+
return accountEntities[0].getAccountInfo();
|
|
4242
|
+
}
|
|
4243
|
+
else {
|
|
4244
|
+
return null;
|
|
4245
|
+
}
|
|
4302
4246
|
}
|
|
4303
4247
|
/**
|
|
4304
|
-
*
|
|
4305
|
-
*
|
|
4248
|
+
* Matches filtered account entities with cached ID tokens that match the tenant profile-specific account filters
|
|
4249
|
+
* and builds the account info objects from the matching ID token's claims
|
|
4250
|
+
* @param cachedAccounts
|
|
4251
|
+
* @param accountFilter
|
|
4252
|
+
* @returns Array of AccountInfo objects that match account and tenant profile filters
|
|
4306
4253
|
*/
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
accountInterface.environment || "",
|
|
4312
|
-
homeTenantId || accountInterface.tenantId || "",
|
|
4313
|
-
];
|
|
4314
|
-
return accountKey.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
|
|
4254
|
+
buildTenantProfiles(cachedAccounts, correlationId, accountFilter) {
|
|
4255
|
+
return cachedAccounts.flatMap((accountEntity) => {
|
|
4256
|
+
return this.getTenantProfilesFromAccountEntity(accountEntity, correlationId, accountFilter?.tenantId, accountFilter);
|
|
4257
|
+
});
|
|
4315
4258
|
}
|
|
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;
|
|
4259
|
+
getTenantedAccountInfoByFilter(accountInfo, tokenKeys, tenantProfile, correlationId, tenantProfileFilter) {
|
|
4260
|
+
let tenantedAccountInfo = null;
|
|
4261
|
+
let idTokenClaims;
|
|
4262
|
+
if (tenantProfileFilter) {
|
|
4263
|
+
if (!this.tenantProfileMatchesFilter(tenantProfile, tenantProfileFilter)) {
|
|
4264
|
+
return null;
|
|
4265
|
+
}
|
|
4330
4266
|
}
|
|
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
|
-
}
|
|
4267
|
+
const idToken = this.getIdToken(accountInfo, correlationId, tokenKeys, tenantProfile.tenantId);
|
|
4268
|
+
if (idToken) {
|
|
4269
|
+
idTokenClaims = extractTokenClaims(idToken.secret, this.cryptoImpl.base64Decode);
|
|
4270
|
+
if (!this.idTokenClaimsMatchTenantProfileFilter(idTokenClaims, tenantProfileFilter)) {
|
|
4271
|
+
// ID token sourced claims don't match so this tenant profile is not a match
|
|
4272
|
+
return null;
|
|
4273
|
+
}
|
|
4613
4274
|
}
|
|
4614
4275
|
// Expand tenant profile into account info based on matching tenant profile and if available matching ID token claims
|
|
4615
4276
|
tenantedAccountInfo = updateAccountTenantProfileData(accountInfo, tenantProfile, idTokenClaims, idToken?.secret);
|
|
@@ -4762,10 +4423,6 @@ class CacheManager {
|
|
|
4762
4423
|
const allAccountKeys = this.getAccountKeys();
|
|
4763
4424
|
const matchingAccounts = [];
|
|
4764
4425
|
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
4426
|
const entity = this.getAccount(cacheKey, correlationId);
|
|
4770
4427
|
// Match base account fields
|
|
4771
4428
|
if (!entity) {
|
|
@@ -4811,64 +4468,6 @@ class CacheManager {
|
|
|
4811
4468
|
});
|
|
4812
4469
|
return matchingAccounts;
|
|
4813
4470
|
}
|
|
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
4471
|
/**
|
|
4873
4472
|
* Returns whether or not the given credential entity matches the filter
|
|
4874
4473
|
* @param entity
|
|
@@ -4993,22 +4592,26 @@ class CacheManager {
|
|
|
4993
4592
|
* Removes all accounts and related tokens from cache.
|
|
4994
4593
|
*/
|
|
4995
4594
|
removeAllAccounts(correlationId) {
|
|
4996
|
-
const
|
|
4997
|
-
|
|
4998
|
-
this.removeAccount(
|
|
4595
|
+
const accounts = this.getAllAccounts({}, correlationId);
|
|
4596
|
+
accounts.forEach((account) => {
|
|
4597
|
+
this.removeAccount(account, correlationId);
|
|
4999
4598
|
});
|
|
5000
4599
|
}
|
|
5001
4600
|
/**
|
|
5002
4601
|
* Removes the account and related tokens for a given account key
|
|
5003
4602
|
* @param account
|
|
5004
4603
|
*/
|
|
5005
|
-
removeAccount(
|
|
5006
|
-
const account = this.getAccount(accountKey, correlationId);
|
|
5007
|
-
if (!account) {
|
|
5008
|
-
return;
|
|
5009
|
-
}
|
|
4604
|
+
removeAccount(account, correlationId) {
|
|
5010
4605
|
this.removeAccountContext(account, correlationId);
|
|
5011
|
-
this.
|
|
4606
|
+
const accountKeys = this.getAccountKeys();
|
|
4607
|
+
const keyFilter = (key) => {
|
|
4608
|
+
return (key.includes(account.homeAccountId) &&
|
|
4609
|
+
key.includes(account.environment));
|
|
4610
|
+
};
|
|
4611
|
+
accountKeys.filter(keyFilter).forEach((key) => {
|
|
4612
|
+
this.removeItem(key, correlationId);
|
|
4613
|
+
this.performanceClient.incrementFields({ accountsRemoved: 1 }, correlationId);
|
|
4614
|
+
});
|
|
5012
4615
|
}
|
|
5013
4616
|
/**
|
|
5014
4617
|
* Removes credentials associated with the provided account
|
|
@@ -5016,21 +4619,18 @@ class CacheManager {
|
|
|
5016
4619
|
*/
|
|
5017
4620
|
removeAccountContext(account, correlationId) {
|
|
5018
4621
|
const allTokenKeys = this.getTokenKeys();
|
|
5019
|
-
const
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
4622
|
+
const keyFilter = (key) => {
|
|
4623
|
+
return (key.includes(account.homeAccountId) &&
|
|
4624
|
+
key.includes(account.environment));
|
|
4625
|
+
};
|
|
4626
|
+
allTokenKeys.idToken.filter(keyFilter).forEach((key) => {
|
|
4627
|
+
this.removeIdToken(key, correlationId);
|
|
5024
4628
|
});
|
|
5025
|
-
allTokenKeys.accessToken.forEach((key) => {
|
|
5026
|
-
|
|
5027
|
-
this.removeAccessToken(key, correlationId);
|
|
5028
|
-
}
|
|
4629
|
+
allTokenKeys.accessToken.filter(keyFilter).forEach((key) => {
|
|
4630
|
+
this.removeAccessToken(key, correlationId);
|
|
5029
4631
|
});
|
|
5030
|
-
allTokenKeys.refreshToken.forEach((key) => {
|
|
5031
|
-
|
|
5032
|
-
this.removeRefreshToken(key, correlationId);
|
|
5033
|
-
}
|
|
4632
|
+
allTokenKeys.refreshToken.filter(keyFilter).forEach((key) => {
|
|
4633
|
+
this.removeRefreshToken(key, correlationId);
|
|
5034
4634
|
});
|
|
5035
4635
|
}
|
|
5036
4636
|
/**
|
|
@@ -5070,14 +4670,6 @@ class CacheManager {
|
|
|
5070
4670
|
});
|
|
5071
4671
|
return true;
|
|
5072
4672
|
}
|
|
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
4673
|
/**
|
|
5082
4674
|
* Retrieve IdTokenEntity from cache
|
|
5083
4675
|
* @param account {AccountInfo}
|
|
@@ -5247,7 +4839,7 @@ class CacheManager {
|
|
|
5247
4839
|
else if (numAccessTokens > 1) {
|
|
5248
4840
|
this.commonLogger.info("CacheManager:getAccessToken - Multiple access tokens found, clearing them", correlationId);
|
|
5249
4841
|
accessTokens.forEach((accessToken) => {
|
|
5250
|
-
this.removeAccessToken(generateCredentialKey(accessToken), correlationId);
|
|
4842
|
+
this.removeAccessToken(this.generateCredentialKey(accessToken), correlationId);
|
|
5251
4843
|
});
|
|
5252
4844
|
this.performanceClient.addFields({ multiMatchedAT: accessTokens.length }, correlationId);
|
|
5253
4845
|
return null;
|
|
@@ -5688,6 +5280,12 @@ class DefaultStorageClass extends CacheManager {
|
|
|
5688
5280
|
getTokenKeys() {
|
|
5689
5281
|
throw createClientAuthError(methodNotImplemented);
|
|
5690
5282
|
}
|
|
5283
|
+
generateCredentialKey() {
|
|
5284
|
+
throw createClientAuthError(methodNotImplemented);
|
|
5285
|
+
}
|
|
5286
|
+
generateAccountKey() {
|
|
5287
|
+
throw createClientAuthError(methodNotImplemented);
|
|
5288
|
+
}
|
|
5691
5289
|
}
|
|
5692
5290
|
|
|
5693
5291
|
/*
|
|
@@ -5858,22 +5456,60 @@ function buildAuthOptions(authOptions) {
|
|
|
5858
5456
|
};
|
|
5859
5457
|
}
|
|
5860
5458
|
/**
|
|
5861
|
-
* Returns true if config has protocolMode set to ProtocolMode.OIDC, false otherwise
|
|
5862
|
-
* @param ClientConfiguration
|
|
5459
|
+
* Returns true if config has protocolMode set to ProtocolMode.OIDC, false otherwise
|
|
5460
|
+
* @param ClientConfiguration
|
|
5461
|
+
*/
|
|
5462
|
+
function isOidcProtocolMode(config) {
|
|
5463
|
+
return (config.authOptions.authority.options.protocolMode === ProtocolMode.OIDC);
|
|
5464
|
+
}
|
|
5465
|
+
|
|
5466
|
+
/*
|
|
5467
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
5468
|
+
* Licensed under the MIT License.
|
|
5469
|
+
*/
|
|
5470
|
+
const CcsCredentialType = {
|
|
5471
|
+
HOME_ACCOUNT_ID: "home_account_id",
|
|
5472
|
+
UPN: "UPN",
|
|
5473
|
+
};
|
|
5474
|
+
|
|
5475
|
+
/*
|
|
5476
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
5477
|
+
* Licensed under the MIT License.
|
|
5478
|
+
*/
|
|
5479
|
+
/**
|
|
5480
|
+
* Function to build a client info object from server clientInfo string
|
|
5481
|
+
* @param rawClientInfo
|
|
5482
|
+
* @param crypto
|
|
5483
|
+
*/
|
|
5484
|
+
function buildClientInfo(rawClientInfo, base64Decode) {
|
|
5485
|
+
if (!rawClientInfo) {
|
|
5486
|
+
throw createClientAuthError(clientInfoEmptyError);
|
|
5487
|
+
}
|
|
5488
|
+
try {
|
|
5489
|
+
const decodedClientInfo = base64Decode(rawClientInfo);
|
|
5490
|
+
return JSON.parse(decodedClientInfo);
|
|
5491
|
+
}
|
|
5492
|
+
catch (e) {
|
|
5493
|
+
throw createClientAuthError(clientInfoDecodingError);
|
|
5494
|
+
}
|
|
5495
|
+
}
|
|
5496
|
+
/**
|
|
5497
|
+
* Function to build a client info object from cached homeAccountId string
|
|
5498
|
+
* @param homeAccountId
|
|
5863
5499
|
*/
|
|
5864
|
-
function
|
|
5865
|
-
|
|
5500
|
+
function buildClientInfoFromHomeAccountId(homeAccountId) {
|
|
5501
|
+
if (!homeAccountId) {
|
|
5502
|
+
throw createClientAuthError(clientInfoDecodingError);
|
|
5503
|
+
}
|
|
5504
|
+
const clientInfoParts = homeAccountId.split(Separators.CLIENT_INFO_SEPARATOR, 2);
|
|
5505
|
+
return {
|
|
5506
|
+
uid: clientInfoParts[0],
|
|
5507
|
+
utid: clientInfoParts.length < 2
|
|
5508
|
+
? Constants.EMPTY_STRING
|
|
5509
|
+
: clientInfoParts[1],
|
|
5510
|
+
};
|
|
5866
5511
|
}
|
|
5867
5512
|
|
|
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
5513
|
/*
|
|
5878
5514
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
5879
5515
|
* Licensed under the MIT License.
|
|
@@ -6634,6 +6270,240 @@ class BaseClient {
|
|
|
6634
6270
|
}
|
|
6635
6271
|
}
|
|
6636
6272
|
|
|
6273
|
+
/*
|
|
6274
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
6275
|
+
* Licensed under the MIT License.
|
|
6276
|
+
*/
|
|
6277
|
+
/**
|
|
6278
|
+
* Gets tenantId from available ID token claims to set as credential realm with the following precedence:
|
|
6279
|
+
* 1. tid - if the token is acquired from an Azure AD tenant tid will be present
|
|
6280
|
+
* 2. tfp - if the token is acquired from a modern B2C tenant tfp should be present
|
|
6281
|
+
* 3. acr - if the token is acquired from a legacy B2C tenant acr should be present
|
|
6282
|
+
* Downcased to match the realm case-insensitive comparison requirements
|
|
6283
|
+
* @param idTokenClaims
|
|
6284
|
+
* @returns
|
|
6285
|
+
*/
|
|
6286
|
+
function getTenantIdFromIdTokenClaims(idTokenClaims) {
|
|
6287
|
+
if (idTokenClaims) {
|
|
6288
|
+
const tenantId = idTokenClaims.tid || idTokenClaims.tfp || idTokenClaims.acr;
|
|
6289
|
+
return tenantId || null;
|
|
6290
|
+
}
|
|
6291
|
+
return null;
|
|
6292
|
+
}
|
|
6293
|
+
|
|
6294
|
+
/*
|
|
6295
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
6296
|
+
* Licensed under the MIT License.
|
|
6297
|
+
*/
|
|
6298
|
+
/**
|
|
6299
|
+
* Type that defines required and optional parameters for an Account field (based on universal cache schema implemented by all MSALs).
|
|
6300
|
+
*
|
|
6301
|
+
* Key : Value Schema
|
|
6302
|
+
*
|
|
6303
|
+
* Key: <home_account_id>-<environment>-<realm*>
|
|
6304
|
+
*
|
|
6305
|
+
* Value Schema:
|
|
6306
|
+
* {
|
|
6307
|
+
* homeAccountId: home account identifier for the auth scheme,
|
|
6308
|
+
* environment: entity that issued the token, represented as a full host
|
|
6309
|
+
* realm: Full tenant or organizational identifier that the account belongs to
|
|
6310
|
+
* localAccountId: Original tenant-specific accountID, usually used for legacy cases
|
|
6311
|
+
* username: primary username that represents the user, usually corresponds to preferred_username in the v2 endpt
|
|
6312
|
+
* authorityType: Accounts authority type as a string
|
|
6313
|
+
* name: Full name for the account, including given name and family name,
|
|
6314
|
+
* lastModificationTime: last time this entity was modified in the cache
|
|
6315
|
+
* lastModificationApp:
|
|
6316
|
+
* nativeAccountId: Account identifier on the native device
|
|
6317
|
+
* tenantProfiles: Array of tenant profile objects for each tenant that the account has authenticated with in the browser
|
|
6318
|
+
* }
|
|
6319
|
+
* @internal
|
|
6320
|
+
*/
|
|
6321
|
+
class AccountEntity {
|
|
6322
|
+
/**
|
|
6323
|
+
* Returns the AccountInfo interface for this account.
|
|
6324
|
+
*/
|
|
6325
|
+
getAccountInfo() {
|
|
6326
|
+
return {
|
|
6327
|
+
homeAccountId: this.homeAccountId,
|
|
6328
|
+
environment: this.environment,
|
|
6329
|
+
tenantId: this.realm,
|
|
6330
|
+
username: this.username,
|
|
6331
|
+
localAccountId: this.localAccountId,
|
|
6332
|
+
loginHint: this.loginHint,
|
|
6333
|
+
name: this.name,
|
|
6334
|
+
nativeAccountId: this.nativeAccountId,
|
|
6335
|
+
authorityType: this.authorityType,
|
|
6336
|
+
// Deserialize tenant profiles array into a Map
|
|
6337
|
+
tenantProfiles: new Map((this.tenantProfiles || []).map((tenantProfile) => {
|
|
6338
|
+
return [tenantProfile.tenantId, tenantProfile];
|
|
6339
|
+
})),
|
|
6340
|
+
};
|
|
6341
|
+
}
|
|
6342
|
+
/**
|
|
6343
|
+
* Returns true if the account entity is in single tenant format (outdated), false otherwise
|
|
6344
|
+
*/
|
|
6345
|
+
isSingleTenant() {
|
|
6346
|
+
return !this.tenantProfiles;
|
|
6347
|
+
}
|
|
6348
|
+
/**
|
|
6349
|
+
* Build Account cache from IdToken, clientInfo and authority/policy. Associated with AAD.
|
|
6350
|
+
* @param accountDetails
|
|
6351
|
+
*/
|
|
6352
|
+
static createAccount(accountDetails, authority, base64Decode) {
|
|
6353
|
+
const account = new AccountEntity();
|
|
6354
|
+
if (authority.authorityType === AuthorityType.Adfs) {
|
|
6355
|
+
account.authorityType = CacheAccountType.ADFS_ACCOUNT_TYPE;
|
|
6356
|
+
}
|
|
6357
|
+
else if (authority.protocolMode === ProtocolMode.OIDC) {
|
|
6358
|
+
account.authorityType = CacheAccountType.GENERIC_ACCOUNT_TYPE;
|
|
6359
|
+
}
|
|
6360
|
+
else {
|
|
6361
|
+
account.authorityType = CacheAccountType.MSSTS_ACCOUNT_TYPE;
|
|
6362
|
+
}
|
|
6363
|
+
let clientInfo;
|
|
6364
|
+
if (accountDetails.clientInfo && base64Decode) {
|
|
6365
|
+
clientInfo = buildClientInfo(accountDetails.clientInfo, base64Decode);
|
|
6366
|
+
}
|
|
6367
|
+
account.clientInfo = accountDetails.clientInfo;
|
|
6368
|
+
account.homeAccountId = accountDetails.homeAccountId;
|
|
6369
|
+
account.nativeAccountId = accountDetails.nativeAccountId;
|
|
6370
|
+
const env = accountDetails.environment ||
|
|
6371
|
+
(authority && authority.getPreferredCache());
|
|
6372
|
+
if (!env) {
|
|
6373
|
+
throw createClientAuthError(invalidCacheEnvironment);
|
|
6374
|
+
}
|
|
6375
|
+
account.environment = env;
|
|
6376
|
+
// non AAD scenarios can have empty realm
|
|
6377
|
+
account.realm =
|
|
6378
|
+
clientInfo?.utid ||
|
|
6379
|
+
getTenantIdFromIdTokenClaims(accountDetails.idTokenClaims) ||
|
|
6380
|
+
"";
|
|
6381
|
+
// How do you account for MSA CID here?
|
|
6382
|
+
account.localAccountId =
|
|
6383
|
+
clientInfo?.uid ||
|
|
6384
|
+
accountDetails.idTokenClaims?.oid ||
|
|
6385
|
+
accountDetails.idTokenClaims?.sub ||
|
|
6386
|
+
"";
|
|
6387
|
+
/*
|
|
6388
|
+
* In B2C scenarios the emails claim is used instead of preferred_username and it is an array.
|
|
6389
|
+
* In most cases it will contain a single email. This field should not be relied upon if a custom
|
|
6390
|
+
* policy is configured to return more than 1 email.
|
|
6391
|
+
*/
|
|
6392
|
+
const preferredUsername = accountDetails.idTokenClaims?.preferred_username ||
|
|
6393
|
+
accountDetails.idTokenClaims?.upn;
|
|
6394
|
+
const email = accountDetails.idTokenClaims?.emails
|
|
6395
|
+
? accountDetails.idTokenClaims.emails[0]
|
|
6396
|
+
: null;
|
|
6397
|
+
account.username = preferredUsername || email || "";
|
|
6398
|
+
account.loginHint = accountDetails.idTokenClaims?.login_hint;
|
|
6399
|
+
account.name = accountDetails.idTokenClaims?.name || "";
|
|
6400
|
+
account.cloudGraphHostName = accountDetails.cloudGraphHostName;
|
|
6401
|
+
account.msGraphHost = accountDetails.msGraphHost;
|
|
6402
|
+
if (accountDetails.tenantProfiles) {
|
|
6403
|
+
account.tenantProfiles = accountDetails.tenantProfiles;
|
|
6404
|
+
}
|
|
6405
|
+
else {
|
|
6406
|
+
const tenantProfile = buildTenantProfile(accountDetails.homeAccountId, account.localAccountId, account.realm, accountDetails.idTokenClaims);
|
|
6407
|
+
account.tenantProfiles = [tenantProfile];
|
|
6408
|
+
}
|
|
6409
|
+
return account;
|
|
6410
|
+
}
|
|
6411
|
+
/**
|
|
6412
|
+
* Creates an AccountEntity object from AccountInfo
|
|
6413
|
+
* @param accountInfo
|
|
6414
|
+
* @param cloudGraphHostName
|
|
6415
|
+
* @param msGraphHost
|
|
6416
|
+
* @returns
|
|
6417
|
+
*/
|
|
6418
|
+
static createFromAccountInfo(accountInfo, cloudGraphHostName, msGraphHost) {
|
|
6419
|
+
const account = new AccountEntity();
|
|
6420
|
+
account.authorityType =
|
|
6421
|
+
accountInfo.authorityType || CacheAccountType.GENERIC_ACCOUNT_TYPE;
|
|
6422
|
+
account.homeAccountId = accountInfo.homeAccountId;
|
|
6423
|
+
account.localAccountId = accountInfo.localAccountId;
|
|
6424
|
+
account.nativeAccountId = accountInfo.nativeAccountId;
|
|
6425
|
+
account.realm = accountInfo.tenantId;
|
|
6426
|
+
account.environment = accountInfo.environment;
|
|
6427
|
+
account.username = accountInfo.username;
|
|
6428
|
+
account.name = accountInfo.name;
|
|
6429
|
+
account.loginHint = accountInfo.loginHint;
|
|
6430
|
+
account.cloudGraphHostName = cloudGraphHostName;
|
|
6431
|
+
account.msGraphHost = msGraphHost;
|
|
6432
|
+
// Serialize tenant profiles map into an array
|
|
6433
|
+
account.tenantProfiles = Array.from(accountInfo.tenantProfiles?.values() || []);
|
|
6434
|
+
return account;
|
|
6435
|
+
}
|
|
6436
|
+
/**
|
|
6437
|
+
* Generate HomeAccountId from server response
|
|
6438
|
+
* @param serverClientInfo
|
|
6439
|
+
* @param authType
|
|
6440
|
+
*/
|
|
6441
|
+
static generateHomeAccountId(serverClientInfo, authType, logger, cryptoObj, idTokenClaims) {
|
|
6442
|
+
// since ADFS/DSTS do not have tid and does not set client_info
|
|
6443
|
+
if (!(authType === AuthorityType.Adfs ||
|
|
6444
|
+
authType === AuthorityType.Dsts)) {
|
|
6445
|
+
// for cases where there is clientInfo
|
|
6446
|
+
if (serverClientInfo) {
|
|
6447
|
+
try {
|
|
6448
|
+
const clientInfo = buildClientInfo(serverClientInfo, cryptoObj.base64Decode);
|
|
6449
|
+
if (clientInfo.uid && clientInfo.utid) {
|
|
6450
|
+
return `${clientInfo.uid}.${clientInfo.utid}`;
|
|
6451
|
+
}
|
|
6452
|
+
}
|
|
6453
|
+
catch (e) { }
|
|
6454
|
+
}
|
|
6455
|
+
logger.warning("No client info in response");
|
|
6456
|
+
}
|
|
6457
|
+
// default to "sub" claim
|
|
6458
|
+
return idTokenClaims?.sub || "";
|
|
6459
|
+
}
|
|
6460
|
+
/**
|
|
6461
|
+
* Validates an entity: checks for all expected params
|
|
6462
|
+
* @param entity
|
|
6463
|
+
*/
|
|
6464
|
+
static isAccountEntity(entity) {
|
|
6465
|
+
if (!entity) {
|
|
6466
|
+
return false;
|
|
6467
|
+
}
|
|
6468
|
+
return (entity.hasOwnProperty("homeAccountId") &&
|
|
6469
|
+
entity.hasOwnProperty("environment") &&
|
|
6470
|
+
entity.hasOwnProperty("realm") &&
|
|
6471
|
+
entity.hasOwnProperty("localAccountId") &&
|
|
6472
|
+
entity.hasOwnProperty("username") &&
|
|
6473
|
+
entity.hasOwnProperty("authorityType"));
|
|
6474
|
+
}
|
|
6475
|
+
/**
|
|
6476
|
+
* Helper function to determine whether 2 accountInfo objects represent the same account
|
|
6477
|
+
* @param accountA
|
|
6478
|
+
* @param accountB
|
|
6479
|
+
* @param compareClaims - If set to true idTokenClaims will also be compared to determine account equality
|
|
6480
|
+
*/
|
|
6481
|
+
static accountInfoIsEqual(accountA, accountB, compareClaims) {
|
|
6482
|
+
if (!accountA || !accountB) {
|
|
6483
|
+
return false;
|
|
6484
|
+
}
|
|
6485
|
+
let claimsMatch = true; // default to true so as to not fail comparison below if compareClaims: false
|
|
6486
|
+
if (compareClaims) {
|
|
6487
|
+
const accountAClaims = (accountA.idTokenClaims ||
|
|
6488
|
+
{});
|
|
6489
|
+
const accountBClaims = (accountB.idTokenClaims ||
|
|
6490
|
+
{});
|
|
6491
|
+
// issued at timestamp and nonce are expected to change each time a new id token is acquired
|
|
6492
|
+
claimsMatch =
|
|
6493
|
+
accountAClaims.iat === accountBClaims.iat &&
|
|
6494
|
+
accountAClaims.nonce === accountBClaims.nonce;
|
|
6495
|
+
}
|
|
6496
|
+
return (accountA.homeAccountId === accountB.homeAccountId &&
|
|
6497
|
+
accountA.localAccountId === accountB.localAccountId &&
|
|
6498
|
+
accountA.username === accountB.username &&
|
|
6499
|
+
accountA.tenantId === accountB.tenantId &&
|
|
6500
|
+
accountA.loginHint === accountB.loginHint &&
|
|
6501
|
+
accountA.environment === accountB.environment &&
|
|
6502
|
+
accountA.nativeAccountId === accountB.nativeAccountId &&
|
|
6503
|
+
claimsMatch);
|
|
6504
|
+
}
|
|
6505
|
+
}
|
|
6506
|
+
|
|
6637
6507
|
/*
|
|
6638
6508
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
6639
6509
|
* Licensed under the MIT License.
|
|
@@ -7035,7 +6905,7 @@ class ResponseHandler {
|
|
|
7035
6905
|
if (handlingRefreshTokenResponse &&
|
|
7036
6906
|
!forceCacheRefreshTokenResponse &&
|
|
7037
6907
|
cacheRecord.account) {
|
|
7038
|
-
const key = cacheRecord.account.
|
|
6908
|
+
const key = this.cacheStorage.generateAccountKey(cacheRecord.account.getAccountInfo());
|
|
7039
6909
|
const account = this.cacheStorage.getAccount(key, request.correlationId);
|
|
7040
6910
|
if (!account) {
|
|
7041
6911
|
this.logger.warning("Account used to refresh tokens not in persistence, refreshed tokens will not be stored in the cache");
|
|
@@ -7609,7 +7479,7 @@ class RefreshTokenClient extends BaseClient {
|
|
|
7609
7479
|
if (e.subError === badToken) {
|
|
7610
7480
|
// Remove bad refresh token from cache
|
|
7611
7481
|
this.logger.verbose("acquireTokenWithRefreshToken: bad refresh token, removing from cache");
|
|
7612
|
-
const badRefreshTokenKey = generateCredentialKey(refreshToken);
|
|
7482
|
+
const badRefreshTokenKey = this.cacheManager.generateCredentialKey(refreshToken);
|
|
7613
7483
|
this.cacheManager.removeRefreshToken(badRefreshTokenKey, request.correlationId);
|
|
7614
7484
|
}
|
|
7615
7485
|
}
|
|
@@ -7766,7 +7636,7 @@ class SilentFlowClient extends BaseClient {
|
|
|
7766
7636
|
}
|
|
7767
7637
|
const environment = request.authority || this.authority.getPreferredCache();
|
|
7768
7638
|
const cacheRecord = {
|
|
7769
|
-
account: this.cacheManager.
|
|
7639
|
+
account: this.cacheManager.getAccount(this.cacheManager.generateAccountKey(request.account), request.correlationId),
|
|
7770
7640
|
accessToken: cachedAccessToken,
|
|
7771
7641
|
idToken: this.cacheManager.getIdToken(request.account, request.correlationId, tokenKeys, requestTenantId, this.performanceClient),
|
|
7772
7642
|
refreshToken: null,
|
|
@@ -8044,7 +7914,7 @@ function extractAccountSid(account) {
|
|
|
8044
7914
|
return account.idTokenClaims?.sid || null;
|
|
8045
7915
|
}
|
|
8046
7916
|
function extractLoginHint(account) {
|
|
8047
|
-
return account.idTokenClaims?.login_hint || null;
|
|
7917
|
+
return account.loginHint || account.idTokenClaims?.login_hint || null;
|
|
8048
7918
|
}
|
|
8049
7919
|
|
|
8050
7920
|
var Authorize = /*#__PURE__*/Object.freeze({
|
|
@@ -8476,4 +8346,4 @@ exports.invokeAsync = invokeAsync;
|
|
|
8476
8346
|
exports.tenantIdMatchesHomeTenant = tenantIdMatchesHomeTenant;
|
|
8477
8347
|
exports.updateAccountTenantProfileData = updateAccountTenantProfileData;
|
|
8478
8348
|
exports.version = version;
|
|
8479
|
-
//# sourceMappingURL=index-node-
|
|
8349
|
+
//# sourceMappingURL=index-node-CtW_2rqJ.js.map
|