@azure/identity-cache-persistence 1.1.2-alpha.20241112.1 → 1.1.2-alpha.20241113.2
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/index.js.map +1 -1
- package/dist-esm/src/index.js.map +1 -0
- package/dist-esm/src/platforms.js.map +1 -0
- package/dist-esm/src/provider.js.map +1 -0
- package/package.json +3 -4
- package/dist-esm/identity/src/client/identityClient.js +0 -257
- package/dist-esm/identity/src/client/identityClient.js.map +0 -1
- package/dist-esm/identity/src/constants.js +0 -70
- package/dist-esm/identity/src/constants.js.map +0 -1
- package/dist-esm/identity/src/credentials/authorityValidationOptions.js +0 -4
- package/dist-esm/identity/src/credentials/authorityValidationOptions.js.map +0 -1
- package/dist-esm/identity/src/credentials/authorizationCodeCredential.js +0 -63
- package/dist-esm/identity/src/credentials/authorizationCodeCredential.js.map +0 -1
- package/dist-esm/identity/src/credentials/authorizationCodeCredentialOptions.js +0 -4
- package/dist-esm/identity/src/credentials/authorizationCodeCredentialOptions.js.map +0 -1
- package/dist-esm/identity/src/credentials/azureCliCredential.js +0 -194
- package/dist-esm/identity/src/credentials/azureCliCredential.js.map +0 -1
- package/dist-esm/identity/src/credentials/azureCliCredentialOptions.js +0 -4
- package/dist-esm/identity/src/credentials/azureCliCredentialOptions.js.map +0 -1
- package/dist-esm/identity/src/credentials/azureDeveloperCliCredential.js +0 -176
- package/dist-esm/identity/src/credentials/azureDeveloperCliCredential.js.map +0 -1
- package/dist-esm/identity/src/credentials/azureDeveloperCliCredentialOptions.js +0 -4
- package/dist-esm/identity/src/credentials/azureDeveloperCliCredentialOptions.js.map +0 -1
- package/dist-esm/identity/src/credentials/azurePipelinesCredential.js +0 -146
- package/dist-esm/identity/src/credentials/azurePipelinesCredential.js.map +0 -1
- package/dist-esm/identity/src/credentials/azurePipelinesCredentialOptions.js +0 -4
- package/dist-esm/identity/src/credentials/azurePipelinesCredentialOptions.js.map +0 -1
- package/dist-esm/identity/src/credentials/azurePowerShellCredential.js +0 -238
- package/dist-esm/identity/src/credentials/azurePowerShellCredential.js.map +0 -1
- package/dist-esm/identity/src/credentials/azurePowerShellCredentialOptions.js +0 -4
- package/dist-esm/identity/src/credentials/azurePowerShellCredentialOptions.js.map +0 -1
- package/dist-esm/identity/src/credentials/brokerAuthOptions.js +0 -2
- package/dist-esm/identity/src/credentials/brokerAuthOptions.js.map +0 -1
- package/dist-esm/identity/src/credentials/browserCustomizationOptions.js +0 -4
- package/dist-esm/identity/src/credentials/browserCustomizationOptions.js.map +0 -1
- package/dist-esm/identity/src/credentials/chainedTokenCredential.js +0 -95
- package/dist-esm/identity/src/credentials/chainedTokenCredential.js.map +0 -1
- package/dist-esm/identity/src/credentials/clientAssertionCredential.js +0 -58
- package/dist-esm/identity/src/credentials/clientAssertionCredential.js.map +0 -1
- package/dist-esm/identity/src/credentials/clientAssertionCredentialOptions.js +0 -4
- package/dist-esm/identity/src/credentials/clientAssertionCredentialOptions.js.map +0 -1
- package/dist-esm/identity/src/credentials/clientCertificateCredential.js +0 -126
- package/dist-esm/identity/src/credentials/clientCertificateCredential.js.map +0 -1
- package/dist-esm/identity/src/credentials/clientCertificateCredentialOptions.js +0 -4
- package/dist-esm/identity/src/credentials/clientCertificateCredentialOptions.js.map +0 -1
- package/dist-esm/identity/src/credentials/clientSecretCredential.js +0 -63
- package/dist-esm/identity/src/credentials/clientSecretCredential.js.map +0 -1
- package/dist-esm/identity/src/credentials/clientSecretCredentialOptions.js +0 -4
- package/dist-esm/identity/src/credentials/clientSecretCredentialOptions.js.map +0 -1
- package/dist-esm/identity/src/credentials/credentialPersistenceOptions.js +0 -4
- package/dist-esm/identity/src/credentials/credentialPersistenceOptions.js.map +0 -1
- package/dist-esm/identity/src/credentials/defaultAzureCredential.js +0 -164
- package/dist-esm/identity/src/credentials/defaultAzureCredential.js.map +0 -1
- package/dist-esm/identity/src/credentials/defaultAzureCredentialOptions.js +0 -4
- package/dist-esm/identity/src/credentials/defaultAzureCredentialOptions.js.map +0 -1
- package/dist-esm/identity/src/credentials/deviceCodeCredential.js +0 -96
- package/dist-esm/identity/src/credentials/deviceCodeCredential.js.map +0 -1
- package/dist-esm/identity/src/credentials/deviceCodeCredentialOptions.js +0 -4
- package/dist-esm/identity/src/credentials/deviceCodeCredentialOptions.js.map +0 -1
- package/dist-esm/identity/src/credentials/environmentCredential.js +0 -133
- package/dist-esm/identity/src/credentials/environmentCredential.js.map +0 -1
- package/dist-esm/identity/src/credentials/environmentCredentialOptions.js +0 -4
- package/dist-esm/identity/src/credentials/environmentCredentialOptions.js.map +0 -1
- package/dist-esm/identity/src/credentials/interactiveBrowserCredential.js +0 -96
- package/dist-esm/identity/src/credentials/interactiveBrowserCredential.js.map +0 -1
- package/dist-esm/identity/src/credentials/interactiveBrowserCredentialOptions.js +0 -4
- package/dist-esm/identity/src/credentials/interactiveBrowserCredentialOptions.js.map +0 -1
- package/dist-esm/identity/src/credentials/interactiveCredentialOptions.js +0 -4
- package/dist-esm/identity/src/credentials/interactiveCredentialOptions.js.map +0 -1
- package/dist-esm/identity/src/credentials/managedIdentityCredential/imdsMsi.js +0 -125
- package/dist-esm/identity/src/credentials/managedIdentityCredential/imdsMsi.js.map +0 -1
- package/dist-esm/identity/src/credentials/managedIdentityCredential/imdsRetryPolicy.js +0 -33
- package/dist-esm/identity/src/credentials/managedIdentityCredential/imdsRetryPolicy.js.map +0 -1
- package/dist-esm/identity/src/credentials/managedIdentityCredential/index.js +0 -220
- package/dist-esm/identity/src/credentials/managedIdentityCredential/index.js.map +0 -1
- package/dist-esm/identity/src/credentials/managedIdentityCredential/models.js +0 -4
- package/dist-esm/identity/src/credentials/managedIdentityCredential/models.js.map +0 -1
- package/dist-esm/identity/src/credentials/managedIdentityCredential/tokenExchangeMsi.js +0 -37
- package/dist-esm/identity/src/credentials/managedIdentityCredential/tokenExchangeMsi.js.map +0 -1
- package/dist-esm/identity/src/credentials/managedIdentityCredential/utils.js +0 -77
- package/dist-esm/identity/src/credentials/managedIdentityCredential/utils.js.map +0 -1
- package/dist-esm/identity/src/credentials/multiTenantTokenCredentialOptions.js +0 -4
- package/dist-esm/identity/src/credentials/multiTenantTokenCredentialOptions.js.map +0 -1
- package/dist-esm/identity/src/credentials/onBehalfOfCredential.js +0 -119
- package/dist-esm/identity/src/credentials/onBehalfOfCredential.js.map +0 -1
- package/dist-esm/identity/src/credentials/onBehalfOfCredentialOptions.js +0 -4
- package/dist-esm/identity/src/credentials/onBehalfOfCredentialOptions.js.map +0 -1
- package/dist-esm/identity/src/credentials/usernamePasswordCredential.js +0 -70
- package/dist-esm/identity/src/credentials/usernamePasswordCredential.js.map +0 -1
- package/dist-esm/identity/src/credentials/usernamePasswordCredentialOptions.js +0 -4
- package/dist-esm/identity/src/credentials/usernamePasswordCredentialOptions.js.map +0 -1
- package/dist-esm/identity/src/credentials/visualStudioCodeCredential.js +0 -195
- package/dist-esm/identity/src/credentials/visualStudioCodeCredential.js.map +0 -1
- package/dist-esm/identity/src/credentials/visualStudioCodeCredentialOptions.js +0 -4
- package/dist-esm/identity/src/credentials/visualStudioCodeCredentialOptions.js.map +0 -1
- package/dist-esm/identity/src/credentials/visualStudioCodeCredentialPlugin.js +0 -4
- package/dist-esm/identity/src/credentials/visualStudioCodeCredentialPlugin.js.map +0 -1
- package/dist-esm/identity/src/credentials/workloadIdentityCredential.js +0 -119
- package/dist-esm/identity/src/credentials/workloadIdentityCredential.js.map +0 -1
- package/dist-esm/identity/src/credentials/workloadIdentityCredentialOptions.js +0 -4
- package/dist-esm/identity/src/credentials/workloadIdentityCredentialOptions.js.map +0 -1
- package/dist-esm/identity/src/errors.js +0 -123
- package/dist-esm/identity/src/errors.js.map +0 -1
- package/dist-esm/identity/src/index.js +0 -34
- package/dist-esm/identity/src/index.js.map +0 -1
- package/dist-esm/identity/src/msal/msal.js +0 -5
- package/dist-esm/identity/src/msal/msal.js.map +0 -1
- package/dist-esm/identity/src/msal/nodeFlows/brokerOptions.js +0 -2
- package/dist-esm/identity/src/msal/nodeFlows/brokerOptions.js.map +0 -1
- package/dist-esm/identity/src/msal/nodeFlows/msalClient.js +0 -511
- package/dist-esm/identity/src/msal/nodeFlows/msalClient.js.map +0 -1
- package/dist-esm/identity/src/msal/nodeFlows/msalPlugins.js +0 -87
- package/dist-esm/identity/src/msal/nodeFlows/msalPlugins.js.map +0 -1
- package/dist-esm/identity/src/msal/nodeFlows/tokenCachePersistenceOptions.js +0 -4
- package/dist-esm/identity/src/msal/nodeFlows/tokenCachePersistenceOptions.js.map +0 -1
- package/dist-esm/identity/src/msal/types.js +0 -4
- package/dist-esm/identity/src/msal/types.js.map +0 -1
- package/dist-esm/identity/src/msal/utils.js +0 -232
- package/dist-esm/identity/src/msal/utils.js.map +0 -1
- package/dist-esm/identity/src/plugins/consumer.js +0 -43
- package/dist-esm/identity/src/plugins/consumer.js.map +0 -1
- package/dist-esm/identity/src/plugins/provider.js +0 -4
- package/dist-esm/identity/src/plugins/provider.js.map +0 -1
- package/dist-esm/identity/src/regionalAuthority.js +0 -140
- package/dist-esm/identity/src/regionalAuthority.js.map +0 -1
- package/dist-esm/identity/src/tokenCredentialOptions.js +0 -4
- package/dist-esm/identity/src/tokenCredentialOptions.js.map +0 -1
- package/dist-esm/identity/src/tokenProvider.js +0 -55
- package/dist-esm/identity/src/tokenProvider.js.map +0 -1
- package/dist-esm/identity/src/util/identityTokenEndpoint.js +0 -11
- package/dist-esm/identity/src/util/identityTokenEndpoint.js.map +0 -1
- package/dist-esm/identity/src/util/logging.js +0 -94
- package/dist-esm/identity/src/util/logging.js.map +0 -1
- package/dist-esm/identity/src/util/processMultiTenantRequest.js +0 -35
- package/dist-esm/identity/src/util/processMultiTenantRequest.js.map +0 -1
- package/dist-esm/identity/src/util/processUtils.js +0 -32
- package/dist-esm/identity/src/util/processUtils.js.map +0 -1
- package/dist-esm/identity/src/util/scopeUtils.js +0 -29
- package/dist-esm/identity/src/util/scopeUtils.js.map +0 -1
- package/dist-esm/identity/src/util/subscriptionUtils.js +0 -14
- package/dist-esm/identity/src/util/subscriptionUtils.js.map +0 -1
- package/dist-esm/identity/src/util/tenantIdUtils.js +0 -44
- package/dist-esm/identity/src/util/tenantIdUtils.js.map +0 -1
- package/dist-esm/identity/src/util/tracing.js +0 -14
- package/dist-esm/identity/src/util/tracing.js.map +0 -1
- package/dist-esm/identity-cache-persistence/src/index.js.map +0 -1
- package/dist-esm/identity-cache-persistence/src/platforms.js.map +0 -1
- package/dist-esm/identity-cache-persistence/src/provider.js.map +0 -1
- /package/dist-esm/{identity-cache-persistence/src → src}/index.js +0 -0
- /package/dist-esm/{identity-cache-persistence/src → src}/platforms.js +0 -0
- /package/dist-esm/{identity-cache-persistence/src → src}/provider.js +0 -0
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Microsoft Corporation.
|
|
2
|
-
// Licensed under the MIT License.
|
|
3
|
-
import { __awaiter } from "tslib";
|
|
4
|
-
import { checkTenantId, processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, } from "../util/tenantIdUtils";
|
|
5
|
-
import { credentialLogger, formatError, formatSuccess } from "../util/logging";
|
|
6
|
-
import { ensureValidScopeForDevTimeCreds, getScopeResource } from "../util/scopeUtils";
|
|
7
|
-
import { CredentialUnavailableError } from "../errors";
|
|
8
|
-
import child_process from "child_process";
|
|
9
|
-
import { tracingClient } from "../util/tracing";
|
|
10
|
-
import { checkSubscription } from "../util/subscriptionUtils";
|
|
11
|
-
/**
|
|
12
|
-
* Mockable reference to the CLI credential cliCredentialFunctions
|
|
13
|
-
* @internal
|
|
14
|
-
*/
|
|
15
|
-
export const cliCredentialInternals = {
|
|
16
|
-
/**
|
|
17
|
-
* @internal
|
|
18
|
-
*/
|
|
19
|
-
getSafeWorkingDir() {
|
|
20
|
-
if (process.platform === "win32") {
|
|
21
|
-
if (!process.env.SystemRoot) {
|
|
22
|
-
throw new Error("Azure CLI credential expects a 'SystemRoot' environment variable");
|
|
23
|
-
}
|
|
24
|
-
return process.env.SystemRoot;
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
return "/bin";
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
/**
|
|
31
|
-
* Gets the access token from Azure CLI
|
|
32
|
-
* @param resource - The resource to use when getting the token
|
|
33
|
-
* @internal
|
|
34
|
-
*/
|
|
35
|
-
getAzureCliAccessToken(resource, tenantId, subscription, timeout) {
|
|
36
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
-
let tenantSection = [];
|
|
38
|
-
let subscriptionSection = [];
|
|
39
|
-
if (tenantId) {
|
|
40
|
-
tenantSection = ["--tenant", tenantId];
|
|
41
|
-
}
|
|
42
|
-
if (subscription) {
|
|
43
|
-
// Add quotes around the subscription to handle subscriptions with spaces
|
|
44
|
-
subscriptionSection = ["--subscription", `"${subscription}"`];
|
|
45
|
-
}
|
|
46
|
-
return new Promise((resolve, reject) => {
|
|
47
|
-
try {
|
|
48
|
-
child_process.execFile("az", [
|
|
49
|
-
"account",
|
|
50
|
-
"get-access-token",
|
|
51
|
-
"--output",
|
|
52
|
-
"json",
|
|
53
|
-
"--resource",
|
|
54
|
-
resource,
|
|
55
|
-
...tenantSection,
|
|
56
|
-
...subscriptionSection,
|
|
57
|
-
], { cwd: cliCredentialInternals.getSafeWorkingDir(), shell: true, timeout }, (error, stdout, stderr) => {
|
|
58
|
-
resolve({ stdout: stdout, stderr: stderr, error });
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
catch (err) {
|
|
62
|
-
reject(err);
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
const logger = credentialLogger("AzureCliCredential");
|
|
69
|
-
/**
|
|
70
|
-
* This credential will use the currently logged-in user login information
|
|
71
|
-
* via the Azure CLI ('az') commandline tool.
|
|
72
|
-
* To do so, it will read the user access token and expire time
|
|
73
|
-
* with Azure CLI command "az account get-access-token".
|
|
74
|
-
*/
|
|
75
|
-
export class AzureCliCredential {
|
|
76
|
-
/**
|
|
77
|
-
* Creates an instance of the {@link AzureCliCredential}.
|
|
78
|
-
*
|
|
79
|
-
* To use this credential, ensure that you have already logged
|
|
80
|
-
* in via the 'az' tool using the command "az login" from the commandline.
|
|
81
|
-
*
|
|
82
|
-
* @param options - Options, to optionally allow multi-tenant requests.
|
|
83
|
-
*/
|
|
84
|
-
constructor(options) {
|
|
85
|
-
if (options === null || options === void 0 ? void 0 : options.tenantId) {
|
|
86
|
-
checkTenantId(logger, options === null || options === void 0 ? void 0 : options.tenantId);
|
|
87
|
-
this.tenantId = options === null || options === void 0 ? void 0 : options.tenantId;
|
|
88
|
-
}
|
|
89
|
-
if (options === null || options === void 0 ? void 0 : options.subscription) {
|
|
90
|
-
checkSubscription(logger, options === null || options === void 0 ? void 0 : options.subscription);
|
|
91
|
-
this.subscription = options === null || options === void 0 ? void 0 : options.subscription;
|
|
92
|
-
}
|
|
93
|
-
this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants);
|
|
94
|
-
this.timeout = options === null || options === void 0 ? void 0 : options.processTimeoutInMs;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Authenticates with Microsoft Entra ID and returns an access token if successful.
|
|
98
|
-
* If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.
|
|
99
|
-
*
|
|
100
|
-
* @param scopes - The list of scopes for which the token will have access.
|
|
101
|
-
* @param options - The options used to configure any requests this
|
|
102
|
-
* TokenCredential implementation might make.
|
|
103
|
-
*/
|
|
104
|
-
getToken(scopes_1) {
|
|
105
|
-
return __awaiter(this, arguments, void 0, function* (scopes, options = {}) {
|
|
106
|
-
const tenantId = processMultiTenantRequest(this.tenantId, options, this.additionallyAllowedTenantIds);
|
|
107
|
-
if (tenantId) {
|
|
108
|
-
checkTenantId(logger, tenantId);
|
|
109
|
-
}
|
|
110
|
-
if (this.subscription) {
|
|
111
|
-
checkSubscription(logger, this.subscription);
|
|
112
|
-
}
|
|
113
|
-
const scope = typeof scopes === "string" ? scopes : scopes[0];
|
|
114
|
-
logger.getToken.info(`Using the scope ${scope}`);
|
|
115
|
-
return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, () => __awaiter(this, void 0, void 0, function* () {
|
|
116
|
-
var _a, _b, _c, _d;
|
|
117
|
-
try {
|
|
118
|
-
ensureValidScopeForDevTimeCreds(scope, logger);
|
|
119
|
-
const resource = getScopeResource(scope);
|
|
120
|
-
const obj = yield cliCredentialInternals.getAzureCliAccessToken(resource, tenantId, this.subscription, this.timeout);
|
|
121
|
-
const specificScope = (_a = obj.stderr) === null || _a === void 0 ? void 0 : _a.match("(.*)az login --scope(.*)");
|
|
122
|
-
const isLoginError = ((_b = obj.stderr) === null || _b === void 0 ? void 0 : _b.match("(.*)az login(.*)")) && !specificScope;
|
|
123
|
-
const isNotInstallError = ((_c = obj.stderr) === null || _c === void 0 ? void 0 : _c.match("az:(.*)not found")) || ((_d = obj.stderr) === null || _d === void 0 ? void 0 : _d.startsWith("'az' is not recognized"));
|
|
124
|
-
if (isNotInstallError) {
|
|
125
|
-
const error = new CredentialUnavailableError("Azure CLI could not be found. Please visit https://aka.ms/azure-cli for installation instructions and then, once installed, authenticate to your Azure account using 'az login'.");
|
|
126
|
-
logger.getToken.info(formatError(scopes, error));
|
|
127
|
-
throw error;
|
|
128
|
-
}
|
|
129
|
-
if (isLoginError) {
|
|
130
|
-
const error = new CredentialUnavailableError("Please run 'az login' from a command prompt to authenticate before using this credential.");
|
|
131
|
-
logger.getToken.info(formatError(scopes, error));
|
|
132
|
-
throw error;
|
|
133
|
-
}
|
|
134
|
-
try {
|
|
135
|
-
const responseData = obj.stdout;
|
|
136
|
-
const response = this.parseRawResponse(responseData);
|
|
137
|
-
logger.getToken.info(formatSuccess(scopes));
|
|
138
|
-
return response;
|
|
139
|
-
}
|
|
140
|
-
catch (e) {
|
|
141
|
-
if (obj.stderr) {
|
|
142
|
-
throw new CredentialUnavailableError(obj.stderr);
|
|
143
|
-
}
|
|
144
|
-
throw e;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
catch (err) {
|
|
148
|
-
const error = err.name === "CredentialUnavailableError"
|
|
149
|
-
? err
|
|
150
|
-
: new CredentialUnavailableError(err.message || "Unknown error while trying to retrieve the access token");
|
|
151
|
-
logger.getToken.info(formatError(scopes, error));
|
|
152
|
-
throw error;
|
|
153
|
-
}
|
|
154
|
-
}));
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Parses the raw JSON response from the Azure CLI into a usable AccessToken object
|
|
159
|
-
*
|
|
160
|
-
* @param rawResponse - The raw JSON response from the Azure CLI
|
|
161
|
-
* @returns An access token with the expiry time parsed from the raw response
|
|
162
|
-
*
|
|
163
|
-
* The expiryTime of the credential's access token, in milliseconds, is calculated as follows:
|
|
164
|
-
*
|
|
165
|
-
* When available, expires_on (introduced in Azure CLI v2.54.0) will be preferred. Otherwise falls back to expiresOn.
|
|
166
|
-
*/
|
|
167
|
-
parseRawResponse(rawResponse) {
|
|
168
|
-
const response = JSON.parse(rawResponse);
|
|
169
|
-
const token = response.accessToken;
|
|
170
|
-
// if available, expires_on will be a number representing seconds since epoch.
|
|
171
|
-
// ensure it's a number or NaN
|
|
172
|
-
let expiresOnTimestamp = Number.parseInt(response.expires_on, 10) * 1000;
|
|
173
|
-
if (!isNaN(expiresOnTimestamp)) {
|
|
174
|
-
logger.getToken.info("expires_on is available and is valid, using it");
|
|
175
|
-
return {
|
|
176
|
-
token,
|
|
177
|
-
expiresOnTimestamp,
|
|
178
|
-
tokenType: "Bearer",
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
// fallback to the older expiresOn - an RFC3339 date string
|
|
182
|
-
expiresOnTimestamp = new Date(response.expiresOn).getTime();
|
|
183
|
-
// ensure expiresOn is well-formatted
|
|
184
|
-
if (isNaN(expiresOnTimestamp)) {
|
|
185
|
-
throw new CredentialUnavailableError(`Unexpected response from Azure CLI when getting token. Expected "expiresOn" to be a RFC3339 date string. Got: "${response.expiresOn}"`);
|
|
186
|
-
}
|
|
187
|
-
return {
|
|
188
|
-
token,
|
|
189
|
-
expiresOnTimestamp,
|
|
190
|
-
tokenType: "Bearer",
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
//# sourceMappingURL=azureCliCredential.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"azureCliCredential.js","sourceRoot":"","sources":["../../../../../identity/src/credentials/azureCliCredential.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport {\n checkTenantId,\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n} from \"../util/tenantIdUtils\";\nimport { credentialLogger, formatError, formatSuccess } from \"../util/logging\";\nimport { ensureValidScopeForDevTimeCreds, getScopeResource } from \"../util/scopeUtils\";\n\nimport type { AzureCliCredentialOptions } from \"./azureCliCredentialOptions\";\nimport { CredentialUnavailableError } from \"../errors\";\nimport child_process from \"child_process\";\nimport { tracingClient } from \"../util/tracing\";\nimport { checkSubscription } from \"../util/subscriptionUtils\";\n\n/**\n * Mockable reference to the CLI credential cliCredentialFunctions\n * @internal\n */\nexport const cliCredentialInternals = {\n /**\n * @internal\n */\n getSafeWorkingDir(): string {\n if (process.platform === \"win32\") {\n if (!process.env.SystemRoot) {\n throw new Error(\"Azure CLI credential expects a 'SystemRoot' environment variable\");\n }\n return process.env.SystemRoot;\n } else {\n return \"/bin\";\n }\n },\n\n /**\n * Gets the access token from Azure CLI\n * @param resource - The resource to use when getting the token\n * @internal\n */\n async getAzureCliAccessToken(\n resource: string,\n tenantId?: string,\n subscription?: string,\n timeout?: number,\n ): Promise<{ stdout: string; stderr: string; error: Error | null }> {\n let tenantSection: string[] = [];\n let subscriptionSection: string[] = [];\n if (tenantId) {\n tenantSection = [\"--tenant\", tenantId];\n }\n if (subscription) {\n // Add quotes around the subscription to handle subscriptions with spaces\n subscriptionSection = [\"--subscription\", `\"${subscription}\"`];\n }\n return new Promise((resolve, reject) => {\n try {\n child_process.execFile(\n \"az\",\n [\n \"account\",\n \"get-access-token\",\n \"--output\",\n \"json\",\n \"--resource\",\n resource,\n ...tenantSection,\n ...subscriptionSection,\n ],\n { cwd: cliCredentialInternals.getSafeWorkingDir(), shell: true, timeout },\n (error, stdout, stderr) => {\n resolve({ stdout: stdout, stderr: stderr, error });\n },\n );\n } catch (err: any) {\n reject(err);\n }\n });\n },\n};\n\nconst logger = credentialLogger(\"AzureCliCredential\");\n\n/**\n * This credential will use the currently logged-in user login information\n * via the Azure CLI ('az') commandline tool.\n * To do so, it will read the user access token and expire time\n * with Azure CLI command \"az account get-access-token\".\n */\nexport class AzureCliCredential implements TokenCredential {\n private tenantId?: string;\n private additionallyAllowedTenantIds: string[];\n private timeout?: number;\n private subscription?: string;\n\n /**\n * Creates an instance of the {@link AzureCliCredential}.\n *\n * To use this credential, ensure that you have already logged\n * in via the 'az' tool using the command \"az login\" from the commandline.\n *\n * @param options - Options, to optionally allow multi-tenant requests.\n */\n constructor(options?: AzureCliCredentialOptions) {\n if (options?.tenantId) {\n checkTenantId(logger, options?.tenantId);\n this.tenantId = options?.tenantId;\n }\n if (options?.subscription) {\n checkSubscription(logger, options?.subscription);\n this.subscription = options?.subscription;\n }\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.additionallyAllowedTenants,\n );\n this.timeout = options?.processTimeoutInMs;\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 * @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 const tenantId = processMultiTenantRequest(\n this.tenantId,\n options,\n this.additionallyAllowedTenantIds,\n );\n if (tenantId) {\n checkTenantId(logger, tenantId);\n }\n if (this.subscription) {\n checkSubscription(logger, this.subscription);\n }\n const scope = typeof scopes === \"string\" ? scopes : scopes[0];\n logger.getToken.info(`Using the scope ${scope}`);\n\n return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async () => {\n try {\n ensureValidScopeForDevTimeCreds(scope, logger);\n const resource = getScopeResource(scope);\n const obj = await cliCredentialInternals.getAzureCliAccessToken(\n resource,\n tenantId,\n this.subscription,\n this.timeout,\n );\n const specificScope = obj.stderr?.match(\"(.*)az login --scope(.*)\");\n const isLoginError = obj.stderr?.match(\"(.*)az login(.*)\") && !specificScope;\n const isNotInstallError =\n obj.stderr?.match(\"az:(.*)not found\") || obj.stderr?.startsWith(\"'az' is not recognized\");\n\n if (isNotInstallError) {\n const error = new CredentialUnavailableError(\n \"Azure CLI could not be found. Please visit https://aka.ms/azure-cli for installation instructions and then, once installed, authenticate to your Azure account using 'az login'.\",\n );\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n if (isLoginError) {\n const error = new CredentialUnavailableError(\n \"Please run 'az login' from a command prompt to authenticate before using this credential.\",\n );\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n try {\n const responseData = obj.stdout;\n const response: AccessToken = this.parseRawResponse(responseData);\n logger.getToken.info(formatSuccess(scopes));\n return response;\n } catch (e: any) {\n if (obj.stderr) {\n throw new CredentialUnavailableError(obj.stderr);\n }\n throw e;\n }\n } catch (err: any) {\n const error =\n err.name === \"CredentialUnavailableError\"\n ? err\n : new CredentialUnavailableError(\n (err as Error).message || \"Unknown error while trying to retrieve the access token\",\n );\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n });\n }\n\n /**\n * Parses the raw JSON response from the Azure CLI into a usable AccessToken object\n *\n * @param rawResponse - The raw JSON response from the Azure CLI\n * @returns An access token with the expiry time parsed from the raw response\n *\n * The expiryTime of the credential's access token, in milliseconds, is calculated as follows:\n *\n * When available, expires_on (introduced in Azure CLI v2.54.0) will be preferred. Otherwise falls back to expiresOn.\n */\n private parseRawResponse(rawResponse: string): AccessToken {\n const response: any = JSON.parse(rawResponse);\n const token = response.accessToken;\n // if available, expires_on will be a number representing seconds since epoch.\n // ensure it's a number or NaN\n let expiresOnTimestamp = Number.parseInt(response.expires_on, 10) * 1000;\n if (!isNaN(expiresOnTimestamp)) {\n logger.getToken.info(\"expires_on is available and is valid, using it\");\n return {\n token,\n expiresOnTimestamp,\n tokenType: \"Bearer\",\n };\n }\n\n // fallback to the older expiresOn - an RFC3339 date string\n expiresOnTimestamp = new Date(response.expiresOn).getTime();\n\n // ensure expiresOn is well-formatted\n if (isNaN(expiresOnTimestamp)) {\n throw new CredentialUnavailableError(\n `Unexpected response from Azure CLI when getting token. Expected \"expiresOn\" to be a RFC3339 date string. Got: \"${response.expiresOn}\"`,\n );\n }\n\n return {\n token,\n expiresOnTimestamp,\n tokenType: \"Bearer\",\n };\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"azureCliCredentialOptions.js","sourceRoot":"","sources":["../../../../../identity/src/credentials/azureCliCredentialOptions.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { MultiTenantTokenCredentialOptions } from \"./multiTenantTokenCredentialOptions\";\n\n/**\n * Options for the {@link AzureCliCredential}\n */\nexport interface AzureCliCredentialOptions extends MultiTenantTokenCredentialOptions {\n /**\n * Allows specifying a tenant ID\n */\n tenantId?: string;\n /**\n * Process timeout configurable for making token requests, provided in milliseconds\n */\n processTimeoutInMs?: number;\n /**\n * Subscription is the name or ID of a subscription. Set this to acquire tokens for an account other\n * than the Azure CLI's current account.\n */\n subscription?: string;\n}\n"]}
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Microsoft Corporation.
|
|
2
|
-
// Licensed under the MIT License.
|
|
3
|
-
import { __awaiter } from "tslib";
|
|
4
|
-
import { credentialLogger, formatError, formatSuccess } from "../util/logging";
|
|
5
|
-
import { CredentialUnavailableError } from "../errors";
|
|
6
|
-
import child_process from "child_process";
|
|
7
|
-
import { checkTenantId, processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, } from "../util/tenantIdUtils";
|
|
8
|
-
import { tracingClient } from "../util/tracing";
|
|
9
|
-
import { ensureValidScopeForDevTimeCreds } from "../util/scopeUtils";
|
|
10
|
-
/**
|
|
11
|
-
* Mockable reference to the Developer CLI credential cliCredentialFunctions
|
|
12
|
-
* @internal
|
|
13
|
-
*/
|
|
14
|
-
export const developerCliCredentialInternals = {
|
|
15
|
-
/**
|
|
16
|
-
* @internal
|
|
17
|
-
*/
|
|
18
|
-
getSafeWorkingDir() {
|
|
19
|
-
if (process.platform === "win32") {
|
|
20
|
-
if (!process.env.SystemRoot) {
|
|
21
|
-
throw new Error("Azure Developer CLI credential expects a 'SystemRoot' environment variable");
|
|
22
|
-
}
|
|
23
|
-
return process.env.SystemRoot;
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
26
|
-
return "/bin";
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
/**
|
|
30
|
-
* Gets the access token from Azure Developer CLI
|
|
31
|
-
* @param scopes - The scopes to use when getting the token
|
|
32
|
-
* @internal
|
|
33
|
-
*/
|
|
34
|
-
getAzdAccessToken(scopes, tenantId, timeout) {
|
|
35
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
-
let tenantSection = [];
|
|
37
|
-
if (tenantId) {
|
|
38
|
-
tenantSection = ["--tenant-id", tenantId];
|
|
39
|
-
}
|
|
40
|
-
return new Promise((resolve, reject) => {
|
|
41
|
-
try {
|
|
42
|
-
child_process.execFile("azd", [
|
|
43
|
-
"auth",
|
|
44
|
-
"token",
|
|
45
|
-
"--output",
|
|
46
|
-
"json",
|
|
47
|
-
...scopes.reduce((previous, current) => previous.concat("--scope", current), []),
|
|
48
|
-
...tenantSection,
|
|
49
|
-
], {
|
|
50
|
-
cwd: developerCliCredentialInternals.getSafeWorkingDir(),
|
|
51
|
-
timeout,
|
|
52
|
-
}, (error, stdout, stderr) => {
|
|
53
|
-
resolve({ stdout, stderr, error });
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
catch (err) {
|
|
57
|
-
reject(err);
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
},
|
|
62
|
-
};
|
|
63
|
-
const logger = credentialLogger("AzureDeveloperCliCredential");
|
|
64
|
-
/**
|
|
65
|
-
* Azure Developer CLI is a command-line interface tool that allows developers to create, manage, and deploy
|
|
66
|
-
* resources in Azure. It's built on top of the Azure CLI and provides additional functionality specific
|
|
67
|
-
* to Azure developers. It allows users to authenticate as a user and/or a service principal against
|
|
68
|
-
* <a href="https://learn.microsoft.com/entra/fundamentals/">Microsoft Entra ID</a>. The
|
|
69
|
-
* AzureDeveloperCliCredential authenticates in a development environment and acquires a token on behalf of
|
|
70
|
-
* the logged-in user or service principal in the Azure Developer CLI. It acts as the Azure Developer CLI logged in user or
|
|
71
|
-
* service principal and executes an Azure CLI command underneath to authenticate the application against
|
|
72
|
-
* Microsoft Entra ID.
|
|
73
|
-
*
|
|
74
|
-
* <h2> Configure AzureDeveloperCliCredential </h2>
|
|
75
|
-
*
|
|
76
|
-
* To use this credential, the developer needs to authenticate locally in Azure Developer CLI using one of the
|
|
77
|
-
* commands below:
|
|
78
|
-
*
|
|
79
|
-
* <ol>
|
|
80
|
-
* <li>Run "azd auth login" in Azure Developer CLI to authenticate interactively as a user.</li>
|
|
81
|
-
* <li>Run "azd auth login --client-id clientID --client-secret clientSecret
|
|
82
|
-
* --tenant-id tenantID" to authenticate as a service principal.</li>
|
|
83
|
-
* </ol>
|
|
84
|
-
*
|
|
85
|
-
* You may need to repeat this process after a certain time period, depending on the refresh token validity in your
|
|
86
|
-
* organization. Generally, the refresh token validity period is a few weeks to a few months.
|
|
87
|
-
* AzureDeveloperCliCredential will prompt you to sign in again.
|
|
88
|
-
*/
|
|
89
|
-
export class AzureDeveloperCliCredential {
|
|
90
|
-
/**
|
|
91
|
-
* Creates an instance of the {@link AzureDeveloperCliCredential}.
|
|
92
|
-
*
|
|
93
|
-
* To use this credential, ensure that you have already logged
|
|
94
|
-
* in via the 'azd' tool using the command "azd auth login" from the commandline.
|
|
95
|
-
*
|
|
96
|
-
* @param options - Options, to optionally allow multi-tenant requests.
|
|
97
|
-
*/
|
|
98
|
-
constructor(options) {
|
|
99
|
-
if (options === null || options === void 0 ? void 0 : options.tenantId) {
|
|
100
|
-
checkTenantId(logger, options === null || options === void 0 ? void 0 : options.tenantId);
|
|
101
|
-
this.tenantId = options === null || options === void 0 ? void 0 : options.tenantId;
|
|
102
|
-
}
|
|
103
|
-
this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants);
|
|
104
|
-
this.timeout = options === null || options === void 0 ? void 0 : options.processTimeoutInMs;
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Authenticates with Microsoft Entra ID and returns an access token if successful.
|
|
108
|
-
* If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.
|
|
109
|
-
*
|
|
110
|
-
* @param scopes - The list of scopes for which the token will have access.
|
|
111
|
-
* @param options - The options used to configure any requests this
|
|
112
|
-
* TokenCredential implementation might make.
|
|
113
|
-
*/
|
|
114
|
-
getToken(scopes_1) {
|
|
115
|
-
return __awaiter(this, arguments, void 0, function* (scopes, options = {}) {
|
|
116
|
-
const tenantId = processMultiTenantRequest(this.tenantId, options, this.additionallyAllowedTenantIds);
|
|
117
|
-
if (tenantId) {
|
|
118
|
-
checkTenantId(logger, tenantId);
|
|
119
|
-
}
|
|
120
|
-
let scopeList;
|
|
121
|
-
if (typeof scopes === "string") {
|
|
122
|
-
scopeList = [scopes];
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
scopeList = scopes;
|
|
126
|
-
}
|
|
127
|
-
logger.getToken.info(`Using the scopes ${scopes}`);
|
|
128
|
-
return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, () => __awaiter(this, void 0, void 0, function* () {
|
|
129
|
-
var _a, _b, _c, _d;
|
|
130
|
-
try {
|
|
131
|
-
scopeList.forEach((scope) => {
|
|
132
|
-
ensureValidScopeForDevTimeCreds(scope, logger);
|
|
133
|
-
});
|
|
134
|
-
const obj = yield developerCliCredentialInternals.getAzdAccessToken(scopeList, tenantId, this.timeout);
|
|
135
|
-
const isNotLoggedInError = ((_a = obj.stderr) === null || _a === void 0 ? void 0 : _a.match("not logged in, run `azd login` to login")) ||
|
|
136
|
-
((_b = obj.stderr) === null || _b === void 0 ? void 0 : _b.match("not logged in, run `azd auth login` to login"));
|
|
137
|
-
const isNotInstallError = ((_c = obj.stderr) === null || _c === void 0 ? void 0 : _c.match("azd:(.*)not found")) ||
|
|
138
|
-
((_d = obj.stderr) === null || _d === void 0 ? void 0 : _d.startsWith("'azd' is not recognized"));
|
|
139
|
-
if (isNotInstallError || (obj.error && obj.error.code === "ENOENT")) {
|
|
140
|
-
const error = new CredentialUnavailableError("Azure Developer CLI couldn't be found. To mitigate this issue, see the troubleshooting guidelines at https://aka.ms/azsdk/js/identity/azdevclicredential/troubleshoot.");
|
|
141
|
-
logger.getToken.info(formatError(scopes, error));
|
|
142
|
-
throw error;
|
|
143
|
-
}
|
|
144
|
-
if (isNotLoggedInError) {
|
|
145
|
-
const error = new CredentialUnavailableError("Please run 'azd auth login' from a command prompt to authenticate before using this credential. For more information, see the troubleshooting guidelines at https://aka.ms/azsdk/js/identity/azdevclicredential/troubleshoot.");
|
|
146
|
-
logger.getToken.info(formatError(scopes, error));
|
|
147
|
-
throw error;
|
|
148
|
-
}
|
|
149
|
-
try {
|
|
150
|
-
const resp = JSON.parse(obj.stdout);
|
|
151
|
-
logger.getToken.info(formatSuccess(scopes));
|
|
152
|
-
return {
|
|
153
|
-
token: resp.token,
|
|
154
|
-
expiresOnTimestamp: new Date(resp.expiresOn).getTime(),
|
|
155
|
-
tokenType: "Bearer",
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
catch (e) {
|
|
159
|
-
if (obj.stderr) {
|
|
160
|
-
throw new CredentialUnavailableError(obj.stderr);
|
|
161
|
-
}
|
|
162
|
-
throw e;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
catch (err) {
|
|
166
|
-
const error = err.name === "CredentialUnavailableError"
|
|
167
|
-
? err
|
|
168
|
-
: new CredentialUnavailableError(err.message || "Unknown error while trying to retrieve the access token");
|
|
169
|
-
logger.getToken.info(formatError(scopes, error));
|
|
170
|
-
throw error;
|
|
171
|
-
}
|
|
172
|
-
}));
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
//# sourceMappingURL=azureDeveloperCliCredential.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"azureDeveloperCliCredential.js","sourceRoot":"","sources":["../../../../../identity/src/credentials/azureDeveloperCliCredential.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport { credentialLogger, formatError, formatSuccess } from \"../util/logging\";\nimport type { AzureDeveloperCliCredentialOptions } from \"./azureDeveloperCliCredentialOptions\";\nimport { CredentialUnavailableError } from \"../errors\";\nimport child_process from \"child_process\";\nimport {\n checkTenantId,\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n} from \"../util/tenantIdUtils\";\nimport { tracingClient } from \"../util/tracing\";\nimport { ensureValidScopeForDevTimeCreds } from \"../util/scopeUtils\";\n\n/**\n * Mockable reference to the Developer CLI credential cliCredentialFunctions\n * @internal\n */\nexport const developerCliCredentialInternals = {\n /**\n * @internal\n */\n getSafeWorkingDir(): string {\n if (process.platform === \"win32\") {\n if (!process.env.SystemRoot) {\n throw new Error(\n \"Azure Developer CLI credential expects a 'SystemRoot' environment variable\",\n );\n }\n return process.env.SystemRoot;\n } else {\n return \"/bin\";\n }\n },\n\n /**\n * Gets the access token from Azure Developer CLI\n * @param scopes - The scopes to use when getting the token\n * @internal\n */\n async getAzdAccessToken(\n scopes: string[],\n tenantId?: string,\n timeout?: number,\n ): Promise<{ stdout: string; stderr: string; error: Error | null }> {\n let tenantSection: string[] = [];\n if (tenantId) {\n tenantSection = [\"--tenant-id\", tenantId];\n }\n return new Promise((resolve, reject) => {\n try {\n child_process.execFile(\n \"azd\",\n [\n \"auth\",\n \"token\",\n \"--output\",\n \"json\",\n ...scopes.reduce<string[]>(\n (previous, current) => previous.concat(\"--scope\", current),\n [],\n ),\n ...tenantSection,\n ],\n {\n cwd: developerCliCredentialInternals.getSafeWorkingDir(),\n timeout,\n },\n (error, stdout, stderr) => {\n resolve({ stdout, stderr, error });\n },\n );\n } catch (err: any) {\n reject(err);\n }\n });\n },\n};\n\nconst logger = credentialLogger(\"AzureDeveloperCliCredential\");\n\n/**\n * Azure Developer CLI is a command-line interface tool that allows developers to create, manage, and deploy\n * resources in Azure. It's built on top of the Azure CLI and provides additional functionality specific\n * to Azure developers. It allows users to authenticate as a user and/or a service principal against\n * <a href=\"https://learn.microsoft.com/entra/fundamentals/\">Microsoft Entra ID</a>. The\n * AzureDeveloperCliCredential authenticates in a development environment and acquires a token on behalf of\n * the logged-in user or service principal in the Azure Developer CLI. It acts as the Azure Developer CLI logged in user or\n * service principal and executes an Azure CLI command underneath to authenticate the application against\n * Microsoft Entra ID.\n *\n * <h2> Configure AzureDeveloperCliCredential </h2>\n *\n * To use this credential, the developer needs to authenticate locally in Azure Developer CLI using one of the\n * commands below:\n *\n * <ol>\n * <li>Run \"azd auth login\" in Azure Developer CLI to authenticate interactively as a user.</li>\n * <li>Run \"azd auth login --client-id clientID --client-secret clientSecret\n * --tenant-id tenantID\" to authenticate as a service principal.</li>\n * </ol>\n *\n * You may need to repeat this process after a certain time period, depending on the refresh token validity in your\n * organization. Generally, the refresh token validity period is a few weeks to a few months.\n * AzureDeveloperCliCredential will prompt you to sign in again.\n */\nexport class AzureDeveloperCliCredential implements TokenCredential {\n private tenantId?: string;\n private additionallyAllowedTenantIds: string[];\n private timeout?: number;\n\n /**\n * Creates an instance of the {@link AzureDeveloperCliCredential}.\n *\n * To use this credential, ensure that you have already logged\n * in via the 'azd' tool using the command \"azd auth login\" from the commandline.\n *\n * @param options - Options, to optionally allow multi-tenant requests.\n */\n constructor(options?: AzureDeveloperCliCredentialOptions) {\n if (options?.tenantId) {\n checkTenantId(logger, options?.tenantId);\n this.tenantId = options?.tenantId;\n }\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.additionallyAllowedTenants,\n );\n this.timeout = options?.processTimeoutInMs;\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 * @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 const tenantId = processMultiTenantRequest(\n this.tenantId,\n options,\n this.additionallyAllowedTenantIds,\n );\n if (tenantId) {\n checkTenantId(logger, tenantId);\n }\n let scopeList: string[];\n if (typeof scopes === \"string\") {\n scopeList = [scopes];\n } else {\n scopeList = scopes;\n }\n logger.getToken.info(`Using the scopes ${scopes}`);\n\n return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async () => {\n try {\n scopeList.forEach((scope) => {\n ensureValidScopeForDevTimeCreds(scope, logger);\n });\n const obj = await developerCliCredentialInternals.getAzdAccessToken(\n scopeList,\n tenantId,\n this.timeout,\n );\n const isNotLoggedInError =\n obj.stderr?.match(\"not logged in, run `azd login` to login\") ||\n obj.stderr?.match(\"not logged in, run `azd auth login` to login\");\n const isNotInstallError =\n obj.stderr?.match(\"azd:(.*)not found\") ||\n obj.stderr?.startsWith(\"'azd' is not recognized\");\n\n if (isNotInstallError || (obj.error && (obj.error as any).code === \"ENOENT\")) {\n const error = new CredentialUnavailableError(\n \"Azure Developer CLI couldn't be found. To mitigate this issue, see the troubleshooting guidelines at https://aka.ms/azsdk/js/identity/azdevclicredential/troubleshoot.\",\n );\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n\n if (isNotLoggedInError) {\n const error = new CredentialUnavailableError(\n \"Please run 'azd auth login' from a command prompt to authenticate before using this credential. For more information, see the troubleshooting guidelines at https://aka.ms/azsdk/js/identity/azdevclicredential/troubleshoot.\",\n );\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n\n try {\n const resp: { token: string; expiresOn: string } = JSON.parse(obj.stdout);\n logger.getToken.info(formatSuccess(scopes));\n return {\n token: resp.token,\n expiresOnTimestamp: new Date(resp.expiresOn).getTime(),\n tokenType: \"Bearer\",\n } as AccessToken;\n } catch (e: any) {\n if (obj.stderr) {\n throw new CredentialUnavailableError(obj.stderr);\n }\n throw e;\n }\n } catch (err: any) {\n const error =\n err.name === \"CredentialUnavailableError\"\n ? err\n : new CredentialUnavailableError(\n (err as Error).message || \"Unknown error while trying to retrieve the access token\",\n );\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n });\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"azureDeveloperCliCredentialOptions.js","sourceRoot":"","sources":["../../../../../identity/src/credentials/azureDeveloperCliCredentialOptions.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { MultiTenantTokenCredentialOptions } from \"./multiTenantTokenCredentialOptions\";\n\n/**\n * Options for the {@link AzureDeveloperCliCredential}\n */\nexport interface AzureDeveloperCliCredentialOptions extends MultiTenantTokenCredentialOptions {\n /**\n * Allows specifying a tenant ID\n */\n tenantId?: string;\n /**\n * Process timeout configurable for making token requests, provided in milliseconds\n */\n processTimeoutInMs?: number;\n}\n"]}
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Microsoft Corporation.
|
|
2
|
-
// Licensed under the MIT License.
|
|
3
|
-
import { __awaiter } from "tslib";
|
|
4
|
-
import { AuthenticationError, CredentialUnavailableError } from "../errors";
|
|
5
|
-
import { createHttpHeaders, createPipelineRequest } from "@azure/core-rest-pipeline";
|
|
6
|
-
import { ClientAssertionCredential } from "./clientAssertionCredential";
|
|
7
|
-
import { IdentityClient } from "../client/identityClient";
|
|
8
|
-
import { checkTenantId } from "../util/tenantIdUtils";
|
|
9
|
-
import { credentialLogger } from "../util/logging";
|
|
10
|
-
const credentialName = "AzurePipelinesCredential";
|
|
11
|
-
const logger = credentialLogger(credentialName);
|
|
12
|
-
const OIDC_API_VERSION = "7.1";
|
|
13
|
-
/**
|
|
14
|
-
* This credential is designed to be used in Azure Pipelines with service connections
|
|
15
|
-
* as a setup for workload identity federation.
|
|
16
|
-
*/
|
|
17
|
-
export class AzurePipelinesCredential {
|
|
18
|
-
/**
|
|
19
|
-
* AzurePipelinesCredential supports Federated Identity on Azure Pipelines through Service Connections.
|
|
20
|
-
* @param tenantId - tenantId associated with the service connection
|
|
21
|
-
* @param clientId - clientId associated with the service connection
|
|
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.
|
|
24
|
-
* @param options - The identity client options to use for authentication.
|
|
25
|
-
*/
|
|
26
|
-
constructor(tenantId, clientId, serviceConnectionId, systemAccessToken, options = {}) {
|
|
27
|
-
var _a, _b;
|
|
28
|
-
if (!clientId) {
|
|
29
|
-
throw new CredentialUnavailableError(`${credentialName}: is unavailable. clientId is a required parameter.`);
|
|
30
|
-
}
|
|
31
|
-
if (!tenantId) {
|
|
32
|
-
throw new CredentialUnavailableError(`${credentialName}: is unavailable. tenantId is a required parameter.`);
|
|
33
|
-
}
|
|
34
|
-
if (!serviceConnectionId) {
|
|
35
|
-
throw new CredentialUnavailableError(`${credentialName}: is unavailable. serviceConnectionId is a required parameter.`);
|
|
36
|
-
}
|
|
37
|
-
if (!systemAccessToken) {
|
|
38
|
-
throw new CredentialUnavailableError(`${credentialName}: is unavailable. systemAccessToken is a required parameter.`);
|
|
39
|
-
}
|
|
40
|
-
// Allow these headers to be logged for troubleshooting by AzurePipelines.
|
|
41
|
-
options.loggingOptions = Object.assign(Object.assign({}, options === null || options === void 0 ? void 0 : options.loggingOptions), { additionalAllowedHeaderNames: [
|
|
42
|
-
...((_b = (_a = options.loggingOptions) === null || _a === void 0 ? void 0 : _a.additionalAllowedHeaderNames) !== null && _b !== void 0 ? _b : []),
|
|
43
|
-
"x-vss-e2eid",
|
|
44
|
-
"x-msedge-ref",
|
|
45
|
-
] });
|
|
46
|
-
this.identityClient = new IdentityClient(options);
|
|
47
|
-
checkTenantId(logger, tenantId);
|
|
48
|
-
logger.info(`Invoking AzurePipelinesCredential with tenant ID: ${tenantId}, client ID: ${clientId}, and service connection ID: ${serviceConnectionId}`);
|
|
49
|
-
if (!process.env.SYSTEM_OIDCREQUESTURI) {
|
|
50
|
-
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"`);
|
|
51
|
-
}
|
|
52
|
-
const oidcRequestUrl = `${process.env.SYSTEM_OIDCREQUESTURI}?api-version=${OIDC_API_VERSION}&serviceConnectionId=${serviceConnectionId}`;
|
|
53
|
-
logger.info(`Invoking ClientAssertionCredential with tenant ID: ${tenantId}, client ID: ${clientId} and service connection ID: ${serviceConnectionId}`);
|
|
54
|
-
this.clientAssertionCredential = new ClientAssertionCredential(tenantId, clientId, this.requestOidcToken.bind(this, oidcRequestUrl, systemAccessToken), options);
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Authenticates with Microsoft Entra ID and returns an access token if successful.
|
|
58
|
-
* If authentication fails, a {@link CredentialUnavailableError} or {@link AuthenticationError} will be thrown with the details of the failure.
|
|
59
|
-
*
|
|
60
|
-
* @param scopes - The list of scopes for which the token will have access.
|
|
61
|
-
* @param options - The options used to configure any requests this
|
|
62
|
-
* TokenCredential implementation might make.
|
|
63
|
-
*/
|
|
64
|
-
getToken(scopes, options) {
|
|
65
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
66
|
-
if (!this.clientAssertionCredential) {
|
|
67
|
-
const errorMessage = `${credentialName}: is unavailable. To use Federation Identity in Azure Pipelines, the following parameters are required -
|
|
68
|
-
tenantId,
|
|
69
|
-
clientId,
|
|
70
|
-
serviceConnectionId,
|
|
71
|
-
systemAccessToken,
|
|
72
|
-
"SYSTEM_OIDCREQUESTURI".
|
|
73
|
-
See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/azurepipelinescredential/troubleshoot`;
|
|
74
|
-
logger.error(errorMessage);
|
|
75
|
-
throw new CredentialUnavailableError(errorMessage);
|
|
76
|
-
}
|
|
77
|
-
logger.info("Invoking getToken() of Client Assertion Credential");
|
|
78
|
-
return this.clientAssertionCredential.getToken(scopes, options);
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
*
|
|
83
|
-
* @param oidcRequestUrl - oidc request url
|
|
84
|
-
* @param systemAccessToken - system access token
|
|
85
|
-
* @returns OIDC token from Azure Pipelines
|
|
86
|
-
*/
|
|
87
|
-
requestOidcToken(oidcRequestUrl, systemAccessToken) {
|
|
88
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
89
|
-
logger.info("Requesting OIDC token from Azure Pipelines...");
|
|
90
|
-
logger.info(oidcRequestUrl);
|
|
91
|
-
const request = createPipelineRequest({
|
|
92
|
-
url: oidcRequestUrl,
|
|
93
|
-
method: "POST",
|
|
94
|
-
headers: createHttpHeaders({
|
|
95
|
-
"Content-Type": "application/json",
|
|
96
|
-
Authorization: `Bearer ${systemAccessToken}`,
|
|
97
|
-
// Prevents the service from responding with a redirect HTTP status code (useful for automation).
|
|
98
|
-
"X-TFS-FedAuthRedirect": "Suppress",
|
|
99
|
-
}),
|
|
100
|
-
});
|
|
101
|
-
const response = yield this.identityClient.sendRequest(request);
|
|
102
|
-
return handleOidcResponse(response);
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
export function handleOidcResponse(response) {
|
|
107
|
-
// OIDC token is present in `bodyAsText` field
|
|
108
|
-
const text = response.bodyAsText;
|
|
109
|
-
if (!text) {
|
|
110
|
-
logger.error(`${credentialName}: Authentication Failed. Received null token from OIDC request. Response status- ${response.status}. Complete response - ${JSON.stringify(response)}`);
|
|
111
|
-
throw new AuthenticationError(response.status, {
|
|
112
|
-
error: `${credentialName}: Authentication Failed. Received null token from OIDC request.`,
|
|
113
|
-
error_description: `${JSON.stringify(response)}. See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/azurepipelinescredential/troubleshoot`,
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
try {
|
|
117
|
-
const result = JSON.parse(text);
|
|
118
|
-
if (result === null || result === void 0 ? void 0 : result.oidcToken) {
|
|
119
|
-
return result.oidcToken;
|
|
120
|
-
}
|
|
121
|
-
else {
|
|
122
|
-
const errorMessage = `${credentialName}: Authentication Failed. oidcToken field not detected in the response.`;
|
|
123
|
-
let errorDescription = ``;
|
|
124
|
-
if (response.status !== 200) {
|
|
125
|
-
errorDescription = `Response body = ${text}. Response Headers ["x-vss-e2eid"] = ${response.headers.get("x-vss-e2eid")} and ["x-msedge-ref"] = ${response.headers.get("x-msedge-ref")}. See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/azurepipelinescredential/troubleshoot`;
|
|
126
|
-
}
|
|
127
|
-
logger.error(errorMessage);
|
|
128
|
-
logger.error(errorDescription);
|
|
129
|
-
throw new AuthenticationError(response.status, {
|
|
130
|
-
error: errorMessage,
|
|
131
|
-
error_description: errorDescription,
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
catch (e) {
|
|
136
|
-
const errorDetails = `${credentialName}: Authentication Failed. oidcToken field not detected in the response.`;
|
|
137
|
-
logger.error(`Response from service = ${text}, Response Headers ["x-vss-e2eid"] = ${response.headers.get("x-vss-e2eid")}
|
|
138
|
-
and ["x-msedge-ref"] = ${response.headers.get("x-msedge-ref")}, error message = ${e.message}`);
|
|
139
|
-
logger.error(errorDetails);
|
|
140
|
-
throw new AuthenticationError(response.status, {
|
|
141
|
-
error: errorDetails,
|
|
142
|
-
error_description: `Response = ${text}. Response headers ["x-vss-e2eid"] = ${response.headers.get("x-vss-e2eid")} and ["x-msedge-ref"] = ${response.headers.get("x-msedge-ref")}. See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/azurepipelinescredential/troubleshoot`,
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
//# sourceMappingURL=azurePipelinesCredential.js.map
|
|
@@ -1 +0,0 @@
|
|
|
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 type { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport { AuthenticationError, CredentialUnavailableError } from \"../errors\";\nimport { createHttpHeaders, createPipelineRequest } from \"@azure/core-rest-pipeline\";\n\nimport type { AzurePipelinesCredentialOptions } from \"./azurePipelinesCredentialOptions\";\nimport { ClientAssertionCredential } from \"./clientAssertionCredential\";\nimport { IdentityClient } from \"../client/identityClient\";\nimport type { PipelineResponse } from \"@azure/core-rest-pipeline\";\nimport { checkTenantId } from \"../util/tenantIdUtils\";\nimport { credentialLogger } from \"../util/logging\";\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) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. clientId is a required parameter.`,\n );\n }\n if (!tenantId) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. tenantId is a required parameter.`,\n );\n }\n if (!serviceConnectionId) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. serviceConnectionId is a required parameter.`,\n );\n }\n if (!systemAccessToken) {\n throw new CredentialUnavailableError(\n `${credentialName}: is unavailable. systemAccessToken is a required parameter.`,\n );\n }\n\n // Allow these headers to be logged for troubleshooting by AzurePipelines.\n options.loggingOptions = {\n ...options?.loggingOptions,\n additionalAllowedHeaderNames: [\n ...(options.loggingOptions?.additionalAllowedHeaderNames ?? []),\n \"x-vss-e2eid\",\n \"x-msedge-ref\",\n ],\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 // Prevents the service from responding with a redirect HTTP status code (useful for automation).\n \"X-TFS-FedAuthRedirect\": \"Suppress\",\n }),\n });\n const response = await this.identityClient.sendRequest(request);\n return handleOidcResponse(response);\n }\n}\n\nexport function handleOidcResponse(response: PipelineResponse): string {\n // OIDC token is present in `bodyAsText` field\n const text = response.bodyAsText;\n if (!text) {\n logger.error(\n `${credentialName}: Authentication Failed. Received null token from OIDC request. Response status- ${\n response.status\n }. Complete response - ${JSON.stringify(response)}`,\n );\n throw new AuthenticationError(response.status, {\n error: `${credentialName}: Authentication Failed. Received null token from OIDC request.`,\n error_description: `${JSON.stringify(\n response,\n )}. See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/azurepipelinescredential/troubleshoot`,\n });\n }\n try {\n const result = JSON.parse(text);\n if (result?.oidcToken) {\n return result.oidcToken;\n } else {\n const errorMessage = `${credentialName}: Authentication Failed. oidcToken field not detected in the response.`;\n let errorDescription = ``;\n if (response.status !== 200) {\n errorDescription = `Response body = ${text}. Response Headers [\"x-vss-e2eid\"] = ${response.headers.get(\"x-vss-e2eid\")} and [\"x-msedge-ref\"] = ${response.headers.get(\"x-msedge-ref\")}. See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/azurepipelinescredential/troubleshoot`;\n }\n logger.error(errorMessage);\n logger.error(errorDescription);\n throw new AuthenticationError(response.status, {\n error: errorMessage,\n error_description: errorDescription,\n });\n }\n } catch (e: any) {\n const errorDetails = `${credentialName}: Authentication Failed. oidcToken field not detected in the response.`;\n logger.error(\n `Response from service = ${text}, Response Headers [\"x-vss-e2eid\"] = ${response.headers.get(\"x-vss-e2eid\")} \n and [\"x-msedge-ref\"] = ${response.headers.get(\"x-msedge-ref\")}, error message = ${e.message}`,\n );\n logger.error(errorDetails);\n throw new AuthenticationError(response.status, {\n error: errorDetails,\n error_description: `Response = ${text}. Response headers [\"x-vss-e2eid\"] = ${response.headers.get(\"x-vss-e2eid\")} and [\"x-msedge-ref\"] = ${response.headers.get(\"x-msedge-ref\")}. See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/azurepipelinescredential/troubleshoot`,\n });\n }\n}\n"]}
|