UNPKG

@azure/msal-browser

Version:
188 lines (185 loc) 8.39 kB
/*! @azure/msal-browser v4.12.0 2025-05-06 */ 'use strict'; import { RequestParameterBuilder, StringUtils, AuthenticationScheme, createClientAuthError, ClientAuthErrorCodes, TimeUtils, AuthToken, buildTenantProfile, AuthError, InteractionRequiredAuthError, ServerError, ClientAuthError, OIDC_DEFAULT_SCOPES } from '@azure/msal-common/browser'; import { isBridgeError } from '../BridgeError.mjs'; import { BridgeStatusCode } from '../BridgeStatusCode.mjs'; /* * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. */ class NestedAppAuthAdapter { constructor(clientId, clientCapabilities, crypto, logger) { this.clientId = clientId; this.clientCapabilities = clientCapabilities; this.crypto = crypto; this.logger = logger; } toNaaTokenRequest(request) { let extraParams; if (request.extraQueryParameters === undefined) { extraParams = new Map(); } else { extraParams = new Map(Object.entries(request.extraQueryParameters)); } const correlationId = request.correlationId || this.crypto.createNewGuid(); const claims = RequestParameterBuilder.addClientCapabilitiesToClaims(request.claims, this.clientCapabilities); const scopes = request.scopes || OIDC_DEFAULT_SCOPES; const tokenRequest = { platformBrokerId: request.account?.homeAccountId, clientId: this.clientId, authority: request.authority, scope: scopes.join(" "), correlationId, claims: !StringUtils.isEmptyObj(claims) ? claims : undefined, state: request.state, authenticationScheme: request.authenticationScheme || AuthenticationScheme.BEARER, extraParameters: extraParams, }; return tokenRequest; } fromNaaTokenResponse(request, response, reqTimestamp) { if (!response.token.id_token || !response.token.access_token) { throw createClientAuthError(ClientAuthErrorCodes.nullOrEmptyToken); } // Request timestamp and AuthResult expires_in are in seconds, converting to Date for AuthenticationResult const expiresOn = TimeUtils.toDateFromSeconds(reqTimestamp + (response.token.expires_in || 0)); const idTokenClaims = AuthToken.extractTokenClaims(response.token.id_token, this.crypto.base64Decode); const account = this.fromNaaAccountInfo(response.account, response.token.id_token, idTokenClaims); const scopes = response.token.scope || request.scope; const authenticationResult = { authority: response.token.authority || account.environment, uniqueId: account.localAccountId, tenantId: account.tenantId, scopes: scopes.split(" "), account, idToken: response.token.id_token, idTokenClaims, accessToken: response.token.access_token, fromCache: false, expiresOn: expiresOn, tokenType: request.authenticationScheme || AuthenticationScheme.BEARER, correlationId: request.correlationId, extExpiresOn: expiresOn, state: request.state, }; return authenticationResult; } /* * export type AccountInfo = { * homeAccountId: string; * environment: string; * tenantId: string; * username: string; * localAccountId: string; * name?: string; * idToken?: string; * idTokenClaims?: TokenClaims & { * [key: string]: * | string * | number * | string[] * | object * | undefined * | unknown; * }; * nativeAccountId?: string; * authorityType?: string; * }; */ fromNaaAccountInfo(fromAccount, idToken, idTokenClaims) { const effectiveIdTokenClaims = idTokenClaims || fromAccount.idTokenClaims; const localAccountId = fromAccount.localAccountId || effectiveIdTokenClaims?.oid || effectiveIdTokenClaims?.sub || ""; const tenantId = fromAccount.tenantId || effectiveIdTokenClaims?.tid || ""; const homeAccountId = fromAccount.homeAccountId || `${localAccountId}.${tenantId}`; const username = fromAccount.username || effectiveIdTokenClaims?.preferred_username || ""; const name = fromAccount.name || effectiveIdTokenClaims?.name; const tenantProfiles = new Map(); const tenantProfile = buildTenantProfile(homeAccountId, localAccountId, tenantId, effectiveIdTokenClaims); tenantProfiles.set(tenantId, tenantProfile); const account = { homeAccountId, environment: fromAccount.environment, tenantId, username, localAccountId, name, idToken: idToken, idTokenClaims: effectiveIdTokenClaims, tenantProfiles, }; return account; } /** * * @param error BridgeError * @returns AuthError, ClientAuthError, ClientConfigurationError, ServerError, InteractionRequiredError */ fromBridgeError(error) { if (isBridgeError(error)) { switch (error.status) { case BridgeStatusCode.UserCancel: return new ClientAuthError(ClientAuthErrorCodes.userCanceled); case BridgeStatusCode.NoNetwork: return new ClientAuthError(ClientAuthErrorCodes.noNetworkConnectivity); case BridgeStatusCode.AccountUnavailable: return new ClientAuthError(ClientAuthErrorCodes.noAccountFound); case BridgeStatusCode.Disabled: return new ClientAuthError(ClientAuthErrorCodes.nestedAppAuthBridgeDisabled); case BridgeStatusCode.NestedAppAuthUnavailable: return new ClientAuthError(error.code || ClientAuthErrorCodes.nestedAppAuthBridgeDisabled, error.description); case BridgeStatusCode.TransientError: case BridgeStatusCode.PersistentError: return new ServerError(error.code, error.description); case BridgeStatusCode.UserInteractionRequired: return new InteractionRequiredAuthError(error.code, error.description); default: return new AuthError(error.code, error.description); } } else { return new AuthError("unknown_error", "An unknown error occurred"); } } /** * Returns an AuthenticationResult from the given cache items * * @param account * @param idToken * @param accessToken * @param reqTimestamp * @returns */ toAuthenticationResultFromCache(account, idToken, accessToken, request, correlationId) { if (!idToken || !accessToken) { throw createClientAuthError(ClientAuthErrorCodes.nullOrEmptyToken); } const idTokenClaims = AuthToken.extractTokenClaims(idToken.secret, this.crypto.base64Decode); const scopes = accessToken.target || request.scopes.join(" "); const authenticationResult = { authority: accessToken.environment || account.environment, uniqueId: account.localAccountId, tenantId: account.tenantId, scopes: scopes.split(" "), account, idToken: idToken.secret, idTokenClaims: idTokenClaims || {}, accessToken: accessToken.secret, fromCache: true, expiresOn: TimeUtils.toDateFromSeconds(accessToken.expiresOn), extExpiresOn: TimeUtils.toDateFromSeconds(accessToken.extendedExpiresOn), tokenType: request.authenticationScheme || AuthenticationScheme.BEARER, correlationId, state: request.state, }; return authenticationResult; } } export { NestedAppAuthAdapter }; //# sourceMappingURL=NestedAppAuthAdapter.mjs.map