/*! @azure/msal-common v14.14.2 2024-08-28 */ 'use strict'; import { extractTokenClaims } from '../../account/AuthToken.mjs'; import { createClientAuthError } from '../../error/ClientAuthError.mjs'; import { Separators, CredentialType, AuthenticationScheme, SERVER_TELEM_CONSTANTS, ThrottlingConstants, APP_METADATA, AUTHORITY_METADATA_CONSTANTS } from '../../utils/Constants.mjs'; import { nowSeconds } from '../../utils/TimeUtils.mjs'; import { tokenClaimsCnfRequiredForSignedJwt } from '../../error/ClientAuthErrorCodes.mjs'; /* * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. */ /** * Cache Key: ------- * IdToken Example: uid.utid-login.microsoftonline.com-idtoken-app_client_id-contoso.com * AccessToken Example: uid.utid-login.microsoftonline.com-accesstoken-app_client_id-contoso.com-scope1 scope2--pop * RefreshToken Example: uid.utid-login.microsoftonline.com-refreshtoken-1-contoso.com * @param credentialEntity * @returns */ function generateCredentialKey(credentialEntity) { const credentialKey = [ generateAccountId(credentialEntity), generateCredentialId(credentialEntity), generateTarget(credentialEntity), generateClaimsHash(credentialEntity), generateScheme(credentialEntity), ]; return credentialKey.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase(); } /** * Create IdTokenEntity * @param homeAccountId * @param authenticationResult * @param clientId * @param authority */ function createIdTokenEntity(homeAccountId, environment, idToken, clientId, tenantId) { const idTokenEntity = { credentialType: CredentialType.ID_TOKEN, homeAccountId: homeAccountId, environment: environment, clientId: clientId, secret: idToken, realm: tenantId, }; return idTokenEntity; } /** * Create AccessTokenEntity * @param homeAccountId * @param environment * @param accessToken * @param clientId * @param tenantId * @param scopes * @param expiresOn * @param extExpiresOn */ function createAccessTokenEntity(homeAccountId, environment, accessToken, clientId, tenantId, scopes, expiresOn, extExpiresOn, base64Decode, refreshOn, tokenType, userAssertionHash, keyId, requestedClaims, requestedClaimsHash) { const atEntity = { homeAccountId: homeAccountId, credentialType: CredentialType.ACCESS_TOKEN, secret: accessToken, cachedAt: nowSeconds().toString(), expiresOn: expiresOn.toString(), extendedExpiresOn: extExpiresOn.toString(), environment: environment, clientId: clientId, realm: tenantId, target: scopes, tokenType: tokenType || AuthenticationScheme.BEARER, }; if (userAssertionHash) { atEntity.userAssertionHash = userAssertionHash; } if (refreshOn) { atEntity.refreshOn = refreshOn.toString(); } if (requestedClaims) { atEntity.requestedClaims = requestedClaims; atEntity.requestedClaimsHash = requestedClaimsHash; } /* * Create Access Token With Auth Scheme instead of regular access token * Cast to lower to handle "bearer" from ADFS */ if (atEntity.tokenType?.toLowerCase() !== AuthenticationScheme.BEARER.toLowerCase()) { atEntity.credentialType = CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME; switch (atEntity.tokenType) { case AuthenticationScheme.POP: // Make sure keyId is present and add it to credential const tokenClaims = extractTokenClaims(accessToken, base64Decode); if (!tokenClaims?.cnf?.kid) { throw createClientAuthError(tokenClaimsCnfRequiredForSignedJwt); } atEntity.keyId = tokenClaims.cnf.kid; break; case AuthenticationScheme.SSH: atEntity.keyId = keyId; } } return atEntity; } /** * Create RefreshTokenEntity * @param homeAccountId * @param authenticationResult * @param clientId * @param authority */ function createRefreshTokenEntity(homeAccountId, environment, refreshToken, clientId, familyId, userAssertionHash, expiresOn) { const rtEntity = { credentialType: CredentialType.REFRESH_TOKEN, homeAccountId: homeAccountId, environment: environment, clientId: clientId, secret: refreshToken, }; if (userAssertionHash) { rtEntity.userAssertionHash = userAssertionHash; } if (familyId) { rtEntity.familyId = familyId; } if (expiresOn) { rtEntity.expiresOn = expiresOn.toString(); } return rtEntity; } function isCredentialEntity(entity) { return (entity.hasOwnProperty("homeAccountId") && entity.hasOwnProperty("environment") && entity.hasOwnProperty("credentialType") && entity.hasOwnProperty("clientId") && entity.hasOwnProperty("secret")); } /** * Validates an entity: checks for all expected params * @param entity */ function isAccessTokenEntity(entity) { if (!entity) { return false; } return (isCredentialEntity(entity) && entity.hasOwnProperty("realm") && entity.hasOwnProperty("target") && (entity["credentialType"] === CredentialType.ACCESS_TOKEN || entity["credentialType"] === CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME)); } /** * Validates an entity: checks for all expected params * @param entity */ function isIdTokenEntity(entity) { if (!entity) { return false; } return (isCredentialEntity(entity) && entity.hasOwnProperty("realm") && entity["credentialType"] === CredentialType.ID_TOKEN); } /** * Validates an entity: checks for all expected params * @param entity */ function isRefreshTokenEntity(entity) { if (!entity) { return false; } return (isCredentialEntity(entity) && entity["credentialType"] === CredentialType.REFRESH_TOKEN); } /** * Generate Account Id key component as per the schema: - */ function generateAccountId(credentialEntity) { const accountId = [ credentialEntity.homeAccountId, credentialEntity.environment, ]; return accountId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase(); } /** * Generate Credential Id key component as per the schema: -- */ function generateCredentialId(credentialEntity) { const clientOrFamilyId = credentialEntity.credentialType === CredentialType.REFRESH_TOKEN ? credentialEntity.familyId || credentialEntity.clientId : credentialEntity.clientId; const credentialId = [ credentialEntity.credentialType, clientOrFamilyId, credentialEntity.realm || "", ]; return credentialId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase(); } /** * Generate target key component as per schema: */ function generateTarget(credentialEntity) { return (credentialEntity.target || "").toLowerCase(); } /** * Generate requested claims key component as per schema: */ function generateClaimsHash(credentialEntity) { return (credentialEntity.requestedClaimsHash || "").toLowerCase(); } /** * Generate scheme key componenet as per schema: */ function generateScheme(credentialEntity) { /* * PoP Tokens and SSH certs include scheme in cache key * Cast to lowercase to handle "bearer" from ADFS */ return credentialEntity.tokenType && credentialEntity.tokenType.toLowerCase() !== AuthenticationScheme.BEARER.toLowerCase() ? credentialEntity.tokenType.toLowerCase() : ""; } /** * validates if a given cache entry is "Telemetry", parses * @param key * @param entity */ function isServerTelemetryEntity(key, entity) { const validateKey = key.indexOf(SERVER_TELEM_CONSTANTS.CACHE_KEY) === 0; let validateEntity = true; if (entity) { validateEntity = entity.hasOwnProperty("failedRequests") && entity.hasOwnProperty("errors") && entity.hasOwnProperty("cacheHits"); } return validateKey && validateEntity; } /** * validates if a given cache entry is "Throttling", parses * @param key * @param entity */ function isThrottlingEntity(key, entity) { let validateKey = false; if (key) { validateKey = key.indexOf(ThrottlingConstants.THROTTLING_PREFIX) === 0; } let validateEntity = true; if (entity) { validateEntity = entity.hasOwnProperty("throttleTime"); } return validateKey && validateEntity; } /** * Generate AppMetadata Cache Key as per the schema: appmetadata-- */ function generateAppMetadataKey({ environment, clientId, }) { const appMetaDataKeyArray = [ APP_METADATA, environment, clientId, ]; return appMetaDataKeyArray .join(Separators.CACHE_KEY_SEPARATOR) .toLowerCase(); } /* * Validates an entity: checks for all expected params * @param entity */ function isAppMetadataEntity(key, entity) { if (!entity) { return false; } return (key.indexOf(APP_METADATA) === 0 && entity.hasOwnProperty("clientId") && entity.hasOwnProperty("environment")); } /** * Validates an entity: checks for all expected params * @param entity */ function isAuthorityMetadataEntity(key, entity) { if (!entity) { return false; } return (key.indexOf(AUTHORITY_METADATA_CONSTANTS.CACHE_KEY) === 0 && entity.hasOwnProperty("aliases") && entity.hasOwnProperty("preferred_cache") && entity.hasOwnProperty("preferred_network") && entity.hasOwnProperty("canonical_authority") && entity.hasOwnProperty("authorization_endpoint") && entity.hasOwnProperty("token_endpoint") && entity.hasOwnProperty("issuer") && entity.hasOwnProperty("aliasesFromNetwork") && entity.hasOwnProperty("endpointsFromNetwork") && entity.hasOwnProperty("expiresAt") && entity.hasOwnProperty("jwks_uri")); } /** * Reset the exiresAt value */ function generateAuthorityMetadataExpiresAt() { return (nowSeconds() + AUTHORITY_METADATA_CONSTANTS.REFRESH_TIME_SECONDS); } function updateAuthorityEndpointMetadata(authorityMetadata, updatedValues, fromNetwork) { authorityMetadata.authorization_endpoint = updatedValues.authorization_endpoint; authorityMetadata.token_endpoint = updatedValues.token_endpoint; authorityMetadata.end_session_endpoint = updatedValues.end_session_endpoint; authorityMetadata.issuer = updatedValues.issuer; authorityMetadata.endpointsFromNetwork = fromNetwork; authorityMetadata.jwks_uri = updatedValues.jwks_uri; } function updateCloudDiscoveryMetadata(authorityMetadata, updatedValues, fromNetwork) { authorityMetadata.aliases = updatedValues.aliases; authorityMetadata.preferred_cache = updatedValues.preferred_cache; authorityMetadata.preferred_network = updatedValues.preferred_network; authorityMetadata.aliasesFromNetwork = fromNetwork; } /** * Returns whether or not the data needs to be refreshed */ function isAuthorityMetadataExpired(metadata) { return metadata.expiresAt <= nowSeconds(); } export { createAccessTokenEntity, createIdTokenEntity, createRefreshTokenEntity, generateAppMetadataKey, generateAuthorityMetadataExpiresAt, generateCredentialKey, isAccessTokenEntity, isAppMetadataEntity, isAuthorityMetadataEntity, isAuthorityMetadataExpired, isCredentialEntity, isIdTokenEntity, isRefreshTokenEntity, isServerTelemetryEntity, isThrottlingEntity, updateAuthorityEndpointMetadata, updateCloudDiscoveryMetadata }; //# sourceMappingURL=CacheHelpers.mjs.map