Skip to content
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
99c74f7
Update auxiliary auth toke policy
MaryGao Mar 16, 2023
78884f2
Update the changelog and bump the version
MaryGao Mar 16, 2023
e43ac87
Update the test name
MaryGao Mar 16, 2023
9ad2d94
Update format
MaryGao Mar 16, 2023
e7e8e14
Update the lint fix
MaryGao Mar 16, 2023
85c52b4
Merge remote-tracking branch 'origin/main' into add-auxiliary-auth-po…
MaryGao Mar 21, 2023
97d37a6
Update sdk/core/core-rest-pipeline/src/policies/auxiliaryAuthenticati…
MaryGao Apr 6, 2023
ba32825
Merge branch 'main' into add-auxiliary-auth-policy-in-core
MaryGao Apr 6, 2023
1ed399a
Update typo issues
MaryGao Apr 6, 2023
0cf0f6f
Update the name to MultiTenantAuthenticationPolicy
MaryGao Apr 6, 2023
aee479a
Update the policy name and test cases
MaryGao Apr 6, 2023
c386660
Merge remote-tracking branch 'origin/main' into add-auxiliary-auth-po…
MaryGao Apr 12, 2023
f50ca20
Merge remote-tracking branch 'origin/main' into add-auxiliary-auth-po…
MaryGao Apr 13, 2023
51bfbae
Merge remote-tracking branch 'origin/main' into add-auxiliary-auth-po…
MaryGao Apr 17, 2023
0c14094
Merge remote-tracking branch 'origin/main' into add-auxiliary-auth-po…
MaryGao Apr 25, 2023
1bbbb24
Update the test cases and policy code
MaryGao Apr 25, 2023
c5dd52d
Update the documents for this policy
MaryGao Apr 25, 2023
ed3adc1
Update the policy name and CHANGELOG
MaryGao Apr 25, 2023
e1aad77
Update the index
MaryGao Apr 25, 2023
05150e1
Fix the linter issue
MaryGao Apr 25, 2023
08e59ac
Update the format
MaryGao Apr 25, 2023
46f9def
Merge remote-tracking branch 'origin/main' into add-auxiliary-auth-po…
MaryGao Apr 26, 2023
1d3f912
Skip header set if None of the auxiliary tokens are valid
MaryGao Apr 26, 2023
2d9c935
Update the test cases
MaryGao Apr 26, 2023
7bfe2a7
Update sdk/core/core-rest-pipeline/src/policies/auxiliaryAuthenticati…
MaryGao Apr 27, 2023
ba4c69d
Merge remote-tracking branch 'origin/main' into add-auxiliary-auth-po…
MaryGao May 6, 2023
e2e7f7f
Update sdk/core/core-rest-pipeline/src/policies/auxiliaryAuthenticati…
MaryGao May 6, 2023
8ac016e
Update sdk/core/core-rest-pipeline/src/policies/auxiliaryAuthenticati…
MaryGao May 6, 2023
2d9646a
Update sdk/core/core-rest-pipeline/src/policies/auxiliaryAuthenticati…
MaryGao May 6, 2023
6f110a6
Update sdk/core/core-rest-pipeline/src/policies/auxiliaryAuthenticati…
MaryGao May 6, 2023
2e7254e
Update format
MaryGao May 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion sdk/core/core-rest-pipeline/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Release History

## 1.10.4 (Unreleased)
## 1.11.0 (Unreleased)

### Features Added

- Add a policy `auxiliaryAuthenticationHeaderPolicy` 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. [PR #25270](https://github.com/Azure/azure-sdk-for-js/pull/25270)

### Breaking Changes

### Bugs Fixed
Expand Down
2 changes: 1 addition & 1 deletion sdk/core/core-rest-pipeline/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@azure/core-rest-pipeline",
"version": "1.10.4",
"version": "1.11.0",
"description": "Isomorphic client library for making HTTP requests in node.js and browser.",
"sdk-type": "client",
"main": "dist/index.js",
Expand Down
13 changes: 13 additions & 0 deletions sdk/core/core-rest-pipeline/review/core-rest-pipeline.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ export interface AuthorizeRequestOptions {
scopes: string[];
}

// @public
Comment thread
MaryGao marked this conversation as resolved.
export function auxiliaryAuthenticationHeaderPolicy(options: AuxiliaryAuthenticationHeaderPolicyOptions): PipelinePolicy;

// @public
export const auxiliaryAuthenticationHeaderPolicyName = "auxiliaryAuthenticationHeaderPolicy";

// @public
export interface AuxiliaryAuthenticationHeaderPolicyOptions {
credentials?: TokenCredential[];
logger?: AzureLogger;
scopes: string | string[];
}

// @public
export function bearerTokenAuthenticationPolicy(options: BearerTokenAuthenticationPolicyOptions): PipelinePolicy;

Expand Down
5 changes: 5 additions & 0 deletions sdk/core/core-rest-pipeline/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,8 @@ export {
AuthorizeRequestOnChallengeOptions,
} from "./policies/bearerTokenAuthenticationPolicy";
export { ndJsonPolicy, ndJsonPolicyName } from "./policies/ndJsonPolicy";
export {
auxiliaryAuthenticationHeaderPolicy,
AuxiliaryAuthenticationHeaderPolicyOptions,
auxiliaryAuthenticationHeaderPolicyName,
} from "./policies/auxiliaryAuthenticationHeaderPolicy";
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { GetTokenOptions, TokenCredential } from "@azure/core-auth";
import { AzureLogger } from "@azure/logger";
import { PipelineRequest, PipelineResponse, SendRequest } from "../interfaces";
import { PipelinePolicy } from "../pipeline";
import { AccessTokenGetter, createTokenCycler } from "../util/tokenCycler";
import { logger as coreLogger } from "../log";
import { AuthorizeRequestOptions } from "./bearerTokenAuthenticationPolicy";

/**
* The programmatic identifier of the auxiliaryAuthenticationHeaderPolicy.
*/
export const auxiliaryAuthenticationHeaderPolicyName = "auxiliaryAuthenticationHeaderPolicy";
const AUTHORIZATION_AUXILIARY_HEADER = "x-ms-authorization-auxiliary";

/**
* Options to configure the auxiliaryAuthenticationHeaderPolicy
*/
export interface AuxiliaryAuthenticationHeaderPolicyOptions {
/**
* TokenCredential list used to get token from auxiliary tenants and
* one credential for each tenant the client may need to access
*/
credentials?: TokenCredential[];
/**
* Scopes depend on the cloud your application runs in
*/
scopes: string | string[];
/**
* A logger can be sent for debugging purposes.
*/
logger?: AzureLogger;
}

type NullableString = string | null | undefined;

async function sendAuthorizeRequest(options: AuthorizeRequestOptions): Promise<NullableString> {
const { scopes, getAccessToken, request } = options;
const getTokenOptions: GetTokenOptions = {
abortSignal: request.abortSignal,
tracingOptions: request.tracingOptions,
};

return (await getAccessToken(scopes, getTokenOptions))?.token;
Comment thread
MaryGao marked this conversation as resolved.
Outdated
}

/**
* 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/en-us/azure/azure-resource-manager/management/authenticate-multi-tenant) for a rundown of how this feature works
*/
export function auxiliaryAuthenticationHeaderPolicy(
options: AuxiliaryAuthenticationHeaderPolicyOptions
): PipelinePolicy {
const { credentials, scopes } = options;
const logger = options.logger || coreLogger;
const tokenCyclerMap = new WeakMap<TokenCredential, AccessTokenGetter>();

return {
name: auxiliaryAuthenticationHeaderPolicyName,
async sendRequest(request: PipelineRequest, next: SendRequest): Promise<PipelineResponse> {
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(`Skip ${auxiliaryAuthenticationHeaderPolicyName} due to empty credentials`);
return next(request);
}

const tokenPromises: Promise<NullableString>[] = [];
for (const credential of credentials) {
if (!tokenCyclerMap.has(credential)) {
tokenCyclerMap.set(credential, createTokenCycler(credential));
}
tokenPromises.push(
sendAuthorizeRequest({
scopes: Array.isArray(scopes) ? scopes : [scopes],
request,
getAccessToken: tokenCyclerMap.get(credential)!,
logger,
})
);
Comment thread
MaryGao marked this conversation as resolved.
Outdated
}
const auxiliaryTokens: NullableString[] = (await Promise.all(tokenPromises)).filter((token) =>
Comment thread
MaryGao marked this conversation as resolved.
Outdated
Boolean(token)
);
if (auxiliaryTokens.length === 0) {
logger.warning(
`None of the auxiliary tokens are valid and skip to set ${AUTHORIZATION_AUXILIARY_HEADER} header`
Comment thread
MaryGao marked this conversation as resolved.
Outdated
);
return next(request);
}
request.headers.set(
AUTHORIZATION_AUXILIARY_HEADER,
auxiliaryTokens.map((token) => `Bearer ${token}`).join(", ")
);

return next(request);
},
};
}
Loading