Estructura inicial del proyecto

This commit is contained in:
2026-06-02 16:57:08 +00:00
commit 8b306b9afc
9864 changed files with 1435687 additions and 0 deletions

View File

@ -0,0 +1,481 @@
/*! @azure/msal-browser v5.11.0 2026-05-19 */
'use strict';
import { DEFAULT_CRYPTO_IMPLEMENTATION, buildStaticAuthorityOptions, enforceResourceParameter, TimeUtils, AuthError, Constants, AccountEntityUtils, AuthToken } from '@azure/msal-common/browser';
import { AcquireTokenPopup, SsoSilent, AcquireTokenSilent } from '../telemetry/BrowserRootPerformanceEvents.mjs';
import { InteractionType, CacheLookupPolicy, DEFAULT_REQUEST, ApiId } from '../utils/BrowserConstants.mjs';
import { CryptoOps } from '../crypto/CryptoOps.mjs';
import { NestedAppAuthAdapter } from '../naa/mapping/NestedAppAuthAdapter.mjs';
import { NestedAppAuthError } from '../error/NestedAppAuthError.mjs';
import { EventHandler } from '../event/EventHandler.mjs';
import { EventType } from '../event/EventType.mjs';
import { BrowserCacheManager, DEFAULT_BROWSER_CACHE_MANAGER } from '../cache/BrowserCacheManager.mjs';
import { getAccount, getAllAccounts, setActiveAccount, getActiveAccount } from '../cache/AccountManager.mjs';
import { createNewGuid } from '../crypto/BrowserCrypto.mjs';
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
class NestedAppAuthController {
constructor(operatingContext) {
this.operatingContext = operatingContext;
const proxy = this.operatingContext.getBridgeProxy();
if (proxy !== undefined) {
this.bridgeProxy = proxy;
}
else {
throw new Error("unexpected: bridgeProxy is undefined");
}
// Set the configuration.
this.config = operatingContext.getConfig();
// Initialize logger
this.logger = this.operatingContext.getLogger();
// Initialize performance client
this.performanceClient = this.config.telemetry.client;
// Initialize the crypto class.
this.browserCrypto = operatingContext.isBrowserEnvironment()
? new CryptoOps(this.logger, this.performanceClient, true)
: DEFAULT_CRYPTO_IMPLEMENTATION;
this.eventHandler = new EventHandler(this.logger);
// Initialize the browser storage class.
this.browserStorage = this.operatingContext.isBrowserEnvironment()
? new BrowserCacheManager(this.config.auth.clientId, this.config.cache, this.browserCrypto, this.logger, this.performanceClient, this.eventHandler, buildStaticAuthorityOptions(this.config.auth))
: DEFAULT_BROWSER_CACHE_MANAGER(this.config.auth.clientId, this.logger, this.performanceClient, this.eventHandler);
this.nestedAppAuthAdapter = new NestedAppAuthAdapter(this.config.auth.clientId, this.config.auth.clientCapabilities, this.browserCrypto, this.logger);
// Set the active account if available
const accountContext = this.bridgeProxy.getAccountContext();
this.currentAccountContext = accountContext ? accountContext : null;
}
/**
* Factory function to create a new instance of NestedAppAuthController
* @param operatingContext
* @returns Promise<IController>
*/
static async createController(operatingContext) {
const controller = new NestedAppAuthController(operatingContext);
return Promise.resolve(controller);
}
/**
* Specific implementation of initialize function for NestedAppAuthController
* @returns
*/
async initialize(request,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
isBroker) {
const initCorrelationId = request?.correlationId || createNewGuid();
await this.browserStorage.initialize(initCorrelationId);
return Promise.resolve();
}
/**
* Validate the incoming request and add correlationId if not present
* @param request
* @returns
*/
ensureValidRequest(request) {
if (request?.correlationId) {
return request;
}
return {
...request,
correlationId: this.browserCrypto.createNewGuid(),
};
}
/**
* Internal implementation of acquireTokenInteractive flow
* @param request
* @returns
*/
async acquireTokenInteractive(request) {
const validRequest = this.ensureValidRequest(request);
const correlationId = validRequest.correlationId || createNewGuid();
this.eventHandler.emitEvent(EventType.ACQUIRE_TOKEN_START, correlationId, InteractionType.Popup, validRequest);
const atPopupMeasurement = this.performanceClient.startMeasurement(AcquireTokenPopup, correlationId);
atPopupMeasurement.add({ nestedAppAuthRequest: true });
try {
enforceResourceParameter(this.config.auth.isMcp, validRequest);
const naaRequest = this.nestedAppAuthAdapter.toNaaTokenRequest(validRequest);
const reqTimestamp = TimeUtils.nowSeconds();
const response = await this.bridgeProxy.getTokenInteractive(naaRequest);
const result = {
...this.nestedAppAuthAdapter.fromNaaTokenResponse(naaRequest, response, reqTimestamp),
};
// cache the tokens in the response
try {
// cache hydration can fail in JS Runtime scenario that doesn't support full crypto API
await this.hydrateCache(result, request);
}
catch (error) {
this.logger.warningPii("1mwr91", correlationId);
}
// cache the account context in memory after successful token fetch
this.currentAccountContext = {
homeAccountId: result.account.homeAccountId,
environment: result.account.environment,
tenantId: result.account.tenantId,
};
this.eventHandler.emitEvent(EventType.ACQUIRE_TOKEN_SUCCESS, correlationId, InteractionType.Popup, result);
atPopupMeasurement.add({
accessTokenSize: result.accessToken.length,
idTokenSize: result.idToken.length,
});
atPopupMeasurement.end({
success: true,
requestId: result.requestId,
}, undefined, result.account);
return result;
}
catch (e) {
const error = e instanceof AuthError
? e
: this.nestedAppAuthAdapter.fromBridgeError(e);
this.eventHandler.emitEvent(EventType.ACQUIRE_TOKEN_FAILURE, correlationId, InteractionType.Popup, null, e);
atPopupMeasurement.end({
success: false,
}, e, request.account);
throw error;
}
}
/**
* Internal implementation of acquireTokenSilent flow
* @param request
* @returns
*/
async acquireTokenSilentInternal(request) {
const validRequest = this.ensureValidRequest(request);
const correlationId = validRequest.correlationId || createNewGuid();
this.eventHandler.emitEvent(EventType.ACQUIRE_TOKEN_START, correlationId, InteractionType.Silent, validRequest);
// Look for tokens in the cache first
const result = await this.acquireTokenFromCache(validRequest);
if (result) {
this.eventHandler.emitEvent(EventType.ACQUIRE_TOKEN_SUCCESS, correlationId, InteractionType.Silent, result);
return result;
}
// proceed with acquiring tokens via the host
const ssoSilentMeasurement = this.performanceClient.startMeasurement(SsoSilent, correlationId);
ssoSilentMeasurement.increment({
visibilityChangeCount: 0,
});
ssoSilentMeasurement.add({
nestedAppAuthRequest: true,
});
try {
enforceResourceParameter(this.config.auth.isMcp, validRequest);
const naaRequest = this.nestedAppAuthAdapter.toNaaTokenRequest(validRequest);
naaRequest.forceRefresh = validRequest.forceRefresh;
const reqTimestamp = TimeUtils.nowSeconds();
const response = await this.bridgeProxy.getTokenSilent(naaRequest);
const result = this.nestedAppAuthAdapter.fromNaaTokenResponse(naaRequest, response, reqTimestamp);
// cache the tokens in the response
try {
// cache hydration can fail in JS Runtime scenario that doesn't support full crypto API
await this.hydrateCache(result, request);
}
catch (error) {
this.logger.warningPii("1mwr91", correlationId);
}
// cache the account context in memory after successful token fetch
this.currentAccountContext = {
homeAccountId: result.account.homeAccountId,
environment: result.account.environment,
tenantId: result.account.tenantId,
};
this.eventHandler.emitEvent(EventType.ACQUIRE_TOKEN_SUCCESS, correlationId, InteractionType.Silent, result);
ssoSilentMeasurement?.add({
accessTokenSize: result.accessToken.length,
idTokenSize: result.idToken.length,
});
ssoSilentMeasurement?.end({
success: true,
requestId: result.requestId,
}, undefined, result.account);
return result;
}
catch (e) {
const error = e instanceof AuthError
? e
: this.nestedAppAuthAdapter.fromBridgeError(e);
this.eventHandler.emitEvent(EventType.ACQUIRE_TOKEN_FAILURE, correlationId, InteractionType.Silent, null, e);
ssoSilentMeasurement?.end({
success: false,
}, e, request.account);
throw error;
}
}
/**
* acquires tokens from cache
* @param request
* @returns
*/
async acquireTokenFromCache(request) {
const correlationId = request.correlationId || createNewGuid();
const atsMeasurement = this.performanceClient.startMeasurement(AcquireTokenSilent, correlationId);
atsMeasurement?.add({
nestedAppAuthRequest: true,
});
// if the request has claims, we cannot look up in the cache
if (request.claims) {
this.logger.verbose("11t57w", correlationId);
return null;
}
// if the request has forceRefresh, we cannot look up in the cache
if (request.forceRefresh) {
this.logger.verbose("1ovnmo", correlationId);
return null;
}
// respect cache lookup policy
let result = null;
if (!request.cacheLookupPolicy) {
request.cacheLookupPolicy = CacheLookupPolicy.Default;
}
switch (request.cacheLookupPolicy) {
case CacheLookupPolicy.Default:
case CacheLookupPolicy.AccessToken:
case CacheLookupPolicy.AccessTokenAndRefreshToken:
result = await this.acquireTokenFromCacheInternal(request);
break;
default:
return null;
}
if (result) {
this.eventHandler.emitEvent(EventType.ACQUIRE_TOKEN_SUCCESS, correlationId, InteractionType.Silent, result);
atsMeasurement.add({
accessTokenSize: result.accessToken.length,
idTokenSize: result.idToken.length,
});
atsMeasurement.end({
success: true,
}, undefined, result.account);
return result;
}
this.logger.warning("1yb4fi", correlationId);
this.eventHandler.emitEvent(EventType.ACQUIRE_TOKEN_FAILURE, correlationId, InteractionType.Silent, null);
atsMeasurement.end({
success: false,
}, undefined, request.account);
return null;
}
/**
*
* @param request
* @returns
*/
async acquireTokenFromCacheInternal(request) {
// always prioritize the account context from the bridge
const accountContext = this.bridgeProxy.getAccountContext() || this.currentAccountContext;
const correlationId = request.correlationId || createNewGuid();
let currentAccount = null;
if (accountContext) {
currentAccount = getAccount(accountContext, this.logger, this.browserStorage, correlationId);
}
// fall back to brokering if no cached account is found
if (!currentAccount) {
this.logger.verbose("10qnr0", correlationId);
return Promise.resolve(null);
}
this.logger.verbose("1u7hux", correlationId);
const authRequest = {
...request,
correlationId: correlationId,
authority: request.authority || currentAccount.environment,
scopes: request.scopes?.length
? request.scopes
: [...Constants.OIDC_DEFAULT_SCOPES],
};
// fetch access token and check for expiry
const tokenKeys = this.browserStorage.getTokenKeys();
const cachedAccessToken = this.browserStorage.getAccessToken(currentAccount, authRequest, tokenKeys, currentAccount.tenantId);
// If there is no access token, log it and return null
if (!cachedAccessToken) {
this.logger.verbose("03vm49", correlationId);
return Promise.resolve(null);
}
else if (TimeUtils.wasClockTurnedBack(cachedAccessToken.cachedAt) ||
TimeUtils.isTokenExpired(cachedAccessToken.expiresOn, this.config.system.tokenRenewalOffsetSeconds)) {
this.logger.verbose("18egye", correlationId);
return Promise.resolve(null);
}
else if (authRequest.resource) {
const requestedResource = authRequest.resource;
const cachedResource = cachedAccessToken.resource;
if (!cachedResource || cachedResource !== requestedResource) {
this.logger.verbose("0qraxd", correlationId);
return Promise.resolve(null);
}
}
const cachedIdToken = this.browserStorage.getIdToken(currentAccount, authRequest.correlationId, tokenKeys, currentAccount.tenantId);
if (!cachedIdToken) {
this.logger.verbose("0d68kd", correlationId);
return Promise.resolve(null);
}
return this.nestedAppAuthAdapter.toAuthenticationResultFromCache(currentAccount, cachedIdToken, cachedAccessToken, authRequest, authRequest.correlationId);
}
/**
* acquireTokenPopup flow implementation
* @param request
* @returns
*/
async acquireTokenPopup(request) {
return this.acquireTokenInteractive(request);
}
/**
* acquireTokenRedirect flow is not supported in nested app auth
* @param request
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
acquireTokenRedirect(request) {
throw NestedAppAuthError.createUnsupportedError();
}
/**
* acquireTokenSilent flow implementation
* @param silentRequest
* @returns
*/
async acquireTokenSilent(silentRequest) {
return this.acquireTokenSilentInternal(silentRequest);
}
/**
* Hybrid flow is not currently supported in nested app auth
* @param request
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
acquireTokenByCode(request // eslint-disable-line @typescript-eslint/no-unused-vars
) {
throw NestedAppAuthError.createUnsupportedError();
}
/**
* Adds event callbacks to array
* @param callback
* @param eventTypes
*/
addEventCallback(callback, eventTypes) {
return this.eventHandler.addEventCallback(callback, eventTypes);
}
/**
* Removes callback with provided id from callback array
* @param callbackId
*/
removeEventCallback(callbackId) {
this.eventHandler.removeEventCallback(callbackId);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
addPerformanceCallback(callback) {
throw NestedAppAuthError.createUnsupportedError();
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
removePerformanceCallback(callbackId) {
throw NestedAppAuthError.createUnsupportedError();
}
// #region Account APIs
/**
* Returns all the accounts in the cache that match the optional filter. If no filter is provided, all accounts are returned.
* @param accountFilter - (Optional) filter to narrow down the accounts returned
* @returns Array of AccountInfo objects in cache
*/
getAllAccounts(accountFilter) {
return getAllAccounts(this.logger, this.browserStorage, this.isBrowserEnv(), createNewGuid(), accountFilter);
}
/**
* Returns the first account found in the cache that matches the account filter passed in.
* @param accountFilter
* @returns The first account found in the cache matching the provided filter or null if no account could be found.
*/
getAccount(accountFilter) {
return getAccount(accountFilter, this.logger, this.browserStorage, createNewGuid());
}
/**
* Sets the account to use as the active account. If no account is passed to the acquireToken APIs, then MSAL will use this active account.
* @param account
*/
setActiveAccount(account) {
/*
* StandardController uses this to allow the developer to set the active account
* in the nested app auth scenario the active account is controlled by the app hosting the nested app
*/
return setActiveAccount(account, this.browserStorage, createNewGuid());
}
/**
* Gets the currently active account
*/
getActiveAccount() {
return getActiveAccount(this.browserStorage, createNewGuid());
}
// #endregion
handleRedirectPromise(options // eslint-disable-line @typescript-eslint/no-unused-vars
) {
return Promise.resolve(null);
}
loginPopup(request // eslint-disable-line @typescript-eslint/no-unused-vars
) {
return this.acquireTokenInteractive(request || DEFAULT_REQUEST);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
loginRedirect(request) {
throw NestedAppAuthError.createUnsupportedError();
}
logoutRedirect(logoutRequest // eslint-disable-line @typescript-eslint/no-unused-vars
) {
throw NestedAppAuthError.createUnsupportedError();
}
logoutPopup(logoutRequest // eslint-disable-line @typescript-eslint/no-unused-vars
) {
throw NestedAppAuthError.createUnsupportedError();
}
ssoSilent(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
request) {
return this.acquireTokenSilentInternal(request);
}
/**
* Returns the logger instance
*/
getLogger() {
return this.logger;
}
/**
* Replaces the default logger set in configurations with new Logger with new configurations
* @param logger Logger instance
*/
setLogger(logger) {
this.logger = logger;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
initializeWrapperLibrary(sku, version) {
/*
* Standard controller uses this to set the sku and version of the wrapper library in the storage
* we do nothing here
*/
return;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
setNavigationClient(navigationClient) {
this.logger.warning("1k8729", "");
}
getConfiguration() {
return this.config;
}
isBrowserEnv() {
return this.operatingContext.isBrowserEnvironment();
}
getBrowserCrypto() {
return this.browserCrypto;
}
getPerformanceClient() {
throw NestedAppAuthError.createUnsupportedError();
}
getRedirectResponse() {
throw NestedAppAuthError.createUnsupportedError();
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async clearCache(logoutRequest) {
throw NestedAppAuthError.createUnsupportedError();
}
async hydrateCache(result, request) {
this.logger.verbose("16jycr", result.correlationId);
const accountEntity = AccountEntityUtils.createAccountEntityFromAccountInfo(result.account, result.cloudGraphHostName, result.msGraphHost);
await this.browserStorage.setAccount(accountEntity, result.correlationId, AuthToken.isKmsi(result.idTokenClaims), ApiId.hydrateCache);
return this.browserStorage.hydrateCache(result, request);
}
}
export { NestedAppAuthController };
//# sourceMappingURL=NestedAppAuthController.mjs.map

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long