UNPKG

@azure/msal-common

Version:
168 lines (165 loc) 8.09 kB
/*! @azure/msal-common v15.12.0 2025-08-19 */ 'use strict'; import { buildClientConfiguration } from '../config/ClientConfiguration.mjs'; import { Logger } from '../logger/Logger.mjs'; import { Constants, HeaderNames } from '../utils/Constants.mjs'; import { name, version } from '../packageMetadata.mjs'; import { CcsCredentialType } from '../account/CcsCredential.mjs'; import { buildClientInfoFromHomeAccountId } from '../account/ClientInfo.mjs'; import { addBrokerParameters, addExtraQueryParameters, addCorrelationId, instrumentBrokerParams } from '../request/RequestParameterBuilder.mjs'; import { mapToQueryString } from '../utils/UrlUtils.mjs'; import { createDiscoveredInstance } from '../authority/AuthorityFactory.mjs'; import { PerformanceEvents } from '../telemetry/performance/PerformanceEvent.mjs'; import { ThrottlingUtils } from '../network/ThrottlingUtils.mjs'; import { AuthError } from '../error/AuthError.mjs'; import { createClientAuthError } from '../error/ClientAuthError.mjs'; import { NetworkError } from '../error/NetworkError.mjs'; import { invokeAsync } from '../utils/FunctionWrappers.mjs'; import { networkError } from '../error/ClientAuthErrorCodes.mjs'; /* * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. */ /** * Base application class which will construct requests to send to and handle responses from the Microsoft STS using the authorization code flow. * @internal */ class BaseClient { constructor(configuration, performanceClient) { // 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; } /** * Creates default headers for requests to token endpoint */ createTokenRequestHeaders(ccsCred) { const headers = {}; headers[HeaderNames.CONTENT_TYPE] = Constants.URL_FORM_CONTENT_TYPE; if (!this.config.systemOptions.preventCorsPreflight && ccsCred) { switch (ccsCred.type) { case CcsCredentialType.HOME_ACCOUNT_ID: try { const clientInfo = buildClientInfoFromHomeAccountId(ccsCred.credential); headers[HeaderNames.CCS_HEADER] = `Oid:${clientInfo.uid}@${clientInfo.utid}`; } catch (e) { this.logger.verbose("Could not parse home account ID for CCS Header: " + e); } break; case CcsCredentialType.UPN: headers[HeaderNames.CCS_HEADER] = `UPN: ${ccsCred.credential}`; break; } } return headers; } /** * Http post to token endpoint * @param tokenEndpoint * @param queryString * @param headers * @param thumbprint */ async executePostToTokenEndpoint(tokenEndpoint, queryString, headers, thumbprint, correlationId, queuedEvent) { if (queuedEvent) { this.performanceClient?.addQueueMeasurement(queuedEvent, correlationId); } const response = await this.sendPostRequest(thumbprint, tokenEndpoint, { body: queryString, headers: headers }, correlationId); if (this.config.serverTelemetryManager && response.status < 500 && response.status !== 429) { // Telemetry data successfully logged by server, clear Telemetry cache this.config.serverTelemetryManager.clearTelemetryCache(); } return response; } /** * Wraps sendPostRequestAsync with necessary preflight and postflight logic * @param thumbprint - Request thumbprint for throttling * @param tokenEndpoint - Endpoint to make the POST to * @param options - Body and Headers to include on the POST request * @param correlationId - CorrelationId for telemetry */ async sendPostRequest(thumbprint, tokenEndpoint, options, correlationId) { ThrottlingUtils.preProcess(this.cacheManager, thumbprint, correlationId); let response; try { response = await invokeAsync((this.networkClient.sendPostRequestAsync.bind(this.networkClient)), PerformanceEvents.NetworkClientSendPostRequestAsync, this.logger, this.performanceClient, correlationId)(tokenEndpoint, options); const responseHeaders = response.headers || {}; this.performanceClient?.addFields({ refreshTokenSize: response.body.refresh_token?.length || 0, httpVerToken: responseHeaders[HeaderNames.X_MS_HTTP_VERSION] || "", requestId: responseHeaders[HeaderNames.X_MS_REQUEST_ID] || "", }, correlationId); } catch (e) { if (e instanceof NetworkError) { const responseHeaders = e.responseHeaders; if (responseHeaders) { this.performanceClient?.addFields({ httpVerToken: responseHeaders[HeaderNames.X_MS_HTTP_VERSION] || "", requestId: responseHeaders[HeaderNames.X_MS_REQUEST_ID] || "", contentTypeHeader: responseHeaders[HeaderNames.CONTENT_TYPE] || undefined, contentLengthHeader: responseHeaders[HeaderNames.CONTENT_LENGTH] || undefined, httpStatus: e.httpStatus, }, correlationId); } throw e.error; } if (e instanceof AuthError) { throw e; } else { throw createClientAuthError(networkError); } } ThrottlingUtils.postProcess(this.cacheManager, thumbprint, response, correlationId); return response; } /** * Updates the authority object of the client. Endpoint discovery must be completed. * @param updatedAuthority */ async updateAuthority(cloudInstanceHostname, correlationId) { this.performanceClient?.addQueueMeasurement(PerformanceEvents.UpdateTokenEndpointAuthority, correlationId); const cloudInstanceAuthorityUri = `https://${cloudInstanceHostname}/${this.authority.tenant}/`; const cloudInstanceAuthority = await createDiscoveredInstance(cloudInstanceAuthorityUri, this.networkClient, this.cacheManager, this.authority.options, this.logger, correlationId, this.performanceClient); this.authority = cloudInstanceAuthority; } /** * Creates query string for the /token request * @param request */ createTokenQueryParameters(request) { const parameters = new Map(); if (request.embeddedClientId) { addBrokerParameters(parameters, this.config.authOptions.clientId, this.config.authOptions.redirectUri); } if (request.tokenQueryParameters) { addExtraQueryParameters(parameters, request.tokenQueryParameters); } addCorrelationId(parameters, request.correlationId); instrumentBrokerParams(parameters, request.correlationId, this.performanceClient); return mapToQueryString(parameters); } } export { BaseClient }; //# sourceMappingURL=BaseClient.mjs.map