mirror of
https://github.com/tvytlx/ai-agent-deep-dive.git
synced 2026-04-06 00:54:49 +08:00
271 lines
9.6 KiB
JavaScript
271 lines
9.6 KiB
JavaScript
/*! @azure/msal-common v15.13.1 2025-10-29 */
|
|
'use strict';
|
|
import { extractTokenClaims } from '../../account/AuthToken.mjs';
|
|
import { createClientAuthError } from '../../error/ClientAuthError.mjs';
|
|
import { CredentialType, AuthenticationScheme, SERVER_TELEM_CONSTANTS, ThrottlingConstants, APP_METADATA, Separators, 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.
|
|
*/
|
|
/**
|
|
* 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,
|
|
lastUpdatedAt: Date.now().toString(), // Set the last updated time to now
|
|
};
|
|
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,
|
|
lastUpdatedAt: Date.now().toString(), // Set the last updated time to now
|
|
};
|
|
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,
|
|
lastUpdatedAt: Date.now().toString(),
|
|
};
|
|
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);
|
|
}
|
|
/**
|
|
* validates if a given cache entry is "Telemetry", parses <key,value>
|
|
* @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 <key,value>
|
|
* @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-<environment>-<client_id>
|
|
*/
|
|
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, isAccessTokenEntity, isAppMetadataEntity, isAuthorityMetadataEntity, isAuthorityMetadataExpired, isCredentialEntity, isIdTokenEntity, isRefreshTokenEntity, isServerTelemetryEntity, isThrottlingEntity, updateAuthorityEndpointMetadata, updateCloudDiscoveryMetadata };
|
|
//# sourceMappingURL=CacheHelpers.mjs.map
|