@azure/core-rest-pipeline
Version:
Isomorphic client library for making HTTP requests in node.js and browser.
62 lines • 3.11 kB
JavaScript
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { createTokenCycler } from "../util/tokenCycler.js";
import { logger as coreLogger } from "../log.js";
/**
* The programmatic identifier of the auxiliaryAuthenticationHeaderPolicy.
*/
export const auxiliaryAuthenticationHeaderPolicyName = "auxiliaryAuthenticationHeaderPolicy";
const AUTHORIZATION_AUXILIARY_HEADER = "x-ms-authorization-auxiliary";
async function sendAuthorizeRequest(options) {
const { scopes, getAccessToken, request } = options;
const getTokenOptions = {
abortSignal: request.abortSignal,
tracingOptions: request.tracingOptions,
};
return (await getAccessToken(scopes, getTokenOptions))?.token ?? "";
}
/**
* A policy for external tokens to `x-ms-authorization-auxiliary` header.
* This header will be used when creating a cross-tenant application we may need to handle authentication requests
* for resources that are in different tenants.
* You could see [ARM docs](https://learn.microsoft.com/azure/azure-resource-manager/management/authenticate-multi-tenant) for a rundown of how this feature works
*/
export function auxiliaryAuthenticationHeaderPolicy(options) {
const { credentials, scopes } = options;
const logger = options.logger || coreLogger;
const tokenCyclerMap = new WeakMap();
return {
name: auxiliaryAuthenticationHeaderPolicyName,
async sendRequest(request, next) {
if (!request.url.toLowerCase().startsWith("https://")) {
throw new Error("Bearer token authentication for auxiliary header is not permitted for non-TLS protected (non-https) URLs.");
}
if (!credentials || credentials.length === 0) {
logger.info(`${auxiliaryAuthenticationHeaderPolicyName} header will not be set due to empty credentials.`);
return next(request);
}
const tokenPromises = [];
for (const credential of credentials) {
let getAccessToken = tokenCyclerMap.get(credential);
if (!getAccessToken) {
getAccessToken = createTokenCycler(credential);
tokenCyclerMap.set(credential, getAccessToken);
}
tokenPromises.push(sendAuthorizeRequest({
scopes: Array.isArray(scopes) ? scopes : [scopes],
request,
getAccessToken,
logger,
}));
}
const auxiliaryTokens = (await Promise.all(tokenPromises)).filter((token) => Boolean(token));
if (auxiliaryTokens.length === 0) {
logger.warning(`None of the auxiliary tokens are valid. ${AUTHORIZATION_AUXILIARY_HEADER} header will not be set.`);
return next(request);
}
request.headers.set(AUTHORIZATION_AUXILIARY_HEADER, auxiliaryTokens.map((token) => `Bearer ${token}`).join(", "));
return next(request);
},
};
}
//# sourceMappingURL=auxiliaryAuthenticationHeaderPolicy.js.map