Estructura inicial del proyecto
This commit is contained in:
272
backend/node_modules/@azure/msal-common/src/client/SilentFlowClient.ts
generated
vendored
Normal file
272
backend/node_modules/@azure/msal-common/src/client/SilentFlowClient.ts
generated
vendored
Normal file
@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
import {
|
||||
buildClientConfiguration,
|
||||
ClientConfiguration,
|
||||
CommonClientConfiguration,
|
||||
} from "../config/ClientConfiguration.js";
|
||||
import { CommonSilentFlowRequest } from "../request/CommonSilentFlowRequest.js";
|
||||
import { AuthenticationResult } from "../response/AuthenticationResult.js";
|
||||
import * as TimeUtils from "../utils/TimeUtils.js";
|
||||
import {
|
||||
ClientAuthErrorCodes,
|
||||
createClientAuthError,
|
||||
} from "../error/ClientAuthError.js";
|
||||
import { ResponseHandler } from "../response/ResponseHandler.js";
|
||||
import { CacheRecord } from "../cache/entities/CacheRecord.js";
|
||||
import { CacheOutcome } from "../utils/Constants.js";
|
||||
import { IPerformanceClient } from "../telemetry/performance/IPerformanceClient.js";
|
||||
import { StringUtils } from "../utils/StringUtils.js";
|
||||
import { checkMaxAge, extractTokenClaims } from "../account/AuthToken.js";
|
||||
import { TokenClaims } from "../account/TokenClaims.js";
|
||||
import * as PerformanceEvents from "../telemetry/performance/PerformanceEvents.js";
|
||||
import { invokeAsync } from "../utils/FunctionWrappers.js";
|
||||
import {
|
||||
Authority,
|
||||
getTenantFromAuthorityString,
|
||||
} from "../authority/Authority.js";
|
||||
import { Logger } from "../logger/Logger.js";
|
||||
import { ICrypto } from "../crypto/ICrypto.js";
|
||||
import { CacheManager } from "../cache/CacheManager.js";
|
||||
import { INetworkModule } from "../network/INetworkModule.js";
|
||||
import { ServerTelemetryManager } from "../telemetry/server/ServerTelemetryManager.js";
|
||||
import { version, name } from "../packageMetadata.js";
|
||||
|
||||
/** @internal */
|
||||
export class SilentFlowClient {
|
||||
// Logger object
|
||||
public logger: Logger;
|
||||
|
||||
// Application config
|
||||
protected config: CommonClientConfiguration;
|
||||
|
||||
// Crypto Interface
|
||||
protected cryptoUtils: ICrypto;
|
||||
|
||||
// Storage Interface
|
||||
protected cacheManager: CacheManager;
|
||||
|
||||
// Network Interface
|
||||
protected networkClient: INetworkModule;
|
||||
|
||||
// Server Telemetry Manager
|
||||
protected serverTelemetryManager: ServerTelemetryManager | null;
|
||||
|
||||
// Default authority object
|
||||
public authority: Authority;
|
||||
|
||||
// Performance telemetry client
|
||||
protected performanceClient: IPerformanceClient;
|
||||
|
||||
constructor(
|
||||
configuration: ClientConfiguration,
|
||||
performanceClient: IPerformanceClient
|
||||
) {
|
||||
// Set the configuration
|
||||
this.config = buildClientConfiguration(configuration);
|
||||
|
||||
// Initialize the logger
|
||||
this.logger = new Logger(this.config.loggerOptions, name, version);
|
||||
|
||||
// Initialize crypto
|
||||
this.cryptoUtils = this.config.cryptoInterface;
|
||||
|
||||
// Initialize storage interface
|
||||
this.cacheManager = this.config.storageInterface;
|
||||
|
||||
// Set the network interface
|
||||
this.networkClient = this.config.networkInterface;
|
||||
|
||||
// Set TelemetryManager
|
||||
this.serverTelemetryManager = this.config.serverTelemetryManager;
|
||||
|
||||
// set Authority
|
||||
this.authority = this.config.authOptions.authority;
|
||||
|
||||
// set performance telemetry client
|
||||
this.performanceClient = performanceClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves token from cache or throws an error if it must be refreshed.
|
||||
* @param request
|
||||
*/
|
||||
async acquireCachedToken(
|
||||
request: CommonSilentFlowRequest
|
||||
): Promise<[AuthenticationResult, CacheOutcome]> {
|
||||
let lastCacheOutcome: CacheOutcome = CacheOutcome.NOT_APPLICABLE;
|
||||
|
||||
if (request.forceRefresh || !StringUtils.isEmptyObj(request.claims)) {
|
||||
// Must refresh due to present force_refresh flag.
|
||||
this.setCacheOutcome(
|
||||
CacheOutcome.FORCE_REFRESH_OR_CLAIMS,
|
||||
request.correlationId
|
||||
);
|
||||
throw createClientAuthError(
|
||||
ClientAuthErrorCodes.tokenRefreshRequired
|
||||
);
|
||||
}
|
||||
|
||||
// We currently do not support silent flow for account === null use cases; This will be revisited for confidential flow usecases
|
||||
if (!request.account) {
|
||||
throw createClientAuthError(
|
||||
ClientAuthErrorCodes.noAccountInSilentRequest
|
||||
);
|
||||
}
|
||||
|
||||
const requestTenantId =
|
||||
request.account.tenantId ||
|
||||
getTenantFromAuthorityString(request.authority);
|
||||
const tokenKeys = this.cacheManager.getTokenKeys();
|
||||
const cachedAccessToken = this.cacheManager.getAccessToken(
|
||||
request.account,
|
||||
request,
|
||||
tokenKeys,
|
||||
requestTenantId
|
||||
);
|
||||
|
||||
if (!cachedAccessToken) {
|
||||
// must refresh due to non-existent access_token
|
||||
this.setCacheOutcome(
|
||||
CacheOutcome.NO_CACHED_ACCESS_TOKEN,
|
||||
request.correlationId
|
||||
);
|
||||
throw createClientAuthError(
|
||||
ClientAuthErrorCodes.tokenRefreshRequired
|
||||
);
|
||||
} else if (
|
||||
TimeUtils.wasClockTurnedBack(cachedAccessToken.cachedAt) ||
|
||||
TimeUtils.isTokenExpired(
|
||||
cachedAccessToken.expiresOn,
|
||||
this.config.systemOptions.tokenRenewalOffsetSeconds
|
||||
)
|
||||
) {
|
||||
// must refresh due to the expires_in value
|
||||
this.setCacheOutcome(
|
||||
CacheOutcome.CACHED_ACCESS_TOKEN_EXPIRED,
|
||||
request.correlationId
|
||||
);
|
||||
throw createClientAuthError(
|
||||
ClientAuthErrorCodes.tokenRefreshRequired
|
||||
);
|
||||
} else if (request.resource) {
|
||||
// cached access token must have a resource that matches the request resource for MCP scenarios
|
||||
if (cachedAccessToken.resource !== request.resource) {
|
||||
this.setCacheOutcome(
|
||||
CacheOutcome.NO_CACHED_ACCESS_TOKEN,
|
||||
request.correlationId
|
||||
);
|
||||
throw createClientAuthError(
|
||||
ClientAuthErrorCodes.tokenRefreshRequired
|
||||
);
|
||||
}
|
||||
} else if (
|
||||
cachedAccessToken.refreshOn &&
|
||||
TimeUtils.isTokenExpired(cachedAccessToken.refreshOn, 0)
|
||||
) {
|
||||
// must refresh (in the background) due to the refresh_in value
|
||||
lastCacheOutcome = CacheOutcome.PROACTIVELY_REFRESHED;
|
||||
|
||||
// don't throw ClientAuthError.createRefreshRequiredError(), return cached token instead
|
||||
}
|
||||
|
||||
const environment =
|
||||
request.authority || this.authority.getPreferredCache();
|
||||
const cacheRecord: CacheRecord = {
|
||||
account: this.cacheManager.getAccount(
|
||||
this.cacheManager.generateAccountKey(request.account),
|
||||
request.correlationId
|
||||
),
|
||||
accessToken: cachedAccessToken,
|
||||
idToken: this.cacheManager.getIdToken(
|
||||
request.account,
|
||||
request.correlationId,
|
||||
tokenKeys,
|
||||
requestTenantId
|
||||
),
|
||||
refreshToken: null,
|
||||
appMetadata: this.cacheManager.readAppMetadataFromCache(
|
||||
environment,
|
||||
request.correlationId
|
||||
),
|
||||
};
|
||||
|
||||
this.setCacheOutcome(lastCacheOutcome, request.correlationId);
|
||||
|
||||
if (this.config.serverTelemetryManager) {
|
||||
this.config.serverTelemetryManager.incrementCacheHits();
|
||||
}
|
||||
|
||||
return [
|
||||
await invokeAsync(
|
||||
this.generateResultFromCacheRecord.bind(this),
|
||||
PerformanceEvents.SilentFlowClientGenerateResultFromCacheRecord,
|
||||
this.logger,
|
||||
this.performanceClient,
|
||||
request.correlationId
|
||||
)(cacheRecord, request),
|
||||
lastCacheOutcome,
|
||||
];
|
||||
}
|
||||
|
||||
private setCacheOutcome(
|
||||
cacheOutcome: CacheOutcome,
|
||||
correlationId: string
|
||||
): void {
|
||||
this.serverTelemetryManager?.setCacheOutcome(cacheOutcome);
|
||||
this.performanceClient?.addFields(
|
||||
{
|
||||
cacheOutcome: cacheOutcome,
|
||||
},
|
||||
correlationId
|
||||
);
|
||||
if (cacheOutcome !== CacheOutcome.NOT_APPLICABLE) {
|
||||
this.logger.info(
|
||||
`Token refresh is required due to cache outcome: '${cacheOutcome}'`,
|
||||
correlationId
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to build response object from the CacheRecord
|
||||
* @param cacheRecord
|
||||
*/
|
||||
private async generateResultFromCacheRecord(
|
||||
cacheRecord: CacheRecord,
|
||||
request: CommonSilentFlowRequest
|
||||
): Promise<AuthenticationResult> {
|
||||
let idTokenClaims: TokenClaims | undefined;
|
||||
if (cacheRecord.idToken) {
|
||||
idTokenClaims = extractTokenClaims(
|
||||
cacheRecord.idToken.secret,
|
||||
this.config.cryptoInterface.base64Decode
|
||||
);
|
||||
}
|
||||
|
||||
// token max_age check
|
||||
if (request.maxAge || request.maxAge === 0) {
|
||||
const authTime = idTokenClaims?.auth_time;
|
||||
if (!authTime) {
|
||||
throw createClientAuthError(
|
||||
ClientAuthErrorCodes.authTimeNotFound
|
||||
);
|
||||
}
|
||||
|
||||
checkMaxAge(authTime, request.maxAge);
|
||||
}
|
||||
|
||||
return ResponseHandler.generateAuthenticationResult(
|
||||
this.cryptoUtils,
|
||||
this.authority,
|
||||
cacheRecord,
|
||||
true,
|
||||
request,
|
||||
this.performanceClient,
|
||||
idTokenClaims
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user