@azure/identity-cache-persistence 1.1.1 → 1.1.2-alpha.20240619.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-esm/identity/src/constants.js +1 -1
- package/dist-esm/identity/src/constants.js.map +1 -1
- package/dist-esm/identity/src/credentials/azurePipelinesCredential.js +35 -60
- package/dist-esm/identity/src/credentials/azurePipelinesCredential.js.map +1 -1
- package/dist-esm/identity/src/credentials/interactiveBrowserCredential.js +18 -21
- package/dist-esm/identity/src/credentials/interactiveBrowserCredential.js.map +1 -1
- package/dist-esm/identity/src/credentials/managedIdentityCredential/index.js +3 -288
- package/dist-esm/identity/src/credentials/managedIdentityCredential/index.js.map +1 -1
- package/dist-esm/identity/src/credentials/managedIdentityCredential/legacyMsiProvider.js +309 -0
- package/dist-esm/identity/src/credentials/managedIdentityCredential/legacyMsiProvider.js.map +1 -0
- package/dist-esm/identity/src/credentials/onBehalfOfCredential.js +66 -6
- package/dist-esm/identity/src/credentials/onBehalfOfCredential.js.map +1 -1
- package/dist-esm/identity/src/msal/nodeFlows/msalClient.js +135 -24
- package/dist-esm/identity/src/msal/nodeFlows/msalClient.js.map +1 -1
- package/dist-esm/identity/src/msal/nodeFlows/msalPlugins.js.map +1 -1
- package/package.json +3 -3
- package/dist-esm/identity/src/msal/nodeFlows/msalClientCertificate.js +0 -122
- package/dist-esm/identity/src/msal/nodeFlows/msalClientCertificate.js.map +0 -1
- package/dist-esm/identity/src/msal/nodeFlows/msalOnBehalfOf.js +0 -66
- package/dist-esm/identity/src/msal/nodeFlows/msalOnBehalfOf.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../identity/src/constants.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../identity/src/constants.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC;AAEnC;;;GAGG;AACH,2EAA2E;AAC3E,6CAA6C;AAC7C,uGAAuG;AACvG,MAAM,CAAC,MAAM,uBAAuB,GAAG,sCAAsC,CAAC;AAE9E;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAC;AAExC;;GAEG;AACH,MAAM,CAAN,IAAY,mBAiBX;AAjBD,WAAY,mBAAmB;IAC7B;;OAEG;IACH,oEAA6C,CAAA;IAC7C;;OAEG;IACH,wEAAiD,CAAA;IACjD;;OAEG;IACH,2EAAoD,CAAA;IACpD;;OAEG;IACH,6EAAsD,CAAA;AACxD,CAAC,EAjBW,mBAAmB,KAAnB,mBAAmB,QAiB9B;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,mBAAmB,CAAC,gBAAgB,CAAC;AAEzE;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAa,CAAC,GAAG,CAAC,CAAC;AAE3C;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAEtC;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,OAAO,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,YAAY,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/**\n * Current version of the `@azure/identity` package.\n */\nexport const SDK_VERSION = `4.3.1`;\n\n/**\n * The default client ID for authentication\n * @internal\n */\n// TODO: temporary - this is the Azure CLI clientID - we'll replace it when\n// Developer Sign On application is available\n// https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/src/Constants.cs#L9\nexport const DeveloperSignOnClientId = \"04b07795-8ddb-461a-bbee-02f9e1bf7b46\";\n\n/**\n * The default tenant for authentication\n * @internal\n */\nexport const DefaultTenantId = \"common\";\n\n/**\n * A list of known Azure authority hosts\n */\nexport enum AzureAuthorityHosts {\n /**\n * China-based Azure Authority Host\n */\n AzureChina = \"https://login.chinacloudapi.cn\",\n /**\n * Germany-based Azure Authority Host\n */\n AzureGermany = \"https://login.microsoftonline.de\",\n /**\n * US Government Azure Authority Host\n */\n AzureGovernment = \"https://login.microsoftonline.us\",\n /**\n * Public Cloud Azure Authority Host\n */\n AzurePublicCloud = \"https://login.microsoftonline.com\",\n}\n\n/**\n * @internal\n * The default authority host.\n */\nexport const DefaultAuthorityHost = AzureAuthorityHosts.AzurePublicCloud;\n\n/**\n * @internal\n * Allow acquiring tokens for any tenant for multi-tentant auth.\n */\nexport const ALL_TENANTS: string[] = [\"*\"];\n\n/**\n * @internal\n */\nexport const CACHE_CAE_SUFFIX = \"cae\";\n\n/**\n * @internal\n */\nexport const CACHE_NON_CAE_SUFFIX = \"nocae\";\n\n/**\n * @internal\n *\n * The default name for the cache persistence plugin.\n * Matches the constant defined in the cache persistence package.\n */\nexport const DEFAULT_TOKEN_CACHE_NAME = \"msal.cache\";\n"]}
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
// Licensed under the MIT license.
|
|
3
3
|
import { __awaiter } from "tslib";
|
|
4
4
|
import { ClientAssertionCredential } from "./clientAssertionCredential";
|
|
5
|
-
import { CredentialUnavailableError } from "../errors";
|
|
5
|
+
import { AuthenticationError, CredentialUnavailableError } from "../errors";
|
|
6
6
|
import { credentialLogger } from "../util/logging";
|
|
7
7
|
import { checkTenantId } from "../util/tenantIdUtils";
|
|
8
8
|
import { createHttpHeaders, createPipelineRequest } from "@azure/core-rest-pipeline";
|
|
9
9
|
import { IdentityClient } from "../client/identityClient";
|
|
10
10
|
const credentialName = "AzurePipelinesCredential";
|
|
11
11
|
const logger = credentialLogger(credentialName);
|
|
12
|
-
const OIDC_API_VERSION = "7.1
|
|
12
|
+
const OIDC_API_VERSION = "7.1";
|
|
13
13
|
/**
|
|
14
14
|
* This credential is designed to be used in Azure Pipelines with service connections
|
|
15
15
|
* as a setup for workload identity federation.
|
|
@@ -19,23 +19,23 @@ export class AzurePipelinesCredential {
|
|
|
19
19
|
* AzurePipelinesCredential supports Federated Identity on Azure Pipelines through Service Connections.
|
|
20
20
|
* @param tenantId - tenantId associated with the service connection
|
|
21
21
|
* @param clientId - clientId associated with the service connection
|
|
22
|
-
* @param serviceConnectionId -
|
|
22
|
+
* @param serviceConnectionId - Unique ID for the service connection, as found in the querystring's resourceId key
|
|
23
|
+
* @param systemAccessToken - The pipeline's <see href="https://learn.microsoft.com/azure/devops/pipelines/build/variables?view=azure-devops%26tabs=yaml#systemaccesstoken">System.AccessToken</see> value.
|
|
23
24
|
* @param options - The identity client options to use for authentication.
|
|
24
25
|
*/
|
|
25
|
-
constructor(tenantId, clientId, serviceConnectionId, options) {
|
|
26
|
-
if (!clientId || !tenantId || !serviceConnectionId) {
|
|
27
|
-
throw new CredentialUnavailableError(`${credentialName}: is unavailable. tenantId, clientId, and
|
|
26
|
+
constructor(tenantId, clientId, serviceConnectionId, systemAccessToken, options) {
|
|
27
|
+
if (!clientId || !tenantId || !serviceConnectionId || !systemAccessToken) {
|
|
28
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. tenantId, clientId, serviceConnectionId, and systemAccessToken are required parameters.`);
|
|
28
29
|
}
|
|
29
30
|
this.identityClient = new IdentityClient(options);
|
|
30
31
|
checkTenantId(logger, tenantId);
|
|
31
|
-
logger.info(`Invoking AzurePipelinesCredential with tenant ID: ${tenantId},
|
|
32
|
-
if (
|
|
33
|
-
this
|
|
34
|
-
const oidcRequestUrl = `${process.env.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI}${process.env.SYSTEM_TEAMPROJECTID}/_apis/distributedtask/hubs/build/plans/${process.env.SYSTEM_PLANID}/jobs/${process.env.SYSTEM_JOBID}/oidctoken?api-version=${OIDC_API_VERSION}&serviceConnectionId=${serviceConnectionId}`;
|
|
35
|
-
const systemAccessToken = `${process.env.SYSTEM_ACCESSTOKEN}`;
|
|
36
|
-
logger.info(`Invoking ClientAssertionCredential with tenant ID: ${tenantId}, clientId: ${clientId} and service connection id: ${serviceConnectionId}`);
|
|
37
|
-
this.clientAssertionCredential = new ClientAssertionCredential(tenantId, clientId, this.requestOidcToken.bind(this, oidcRequestUrl, systemAccessToken), options);
|
|
32
|
+
logger.info(`Invoking AzurePipelinesCredential with tenant ID: ${tenantId}, client ID: ${clientId}, and service connection ID: ${serviceConnectionId}`);
|
|
33
|
+
if (!process.env.SYSTEM_OIDCREQUESTURI) {
|
|
34
|
+
throw new CredentialUnavailableError(`${credentialName}: is unavailable. Ensure that you're running this task in an Azure Pipeline, so that following missing system variable(s) can be defined- "SYSTEM_OIDCREQUESTURI"`);
|
|
38
35
|
}
|
|
36
|
+
const oidcRequestUrl = `${process.env.SYSTEM_OIDCREQUESTURI}?api-version=${OIDC_API_VERSION}&serviceConnectionId=${serviceConnectionId}`;
|
|
37
|
+
logger.info(`Invoking ClientAssertionCredential with tenant ID: ${tenantId}, client ID: ${clientId} and service connection ID: ${serviceConnectionId}`);
|
|
38
|
+
this.clientAssertionCredential = new ClientAssertionCredential(tenantId, clientId, this.requestOidcToken.bind(this, oidcRequestUrl, systemAccessToken), options);
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
41
|
* Authenticates with Microsoft Entra ID and returns an access token if successful.
|
|
@@ -48,16 +48,13 @@ export class AzurePipelinesCredential {
|
|
|
48
48
|
getToken(scopes, options) {
|
|
49
49
|
return __awaiter(this, void 0, void 0, function* () {
|
|
50
50
|
if (!this.clientAssertionCredential) {
|
|
51
|
-
const errorMessage = `${credentialName}: is unavailable. To use Federation Identity in Azure Pipelines,
|
|
51
|
+
const errorMessage = `${credentialName}: is unavailable. To use Federation Identity in Azure Pipelines, the following parameters are required -
|
|
52
52
|
tenantId,
|
|
53
53
|
clientId,
|
|
54
54
|
serviceConnectionId,
|
|
55
|
-
|
|
56
|
-
"
|
|
57
|
-
|
|
58
|
-
"SYSTEM_JOBID" &&
|
|
59
|
-
"SYSTEM_ACCESSTOKEN"
|
|
60
|
-
See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/troubleshoot`;
|
|
55
|
+
systemAccessToken,
|
|
56
|
+
"SYSTEM_OIDCREQUESTURI".
|
|
57
|
+
See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/azurepipelinescredential/troubleshoot`;
|
|
61
58
|
logger.error(errorMessage);
|
|
62
59
|
throw new CredentialUnavailableError(errorMessage);
|
|
63
60
|
}
|
|
@@ -87,50 +84,28 @@ export class AzurePipelinesCredential {
|
|
|
87
84
|
const text = response.bodyAsText;
|
|
88
85
|
if (!text) {
|
|
89
86
|
logger.error(`${credentialName}: Authenticated Failed. Received null token from OIDC request. Response status- ${response.status}. Complete response - ${JSON.stringify(response)}`);
|
|
90
|
-
throw new
|
|
87
|
+
throw new AuthenticationError(response.status, `${credentialName}: Authenticated Failed. Received null token from OIDC request. Response status- ${response.status}. Complete response - ${JSON.stringify(response)}`);
|
|
91
88
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
89
|
+
try {
|
|
90
|
+
const result = JSON.parse(text);
|
|
91
|
+
if (result === null || result === void 0 ? void 0 : result.oidcToken) {
|
|
92
|
+
return result.oidcToken;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
let errorMessage = `${credentialName}: Authentication Failed. oidcToken field not detected in the response.`;
|
|
96
|
+
if (response.status !== 200) {
|
|
97
|
+
errorMessage += `Response = ${JSON.stringify(result)}`;
|
|
98
|
+
}
|
|
99
|
+
logger.error(errorMessage);
|
|
100
|
+
throw new AuthenticationError(response.status, errorMessage);
|
|
101
|
+
}
|
|
95
102
|
}
|
|
96
|
-
|
|
97
|
-
logger.error(
|
|
98
|
-
|
|
103
|
+
catch (e) {
|
|
104
|
+
logger.error(e.message);
|
|
105
|
+
logger.error(`${credentialName}: Authentication Failed. oidcToken field not detected in the response. Response = ${text}`);
|
|
106
|
+
throw new AuthenticationError(response.status, `${credentialName}: Authentication Failed. oidcToken field not detected in the response. Response = ${text}`);
|
|
99
107
|
}
|
|
100
108
|
});
|
|
101
109
|
}
|
|
102
|
-
/**
|
|
103
|
-
* Ensures all system env vars are there to form the request uri for OIDC token
|
|
104
|
-
* @returns void
|
|
105
|
-
* @throws CredentialUnavailableError
|
|
106
|
-
*/
|
|
107
|
-
ensurePipelinesSystemVars() {
|
|
108
|
-
if (process.env.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI &&
|
|
109
|
-
process.env.SYSTEM_TEAMPROJECTID &&
|
|
110
|
-
process.env.SYSTEM_PLANID &&
|
|
111
|
-
process.env.SYSTEM_JOBID &&
|
|
112
|
-
process.env.SYSTEM_ACCESSTOKEN) {
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
const missingEnvVars = [];
|
|
116
|
-
let errorMessage = "";
|
|
117
|
-
if (!process.env.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI) {
|
|
118
|
-
missingEnvVars.push("SYSTEM_TEAMFOUNDATIONCOLLECTIONURI");
|
|
119
|
-
}
|
|
120
|
-
if (!process.env.SYSTEM_TEAMPROJECTID)
|
|
121
|
-
missingEnvVars.push("SYSTEM_TEAMPROJECTID");
|
|
122
|
-
if (!process.env.SYSTEM_PLANID)
|
|
123
|
-
missingEnvVars.push("SYSTEM_PLANID");
|
|
124
|
-
if (!process.env.SYSTEM_JOBID)
|
|
125
|
-
missingEnvVars.push("SYSTEM_JOBID");
|
|
126
|
-
if (!process.env.SYSTEM_ACCESSTOKEN) {
|
|
127
|
-
errorMessage +=
|
|
128
|
-
"\nPlease ensure that the system access token is available in the SYSTEM_ACCESSTOKEN value; this is often most easily achieved by adding a block to the end of your pipeline yaml for the task with:\n env: \n- SYSTEM_ACCESSTOKEN: $(System.AccessToken)";
|
|
129
|
-
missingEnvVars.push("SYSTEM_ACCESSTOKEN");
|
|
130
|
-
}
|
|
131
|
-
if (missingEnvVars.length > 0) {
|
|
132
|
-
throw new CredentialUnavailableError(`${credentialName}: is unavailable. Ensure that you're running this task in an Azure Pipeline, so that following missing system variable(s) can be defined- ${missingEnvVars.join(", ")}.${errorMessage}`);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
110
|
}
|
|
136
111
|
//# sourceMappingURL=azurePipelinesCredential.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"azurePipelinesCredential.js","sourceRoot":"","sources":["../../../../../identity/src/credentials/azurePipelinesCredential.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport { ClientAssertionCredential } from \"./clientAssertionCredential\";\nimport { AuthenticationError, CredentialUnavailableError } from \"../errors\";\nimport { credentialLogger } from \"../util/logging\";\nimport { checkTenantId } from \"../util/tenantIdUtils\";\nimport { createHttpHeaders, createPipelineRequest } from \"@azure/core-rest-pipeline\";\nimport { AzurePipelinesCredentialOptions } from \"./azurePipelinesCredentialOptions\";\nimport { IdentityClient } from \"../client/identityClient\";\n\nconst credentialName = \"AzurePipelinesCredential\";\nconst logger = credentialLogger(credentialName);\nconst OIDC_API_VERSION = \"7.1-preview.1\";\n\n/**\n * This credential is designed to be used in Azure Pipelines with service connections\n * as a setup for workload identity federation.\n */\nexport class AzurePipelinesCredential implements TokenCredential {\n private clientAssertionCredential: ClientAssertionCredential | undefined;\n private identityClient: IdentityClient;\n\n /**\n * AzurePipelinesCredential supports Federated Identity on Azure Pipelines through Service Connections.\n * @param tenantId - tenantId associated with the service connection\n * @param clientId - clientId associated with the service connection\n * @param serviceConnectionId - id for the service connection, as found in the querystring's resourceId key\n * @param options - The identity client options to use for authentication.\n */\n constructor(\n tenantId: string,\n clientId: string,\n serviceConnectionId: string,\n options?: AzurePipelinesCredentialOptions,\n ) {\n if (!clientId || !tenantId || !serviceConnectionId) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. tenantId, clientId, and serviceConnectionId are required parameters.`,\n );\n }\n this.identityClient = new IdentityClient(options);\n checkTenantId(logger, tenantId);\n logger.info(\n `Invoking AzurePipelinesCredential with tenant ID: ${tenantId}, clientId: ${clientId} and service connection id: ${serviceConnectionId}`,\n );\n\n if (clientId && tenantId && serviceConnectionId) {\n this.ensurePipelinesSystemVars();\n const oidcRequestUrl = `${process.env.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI}${process.env.SYSTEM_TEAMPROJECTID}/_apis/distributedtask/hubs/build/plans/${process.env.SYSTEM_PLANID}/jobs/${process.env.SYSTEM_JOBID}/oidctoken?api-version=${OIDC_API_VERSION}&serviceConnectionId=${serviceConnectionId}`;\n const systemAccessToken = `${process.env.SYSTEM_ACCESSTOKEN}`;\n logger.info(\n `Invoking ClientAssertionCredential with tenant ID: ${tenantId}, clientId: ${clientId} and service connection id: ${serviceConnectionId}`,\n );\n this.clientAssertionCredential = new ClientAssertionCredential(\n tenantId,\n clientId,\n this.requestOidcToken.bind(this, oidcRequestUrl, systemAccessToken),\n options,\n );\n }\n }\n\n /**\n * Authenticates with Microsoft Entra ID and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} or {@link AuthenticationError} will be thrown with the details of the failure.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n public async getToken(\n scopes: string | string[],\n options?: GetTokenOptions,\n ): Promise<AccessToken> {\n if (!this.clientAssertionCredential) {\n const errorMessage = `${credentialName}: is unavailable. To use Federation Identity in Azure Pipelines, these are required as input parameters / env variables - \n tenantId,\n clientId,\n serviceConnectionId,\n \"SYSTEM_TEAMFOUNDATIONCOLLECTIONURI\" &&\n \"SYSTEM_TEAMPROJECTID\" &&\n \"SYSTEM_PLANID\" &&\n \"SYSTEM_JOBID\" &&\n \"SYSTEM_ACCESSTOKEN\"\n See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/troubleshoot`;\n logger.error(errorMessage);\n throw new CredentialUnavailableError(errorMessage);\n }\n logger.info(\"Invoking getToken() of Client Assertion Credential\");\n return this.clientAssertionCredential.getToken(scopes, options);\n }\n\n /**\n *\n * @param oidcRequestUrl - oidc request url\n * @param systemAccessToken - system access token\n * @returns OIDC token from Azure Pipelines\n */\n private async requestOidcToken(\n oidcRequestUrl: string,\n systemAccessToken: string,\n ): Promise<string> {\n logger.info(\"Requesting OIDC token from Azure Pipelines...\");\n logger.info(oidcRequestUrl);\n const request = createPipelineRequest({\n url: oidcRequestUrl,\n method: \"POST\",\n headers: createHttpHeaders({\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${systemAccessToken}`,\n }),\n });\n const response = await this.identityClient.sendRequest(request);\n const text = response.bodyAsText;\n if (!text) {\n logger.error(\n `${credentialName}: Authenticated Failed. Received null token from OIDC request. Response status- ${\n response.status\n }. Complete response - ${JSON.stringify(response)}`,\n );\n throw new CredentialUnavailableError(\n `${credentialName}: Authenticated Failed. Received null token from OIDC request. Response status- ${\n response.status\n }. Complete response - ${JSON.stringify(response)}`,\n );\n }\n const result = JSON.parse(text);\n if (result?.oidcToken) {\n return result.oidcToken;\n } else {\n logger.error(\n `${credentialName}: Authentication Failed. oidcToken field not detected in the response. Response = ${JSON.stringify(\n result,\n )}`,\n );\n throw new CredentialUnavailableError(\n `${credentialName}: Authentication Failed. oidcToken field not detected in the response. Response = ${JSON.stringify(\n result,\n )}`,\n );\n }\n }\n\n /**\n * Ensures all system env vars are there to form the request uri for OIDC token\n * @returns void\n * @throws CredentialUnavailableError\n */\n private ensurePipelinesSystemVars(): void {\n if (\n process.env.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI &&\n process.env.SYSTEM_TEAMPROJECTID &&\n process.env.SYSTEM_PLANID &&\n process.env.SYSTEM_JOBID &&\n process.env.SYSTEM_ACCESSTOKEN\n ) {\n return;\n }\n const missingEnvVars = [];\n let errorMessage = \"\";\n if (!process.env.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI) {\n missingEnvVars.push(\"SYSTEM_TEAMFOUNDATIONCOLLECTIONURI\");\n }\n if (!process.env.SYSTEM_TEAMPROJECTID) missingEnvVars.push(\"SYSTEM_TEAMPROJECTID\");\n if (!process.env.SYSTEM_PLANID) missingEnvVars.push(\"SYSTEM_PLANID\");\n if (!process.env.SYSTEM_JOBID) missingEnvVars.push(\"SYSTEM_JOBID\");\n if (!process.env.SYSTEM_ACCESSTOKEN) {\n errorMessage +=\n \"\\nPlease ensure that the system access token is available in the SYSTEM_ACCESSTOKEN value; this is often most easily achieved by adding a block to the end of your pipeline yaml for the task with:\\n env: \\n- SYSTEM_ACCESSTOKEN: $(System.AccessToken)\";\n missingEnvVars.push(\"SYSTEM_ACCESSTOKEN\");\n }\n if (missingEnvVars.length > 0) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. Ensure that you're running this task in an Azure Pipeline, so that following missing system variable(s) can be defined- ${missingEnvVars.join(\n \", \",\n )}.${errorMessage}`,\n );\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"azurePipelinesCredential.js","sourceRoot":"","sources":["../../../../../identity/src/credentials/azurePipelinesCredential.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport { ClientAssertionCredential } from \"./clientAssertionCredential\";\nimport { AuthenticationError, CredentialUnavailableError } from \"../errors\";\nimport { credentialLogger } from \"../util/logging\";\nimport { checkTenantId } from \"../util/tenantIdUtils\";\nimport { createHttpHeaders, createPipelineRequest } from \"@azure/core-rest-pipeline\";\nimport { AzurePipelinesCredentialOptions } from \"./azurePipelinesCredentialOptions\";\nimport { IdentityClient } from \"../client/identityClient\";\n\nconst credentialName = \"AzurePipelinesCredential\";\nconst logger = credentialLogger(credentialName);\nconst OIDC_API_VERSION = \"7.1\";\n\n/**\n * This credential is designed to be used in Azure Pipelines with service connections\n * as a setup for workload identity federation.\n */\nexport class AzurePipelinesCredential implements TokenCredential {\n private clientAssertionCredential: ClientAssertionCredential | undefined;\n private identityClient: IdentityClient;\n\n /**\n * AzurePipelinesCredential supports Federated Identity on Azure Pipelines through Service Connections.\n * @param tenantId - tenantId associated with the service connection\n * @param clientId - clientId associated with the service connection\n * @param serviceConnectionId - Unique ID for the service connection, as found in the querystring's resourceId key\n * @param systemAccessToken - The pipeline's <see href=\"https://learn.microsoft.com/azure/devops/pipelines/build/variables?view=azure-devops%26tabs=yaml#systemaccesstoken\">System.AccessToken</see> value.\n * @param options - The identity client options to use for authentication.\n */\n constructor(\n tenantId: string,\n clientId: string,\n serviceConnectionId: string,\n systemAccessToken: string,\n options?: AzurePipelinesCredentialOptions,\n ) {\n if (!clientId || !tenantId || !serviceConnectionId || !systemAccessToken) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. tenantId, clientId, serviceConnectionId, and systemAccessToken are required parameters.`,\n );\n }\n this.identityClient = new IdentityClient(options);\n checkTenantId(logger, tenantId);\n logger.info(\n `Invoking AzurePipelinesCredential with tenant ID: ${tenantId}, client ID: ${clientId}, and service connection ID: ${serviceConnectionId}`,\n );\n if (!process.env.SYSTEM_OIDCREQUESTURI) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. Ensure that you're running this task in an Azure Pipeline, so that following missing system variable(s) can be defined- \"SYSTEM_OIDCREQUESTURI\"`,\n );\n }\n\n const oidcRequestUrl = `${process.env.SYSTEM_OIDCREQUESTURI}?api-version=${OIDC_API_VERSION}&serviceConnectionId=${serviceConnectionId}`;\n logger.info(\n `Invoking ClientAssertionCredential with tenant ID: ${tenantId}, client ID: ${clientId} and service connection ID: ${serviceConnectionId}`,\n );\n this.clientAssertionCredential = new ClientAssertionCredential(\n tenantId,\n clientId,\n this.requestOidcToken.bind(this, oidcRequestUrl, systemAccessToken),\n options,\n );\n }\n\n /**\n * Authenticates with Microsoft Entra ID and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} or {@link AuthenticationError} will be thrown with the details of the failure.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n public async getToken(\n scopes: string | string[],\n options?: GetTokenOptions,\n ): Promise<AccessToken> {\n if (!this.clientAssertionCredential) {\n const errorMessage = `${credentialName}: is unavailable. To use Federation Identity in Azure Pipelines, the following parameters are required - \n tenantId,\n clientId,\n serviceConnectionId,\n systemAccessToken,\n \"SYSTEM_OIDCREQUESTURI\". \n See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/azurepipelinescredential/troubleshoot`;\n logger.error(errorMessage);\n throw new CredentialUnavailableError(errorMessage);\n }\n logger.info(\"Invoking getToken() of Client Assertion Credential\");\n return this.clientAssertionCredential.getToken(scopes, options);\n }\n\n /**\n *\n * @param oidcRequestUrl - oidc request url\n * @param systemAccessToken - system access token\n * @returns OIDC token from Azure Pipelines\n */\n private async requestOidcToken(\n oidcRequestUrl: string,\n systemAccessToken: string,\n ): Promise<string> {\n logger.info(\"Requesting OIDC token from Azure Pipelines...\");\n logger.info(oidcRequestUrl);\n const request = createPipelineRequest({\n url: oidcRequestUrl,\n method: \"POST\",\n headers: createHttpHeaders({\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${systemAccessToken}`,\n }),\n });\n const response = await this.identityClient.sendRequest(request);\n const text = response.bodyAsText;\n if (!text) {\n logger.error(\n `${credentialName}: Authenticated Failed. Received null token from OIDC request. Response status- ${\n response.status\n }. Complete response - ${JSON.stringify(response)}`,\n );\n throw new AuthenticationError(\n response.status,\n `${credentialName}: Authenticated Failed. Received null token from OIDC request. Response status- ${\n response.status\n }. Complete response - ${JSON.stringify(response)}`,\n );\n }\n try {\n const result = JSON.parse(text);\n if (result?.oidcToken) {\n return result.oidcToken;\n } else {\n let errorMessage = `${credentialName}: Authentication Failed. oidcToken field not detected in the response.`;\n if (response.status !== 200) {\n errorMessage += `Response = ${JSON.stringify(result)}`;\n }\n logger.error(errorMessage);\n throw new AuthenticationError(response.status, errorMessage);\n }\n } catch (e: any) {\n logger.error(e.message);\n logger.error(\n `${credentialName}: Authentication Failed. oidcToken field not detected in the response. Response = ${text}`,\n );\n throw new AuthenticationError(\n response.status,\n `${credentialName}: Authentication Failed. oidcToken field not detected in the response. Response = ${text}`,\n );\n }\n }\n}\n"]}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT license.
|
|
3
3
|
import { __awaiter } from "tslib";
|
|
4
|
-
import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, } from "../util/tenantIdUtils";
|
|
5
|
-
import { MsalOpenBrowser } from "../msal/nodeFlows/msalOpenBrowser";
|
|
4
|
+
import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, resolveTenantId, } from "../util/tenantIdUtils";
|
|
6
5
|
import { credentialLogger } from "../util/logging";
|
|
7
6
|
import { ensureScopes } from "../util/scopeUtils";
|
|
8
7
|
import { tracingClient } from "../util/tracing";
|
|
8
|
+
import { createMsalClient } from "../msal/nodeFlows/msalClient";
|
|
9
|
+
import { DeveloperSignOnClientId } from "../constants";
|
|
9
10
|
const logger = credentialLogger("InteractiveBrowserCredential");
|
|
10
11
|
/**
|
|
11
12
|
* Enables authentication to Microsoft Entra ID inside of the web browser
|
|
@@ -25,31 +26,27 @@ export class InteractiveBrowserCredential {
|
|
|
25
26
|
* @param options - Options for configuring the client which makes the authentication requests.
|
|
26
27
|
*/
|
|
27
28
|
constructor(options) {
|
|
28
|
-
var _a, _b, _c, _d;
|
|
29
|
-
|
|
30
|
-
? options.redirectUri()
|
|
31
|
-
: options.redirectUri || "http://localhost";
|
|
32
|
-
this.tenantId = options === null || options === void 0 ? void 0 : options.tenantId;
|
|
29
|
+
var _a, _b, _c, _d, _e;
|
|
30
|
+
this.tenantId = resolveTenantId(logger, options.tenantId, options.clientId);
|
|
33
31
|
this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants);
|
|
32
|
+
const msalClientOptions = Object.assign(Object.assign({}, options), { tokenCredentialOptions: options, logger });
|
|
34
33
|
const ibcNodeOptions = options;
|
|
34
|
+
this.browserCustomizationOptions = ibcNodeOptions.browserCustomizationOptions;
|
|
35
|
+
this.loginHint = ibcNodeOptions.loginHint;
|
|
35
36
|
if ((_a = ibcNodeOptions === null || ibcNodeOptions === void 0 ? void 0 : ibcNodeOptions.brokerOptions) === null || _a === void 0 ? void 0 : _a.enabled) {
|
|
36
37
|
if (!((_b = ibcNodeOptions === null || ibcNodeOptions === void 0 ? void 0 : ibcNodeOptions.brokerOptions) === null || _b === void 0 ? void 0 : _b.parentWindowHandle)) {
|
|
37
38
|
throw new Error("In order to do WAM authentication, `parentWindowHandle` under `brokerOptions` is a required parameter");
|
|
38
39
|
}
|
|
39
40
|
else {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
} }));
|
|
41
|
+
msalClientOptions.brokerOptions = {
|
|
42
|
+
enabled: true,
|
|
43
|
+
parentWindowHandle: ibcNodeOptions.brokerOptions.parentWindowHandle,
|
|
44
|
+
legacyEnableMsaPassthrough: (_c = ibcNodeOptions.brokerOptions) === null || _c === void 0 ? void 0 : _c.legacyEnableMsaPassthrough,
|
|
45
|
+
useDefaultBrokerAccount: (_d = ibcNodeOptions.brokerOptions) === null || _d === void 0 ? void 0 : _d.useDefaultBrokerAccount,
|
|
46
|
+
};
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
|
|
50
|
-
this.msalFlow = new MsalOpenBrowser(Object.assign(Object.assign({}, options), { tokenCredentialOptions: options, logger,
|
|
51
|
-
redirectUri, browserCustomizationOptions: ibcNodeOptions === null || ibcNodeOptions === void 0 ? void 0 : ibcNodeOptions.browserCustomizationOptions }));
|
|
52
|
-
}
|
|
49
|
+
this.msalClient = createMsalClient((_e = options.clientId) !== null && _e !== void 0 ? _e : DeveloperSignOnClientId, this.tenantId, msalClientOptions);
|
|
53
50
|
this.disableAutomaticAuthentication = options === null || options === void 0 ? void 0 : options.disableAutomaticAuthentication;
|
|
54
51
|
}
|
|
55
52
|
/**
|
|
@@ -69,7 +66,7 @@ export class InteractiveBrowserCredential {
|
|
|
69
66
|
return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, (newOptions) => __awaiter(this, void 0, void 0, function* () {
|
|
70
67
|
newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger);
|
|
71
68
|
const arrayScopes = ensureScopes(scopes);
|
|
72
|
-
return this.
|
|
69
|
+
return this.msalClient.getTokenByInteractiveRequest(arrayScopes, Object.assign(Object.assign({}, newOptions), { disableAutomaticAuthentication: this.disableAutomaticAuthentication, browserCustomizationOptions: this.browserCustomizationOptions, loginHint: this.loginHint }));
|
|
73
70
|
}));
|
|
74
71
|
});
|
|
75
72
|
}
|
|
@@ -90,8 +87,8 @@ export class InteractiveBrowserCredential {
|
|
|
90
87
|
return __awaiter(this, arguments, void 0, function* (scopes, options = {}) {
|
|
91
88
|
return tracingClient.withSpan(`${this.constructor.name}.authenticate`, options, (newOptions) => __awaiter(this, void 0, void 0, function* () {
|
|
92
89
|
const arrayScopes = ensureScopes(scopes);
|
|
93
|
-
yield this.
|
|
94
|
-
return this.
|
|
90
|
+
yield this.msalClient.getTokenByInteractiveRequest(arrayScopes, Object.assign(Object.assign({}, newOptions), { disableAutomaticAuthentication: false, browserCustomizationOptions: this.browserCustomizationOptions, loginHint: this.loginHint }));
|
|
91
|
+
return this.msalClient.getActiveAccount();
|
|
95
92
|
}));
|
|
96
93
|
});
|
|
97
94
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactiveBrowserCredential.js","sourceRoot":"","sources":["../../../../../identity/src/credentials/interactiveBrowserCredential.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;;AASlC,OAAO,EACL,yBAAyB,EACzB,mCAAmC,
|
|
1
|
+
{"version":3,"file":"interactiveBrowserCredential.js","sourceRoot":"","sources":["../../../../../identity/src/credentials/interactiveBrowserCredential.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/* eslint-disable @typescript-eslint/no-unused-vars */\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport {\n InteractiveBrowserCredentialInBrowserOptions,\n InteractiveBrowserCredentialNodeOptions,\n} from \"./interactiveBrowserCredentialOptions\";\nimport {\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n resolveTenantId,\n} from \"../util/tenantIdUtils\";\n\nimport { AuthenticationRecord } from \"../msal/types\";\nimport { credentialLogger } from \"../util/logging\";\nimport { ensureScopes } from \"../util/scopeUtils\";\nimport { tracingClient } from \"../util/tracing\";\nimport { MsalClient, MsalClientOptions, createMsalClient } from \"../msal/nodeFlows/msalClient\";\nimport { DeveloperSignOnClientId } from \"../constants\";\n\nconst logger = credentialLogger(\"InteractiveBrowserCredential\");\n\n/**\n * Enables authentication to Microsoft Entra ID inside of the web browser\n * using the interactive login flow.\n */\nexport class InteractiveBrowserCredential implements TokenCredential {\n private tenantId?: string;\n private additionallyAllowedTenantIds: string[];\n private msalClient: MsalClient;\n private disableAutomaticAuthentication?: boolean;\n private browserCustomizationOptions: InteractiveBrowserCredentialNodeOptions[\"browserCustomizationOptions\"];\n private loginHint?: string;\n\n /**\n * Creates an instance of InteractiveBrowserCredential with the details needed.\n *\n * This credential uses the [Authorization Code Flow](https://learn.microsoft.com/entra/identity-platform/v2-oauth2-auth-code-flow).\n * On Node.js, it will open a browser window while it listens for a redirect response from the authentication service.\n * On browsers, it authenticates via popups. The `loginStyle` optional parameter can be set to `redirect` to authenticate by redirecting the user to an Azure secure login page, which then will redirect the user back to the web application where the authentication started.\n *\n * For Node.js, if a `clientId` is provided, the Microsoft Entra application will need to be configured to have a \"Mobile and desktop applications\" redirect endpoint.\n * Follow our guide on [setting up Redirect URIs for Desktop apps that calls to web APIs](https://learn.microsoft.com/entra/identity-platform/scenario-desktop-app-registration#redirect-uris).\n *\n * @param options - Options for configuring the client which makes the authentication requests.\n */\n constructor(\n options: InteractiveBrowserCredentialNodeOptions | InteractiveBrowserCredentialInBrowserOptions,\n ) {\n this.tenantId = resolveTenantId(logger, options.tenantId, options.clientId);\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.additionallyAllowedTenants,\n );\n\n const msalClientOptions: MsalClientOptions = {\n ...options,\n tokenCredentialOptions: options,\n logger,\n };\n const ibcNodeOptions = options as InteractiveBrowserCredentialNodeOptions;\n this.browserCustomizationOptions = ibcNodeOptions.browserCustomizationOptions;\n this.loginHint = ibcNodeOptions.loginHint;\n if (ibcNodeOptions?.brokerOptions?.enabled) {\n if (!ibcNodeOptions?.brokerOptions?.parentWindowHandle) {\n throw new Error(\n \"In order to do WAM authentication, `parentWindowHandle` under `brokerOptions` is a required parameter\",\n );\n } else {\n msalClientOptions.brokerOptions = {\n enabled: true,\n parentWindowHandle: ibcNodeOptions.brokerOptions.parentWindowHandle,\n legacyEnableMsaPassthrough: ibcNodeOptions.brokerOptions?.legacyEnableMsaPassthrough,\n useDefaultBrokerAccount: ibcNodeOptions.brokerOptions?.useDefaultBrokerAccount,\n };\n }\n }\n this.msalClient = createMsalClient(\n options.clientId ?? DeveloperSignOnClientId,\n this.tenantId,\n msalClientOptions,\n );\n this.disableAutomaticAuthentication = options?.disableAutomaticAuthentication;\n }\n\n /**\n * Authenticates with Microsoft Entra ID and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.\n *\n * If the user provided the option `disableAutomaticAuthentication`,\n * once the token can't be retrieved silently,\n * this method won't attempt to request user interaction to retrieve the token.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n async getToken(scopes: string | string[], options: GetTokenOptions = {}): Promise<AccessToken> {\n return tracingClient.withSpan(\n `${this.constructor.name}.getToken`,\n options,\n async (newOptions) => {\n newOptions.tenantId = processMultiTenantRequest(\n this.tenantId,\n newOptions,\n this.additionallyAllowedTenantIds,\n logger,\n );\n\n const arrayScopes = ensureScopes(scopes);\n return this.msalClient.getTokenByInteractiveRequest(arrayScopes, {\n ...newOptions,\n disableAutomaticAuthentication: this.disableAutomaticAuthentication,\n browserCustomizationOptions: this.browserCustomizationOptions,\n loginHint: this.loginHint,\n });\n },\n );\n }\n\n /**\n * Authenticates with Microsoft Entra ID and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.\n *\n * If the token can't be retrieved silently, this method will require user interaction to retrieve the token.\n *\n * On Node.js, this credential has [Proof Key for Code Exchange (PKCE)](https://datatracker.ietf.org/doc/html/rfc7636) enabled by default.\n * PKCE is a security feature that mitigates authentication code interception attacks.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n async authenticate(\n scopes: string | string[],\n options: GetTokenOptions = {},\n ): Promise<AuthenticationRecord | undefined> {\n return tracingClient.withSpan(\n `${this.constructor.name}.authenticate`,\n options,\n async (newOptions) => {\n const arrayScopes = ensureScopes(scopes);\n await this.msalClient.getTokenByInteractiveRequest(arrayScopes, {\n ...newOptions,\n disableAutomaticAuthentication: false, // this method should always allow user interaction\n browserCustomizationOptions: this.browserCustomizationOptions,\n loginHint: this.loginHint,\n });\n return this.msalClient.getActiveAccount();\n },\n );\n }\n}\n"]}
|