@azure/identity 4.1.0-alpha.20240229.2 → 4.1.0-alpha.20240305.3
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.
Potentially problematic release.
This version of @azure/identity might be problematic. Click here for more details.
- package/dist/index.js +1308 -1305
- package/dist/index.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalNodeCommon.js +1 -33
- package/dist-esm/src/msal/nodeFlows/msalNodeCommon.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalOpenBrowser.js +2 -1
- package/dist-esm/src/msal/nodeFlows/msalOpenBrowser.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalPlugins.js +33 -1
- package/dist-esm/src/msal/nodeFlows/msalPlugins.js.map +1 -1
- package/dist-esm/src/plugins/consumer.js +1 -1
- package/dist-esm/src/plugins/consumer.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var msalCommon = require('@azure/msal-node');
|
|
6
5
|
var logger$q = require('@azure/logger');
|
|
7
|
-
var coreUtil = require('@azure/core-util');
|
|
8
|
-
var abortController = require('@azure/abort-controller');
|
|
9
6
|
var coreClient = require('@azure/core-client');
|
|
7
|
+
var coreUtil = require('@azure/core-util');
|
|
10
8
|
var coreRestPipeline = require('@azure/core-rest-pipeline');
|
|
9
|
+
var abortController = require('@azure/abort-controller');
|
|
11
10
|
var coreTracing = require('@azure/core-tracing');
|
|
12
11
|
var fs = require('fs');
|
|
13
12
|
var os = require('os');
|
|
14
13
|
var path = require('path');
|
|
14
|
+
var msalCommon = require('@azure/msal-node');
|
|
15
15
|
var promises = require('fs/promises');
|
|
16
16
|
var https = require('https');
|
|
17
17
|
var child_process = require('child_process');
|
|
@@ -42,62 +42,38 @@ var child_process__namespace = /*#__PURE__*/_interopNamespaceDefault(child_proce
|
|
|
42
42
|
// Copyright (c) Microsoft Corporation.
|
|
43
43
|
// Licensed under the MIT license.
|
|
44
44
|
/**
|
|
45
|
-
*
|
|
46
|
-
*/
|
|
47
|
-
const SDK_VERSION = `4.1.0-beta.2`;
|
|
48
|
-
/**
|
|
49
|
-
* The default client ID for authentication
|
|
50
|
-
* @internal
|
|
51
|
-
*/
|
|
52
|
-
// TODO: temporary - this is the Azure CLI clientID - we'll replace it when
|
|
53
|
-
// Developer Sign On application is available
|
|
54
|
-
// https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/src/Constants.cs#L9
|
|
55
|
-
const DeveloperSignOnClientId = "04b07795-8ddb-461a-bbee-02f9e1bf7b46";
|
|
56
|
-
/**
|
|
57
|
-
* The default tenant for authentication
|
|
58
|
-
* @internal
|
|
59
|
-
*/
|
|
60
|
-
const DefaultTenantId = "common";
|
|
61
|
-
/**
|
|
62
|
-
* A list of known Azure authority hosts
|
|
63
|
-
*/
|
|
64
|
-
exports.AzureAuthorityHosts = void 0;
|
|
65
|
-
(function (AzureAuthorityHosts) {
|
|
66
|
-
/**
|
|
67
|
-
* China-based Azure Authority Host
|
|
68
|
-
*/
|
|
69
|
-
AzureAuthorityHosts["AzureChina"] = "https://login.chinacloudapi.cn";
|
|
70
|
-
/**
|
|
71
|
-
* Germany-based Azure Authority Host
|
|
72
|
-
*/
|
|
73
|
-
AzureAuthorityHosts["AzureGermany"] = "https://login.microsoftonline.de";
|
|
74
|
-
/**
|
|
75
|
-
* US Government Azure Authority Host
|
|
76
|
-
*/
|
|
77
|
-
AzureAuthorityHosts["AzureGovernment"] = "https://login.microsoftonline.us";
|
|
78
|
-
/**
|
|
79
|
-
* Public Cloud Azure Authority Host
|
|
80
|
-
*/
|
|
81
|
-
AzureAuthorityHosts["AzurePublicCloud"] = "https://login.microsoftonline.com";
|
|
82
|
-
})(exports.AzureAuthorityHosts || (exports.AzureAuthorityHosts = {}));
|
|
83
|
-
/**
|
|
45
|
+
* The current persistence provider, undefined by default.
|
|
84
46
|
* @internal
|
|
85
|
-
* The default authority host.
|
|
86
47
|
*/
|
|
87
|
-
|
|
48
|
+
let persistenceProvider = undefined;
|
|
88
49
|
/**
|
|
50
|
+
* An object that allows setting the persistence provider.
|
|
89
51
|
* @internal
|
|
90
|
-
* Allow acquiring tokens for any tenant for multi-tentant auth.
|
|
91
52
|
*/
|
|
92
|
-
const
|
|
53
|
+
const msalNodeFlowCacheControl = {
|
|
54
|
+
setPersistence(pluginProvider) {
|
|
55
|
+
persistenceProvider = pluginProvider;
|
|
56
|
+
},
|
|
57
|
+
};
|
|
93
58
|
/**
|
|
59
|
+
* The current native broker provider, undefined by default.
|
|
94
60
|
* @internal
|
|
95
61
|
*/
|
|
96
|
-
|
|
62
|
+
let nativeBrokerInfo = undefined;
|
|
63
|
+
function hasNativeBroker() {
|
|
64
|
+
return nativeBrokerInfo !== undefined;
|
|
65
|
+
}
|
|
97
66
|
/**
|
|
67
|
+
* An object that allows setting the native broker provider.
|
|
98
68
|
* @internal
|
|
99
69
|
*/
|
|
100
|
-
const
|
|
70
|
+
const msalNodeFlowNativeBrokerControl = {
|
|
71
|
+
setNativeBroker(broker) {
|
|
72
|
+
nativeBrokerInfo = {
|
|
73
|
+
broker,
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
};
|
|
101
77
|
|
|
102
78
|
// Copyright (c) Microsoft Corporation.
|
|
103
79
|
// Licensed under the MIT license.
|
|
@@ -178,6 +154,66 @@ function credentialLogger(title, log = logger$p) {
|
|
|
178
154
|
return Object.assign(Object.assign({}, credLogger), { parent: log, getToken: credentialLoggerInstance("=> getToken()", credLogger, log) });
|
|
179
155
|
}
|
|
180
156
|
|
|
157
|
+
// Copyright (c) Microsoft Corporation.
|
|
158
|
+
// Licensed under the MIT license.
|
|
159
|
+
/**
|
|
160
|
+
* Current version of the `@azure/identity` package.
|
|
161
|
+
*/
|
|
162
|
+
const SDK_VERSION = `4.1.0-beta.2`;
|
|
163
|
+
/**
|
|
164
|
+
* The default client ID for authentication
|
|
165
|
+
* @internal
|
|
166
|
+
*/
|
|
167
|
+
// TODO: temporary - this is the Azure CLI clientID - we'll replace it when
|
|
168
|
+
// Developer Sign On application is available
|
|
169
|
+
// https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/src/Constants.cs#L9
|
|
170
|
+
const DeveloperSignOnClientId = "04b07795-8ddb-461a-bbee-02f9e1bf7b46";
|
|
171
|
+
/**
|
|
172
|
+
* The default tenant for authentication
|
|
173
|
+
* @internal
|
|
174
|
+
*/
|
|
175
|
+
const DefaultTenantId = "common";
|
|
176
|
+
/**
|
|
177
|
+
* A list of known Azure authority hosts
|
|
178
|
+
*/
|
|
179
|
+
exports.AzureAuthorityHosts = void 0;
|
|
180
|
+
(function (AzureAuthorityHosts) {
|
|
181
|
+
/**
|
|
182
|
+
* China-based Azure Authority Host
|
|
183
|
+
*/
|
|
184
|
+
AzureAuthorityHosts["AzureChina"] = "https://login.chinacloudapi.cn";
|
|
185
|
+
/**
|
|
186
|
+
* Germany-based Azure Authority Host
|
|
187
|
+
*/
|
|
188
|
+
AzureAuthorityHosts["AzureGermany"] = "https://login.microsoftonline.de";
|
|
189
|
+
/**
|
|
190
|
+
* US Government Azure Authority Host
|
|
191
|
+
*/
|
|
192
|
+
AzureAuthorityHosts["AzureGovernment"] = "https://login.microsoftonline.us";
|
|
193
|
+
/**
|
|
194
|
+
* Public Cloud Azure Authority Host
|
|
195
|
+
*/
|
|
196
|
+
AzureAuthorityHosts["AzurePublicCloud"] = "https://login.microsoftonline.com";
|
|
197
|
+
})(exports.AzureAuthorityHosts || (exports.AzureAuthorityHosts = {}));
|
|
198
|
+
/**
|
|
199
|
+
* @internal
|
|
200
|
+
* The default authority host.
|
|
201
|
+
*/
|
|
202
|
+
const DefaultAuthorityHost = exports.AzureAuthorityHosts.AzurePublicCloud;
|
|
203
|
+
/**
|
|
204
|
+
* @internal
|
|
205
|
+
* Allow acquiring tokens for any tenant for multi-tentant auth.
|
|
206
|
+
*/
|
|
207
|
+
const ALL_TENANTS = ["*"];
|
|
208
|
+
/**
|
|
209
|
+
* @internal
|
|
210
|
+
*/
|
|
211
|
+
const CACHE_CAE_SUFFIX = ".cae";
|
|
212
|
+
/**
|
|
213
|
+
* @internal
|
|
214
|
+
*/
|
|
215
|
+
const CACHE_NON_CAE_SUFFIX = ".nocae";
|
|
216
|
+
|
|
181
217
|
// Copyright (c) Microsoft Corporation.
|
|
182
218
|
// Licensed under the MIT license.
|
|
183
219
|
function isErrorResponse(errorResponse) {
|
|
@@ -299,325 +335,113 @@ class AuthenticationRequiredError extends Error {
|
|
|
299
335
|
|
|
300
336
|
// Copyright (c) Microsoft Corporation.
|
|
301
337
|
// Licensed under the MIT license.
|
|
338
|
+
function createConfigurationErrorMessage(tenantId) {
|
|
339
|
+
return `The current credential is not configured to acquire tokens for tenant ${tenantId}. To enable acquiring tokens for this tenant add it to the AdditionallyAllowedTenants on the credential options, or add "*" to AdditionallyAllowedTenants to allow acquiring tokens for any tenant.`;
|
|
340
|
+
}
|
|
302
341
|
/**
|
|
342
|
+
* Of getToken contains a tenantId, this functions allows picking this tenantId as the appropriate for authentication,
|
|
343
|
+
* unless multitenant authentication has been disabled through the AZURE_IDENTITY_DISABLE_MULTITENANTAUTH (on Node.js),
|
|
344
|
+
* or unless the original tenant Id is `adfs`.
|
|
303
345
|
* @internal
|
|
304
346
|
*/
|
|
305
|
-
|
|
347
|
+
function processMultiTenantRequest(tenantId, getTokenOptions, additionallyAllowedTenantIds = [], logger) {
|
|
348
|
+
var _a;
|
|
349
|
+
let resolvedTenantId;
|
|
350
|
+
if (process.env.AZURE_IDENTITY_DISABLE_MULTITENANTAUTH) {
|
|
351
|
+
resolvedTenantId = tenantId;
|
|
352
|
+
}
|
|
353
|
+
else if (tenantId === "adfs") {
|
|
354
|
+
resolvedTenantId = tenantId;
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
resolvedTenantId = (_a = getTokenOptions === null || getTokenOptions === void 0 ? void 0 : getTokenOptions.tenantId) !== null && _a !== void 0 ? _a : tenantId;
|
|
358
|
+
}
|
|
359
|
+
if (tenantId &&
|
|
360
|
+
resolvedTenantId !== tenantId &&
|
|
361
|
+
!additionallyAllowedTenantIds.includes("*") &&
|
|
362
|
+
!additionallyAllowedTenantIds.some((t) => t.localeCompare(resolvedTenantId) === 0)) {
|
|
363
|
+
const message = createConfigurationErrorMessage(tenantId);
|
|
364
|
+
logger === null || logger === void 0 ? void 0 : logger.info(message);
|
|
365
|
+
throw new CredentialUnavailableError(message);
|
|
366
|
+
}
|
|
367
|
+
return resolvedTenantId;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Copyright (c) Microsoft Corporation.
|
|
371
|
+
// Licensed under the MIT license.
|
|
306
372
|
/**
|
|
307
|
-
* Latest AuthenticationRecord version
|
|
308
373
|
* @internal
|
|
309
374
|
*/
|
|
310
|
-
|
|
375
|
+
function checkTenantId(logger, tenantId) {
|
|
376
|
+
if (!tenantId.match(/^[0-9a-zA-Z-.]+$/)) {
|
|
377
|
+
const error = new Error("Invalid tenant id provided. You can locate your tenant id by following the instructions listed here: https://learn.microsoft.com/partner-center/find-ids-and-domain-names.");
|
|
378
|
+
logger.info(formatError("", error));
|
|
379
|
+
throw error;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
311
382
|
/**
|
|
312
|
-
* Ensures the validity of the MSAL token
|
|
313
383
|
* @internal
|
|
314
384
|
*/
|
|
315
|
-
function
|
|
316
|
-
|
|
317
|
-
logger
|
|
318
|
-
return
|
|
319
|
-
scopes: Array.isArray(scopes) ? scopes : [scopes],
|
|
320
|
-
getTokenOptions,
|
|
321
|
-
message,
|
|
322
|
-
});
|
|
323
|
-
};
|
|
324
|
-
if (!msalToken) {
|
|
325
|
-
throw error("No response");
|
|
385
|
+
function resolveTenantId(logger, tenantId, clientId) {
|
|
386
|
+
if (tenantId) {
|
|
387
|
+
checkTenantId(logger, tenantId);
|
|
388
|
+
return tenantId;
|
|
326
389
|
}
|
|
327
|
-
if (!
|
|
328
|
-
|
|
390
|
+
if (!clientId) {
|
|
391
|
+
clientId = DeveloperSignOnClientId;
|
|
329
392
|
}
|
|
330
|
-
if (
|
|
331
|
-
|
|
393
|
+
if (clientId !== DeveloperSignOnClientId) {
|
|
394
|
+
return "common";
|
|
332
395
|
}
|
|
396
|
+
return "organizations";
|
|
333
397
|
}
|
|
334
398
|
/**
|
|
335
|
-
* Generates a valid authority by combining a host with a tenantId.
|
|
336
399
|
* @internal
|
|
337
400
|
*/
|
|
338
|
-
function
|
|
339
|
-
if (!
|
|
340
|
-
|
|
401
|
+
function resolveAdditionallyAllowedTenantIds(additionallyAllowedTenants) {
|
|
402
|
+
if (!additionallyAllowedTenants || additionallyAllowedTenants.length === 0) {
|
|
403
|
+
return [];
|
|
341
404
|
}
|
|
342
|
-
if (
|
|
343
|
-
return
|
|
405
|
+
if (additionallyAllowedTenants.includes("*")) {
|
|
406
|
+
return ALL_TENANTS;
|
|
344
407
|
}
|
|
345
|
-
|
|
346
|
-
|
|
408
|
+
return additionallyAllowedTenants;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// Copyright (c) Microsoft Corporation.
|
|
412
|
+
// Licensed under the MIT license.
|
|
413
|
+
function getIdentityTokenEndpointSuffix(tenantId) {
|
|
414
|
+
if (tenantId === "adfs") {
|
|
415
|
+
return "oauth2/token";
|
|
347
416
|
}
|
|
348
417
|
else {
|
|
349
|
-
return
|
|
418
|
+
return "oauth2/v2.0/token";
|
|
350
419
|
}
|
|
351
420
|
}
|
|
421
|
+
|
|
422
|
+
// Copyright (c) Microsoft Corporation.
|
|
423
|
+
// Licensed under the MIT license.
|
|
352
424
|
/**
|
|
353
|
-
*
|
|
354
|
-
* If the Tenant Id is `adfs`, the authority can't be validated since the format won't match the expected one.
|
|
355
|
-
* For that reason, we have to force MSAL to disable validating the authority
|
|
356
|
-
* by sending it within the known authorities in the MSAL configuration.
|
|
425
|
+
* Creates a span using the global tracer.
|
|
357
426
|
* @internal
|
|
358
427
|
*/
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
const
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
credLogger.info(`MSAL ${platform} V2 error: ${message}`);
|
|
377
|
-
return;
|
|
378
|
-
case msalCommon__namespace.LogLevel.Info:
|
|
379
|
-
credLogger.info(`MSAL ${platform} V2 info message: ${message}`);
|
|
380
|
-
return;
|
|
381
|
-
case msalCommon__namespace.LogLevel.Verbose:
|
|
382
|
-
credLogger.info(`MSAL ${platform} V2 verbose message: ${message}`);
|
|
383
|
-
return;
|
|
384
|
-
case msalCommon__namespace.LogLevel.Warning:
|
|
385
|
-
credLogger.info(`MSAL ${platform} V2 warning: ${message}`);
|
|
386
|
-
return;
|
|
387
|
-
}
|
|
388
|
-
};
|
|
389
|
-
/**
|
|
390
|
-
* @internal
|
|
391
|
-
*/
|
|
392
|
-
function getMSALLogLevel(logLevel) {
|
|
393
|
-
switch (logLevel) {
|
|
394
|
-
case "error":
|
|
395
|
-
return msalCommon__namespace.LogLevel.Error;
|
|
396
|
-
case "info":
|
|
397
|
-
return msalCommon__namespace.LogLevel.Info;
|
|
398
|
-
case "verbose":
|
|
399
|
-
return msalCommon__namespace.LogLevel.Verbose;
|
|
400
|
-
case "warning":
|
|
401
|
-
return msalCommon__namespace.LogLevel.Warning;
|
|
402
|
-
default:
|
|
403
|
-
// default msal logging level should be Info
|
|
404
|
-
return msalCommon__namespace.LogLevel.Info;
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
/**
|
|
408
|
-
* Wraps core-util's randomUUID in order to allow for mocking in tests.
|
|
409
|
-
* This prepares the library for the upcoming core-util update to ESM.
|
|
410
|
-
*
|
|
411
|
-
* @internal
|
|
412
|
-
* @returns A string containing a random UUID
|
|
413
|
-
*/
|
|
414
|
-
function randomUUID() {
|
|
415
|
-
return coreUtil.randomUUID();
|
|
416
|
-
}
|
|
417
|
-
/**
|
|
418
|
-
* Handles MSAL errors.
|
|
419
|
-
*/
|
|
420
|
-
function handleMsalError(scopes, error, getTokenOptions) {
|
|
421
|
-
if (error.name === "AuthError" ||
|
|
422
|
-
error.name === "ClientAuthError" ||
|
|
423
|
-
error.name === "BrowserAuthError") {
|
|
424
|
-
const msalError = error;
|
|
425
|
-
switch (msalError.errorCode) {
|
|
426
|
-
case "endpoints_resolution_error":
|
|
427
|
-
logger$o.info(formatError(scopes, error.message));
|
|
428
|
-
return new CredentialUnavailableError(error.message);
|
|
429
|
-
case "device_code_polling_cancelled":
|
|
430
|
-
return new abortController.AbortError("The authentication has been aborted by the caller.");
|
|
431
|
-
case "consent_required":
|
|
432
|
-
case "interaction_required":
|
|
433
|
-
case "login_required":
|
|
434
|
-
logger$o.info(formatError(scopes, `Authentication returned errorCode ${msalError.errorCode}`));
|
|
435
|
-
break;
|
|
436
|
-
default:
|
|
437
|
-
logger$o.info(formatError(scopes, `Failed to acquire token: ${error.message}`));
|
|
438
|
-
break;
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
if (error.name === "ClientConfigurationError" ||
|
|
442
|
-
error.name === "BrowserConfigurationAuthError" ||
|
|
443
|
-
error.name === "AbortError") {
|
|
444
|
-
return error;
|
|
445
|
-
}
|
|
446
|
-
if (error.name === "NativeAuthError") {
|
|
447
|
-
logger$o.info(formatError(scopes, `Error from the native broker: ${error.message} with status code: ${error.statusCode}`));
|
|
448
|
-
return error;
|
|
449
|
-
}
|
|
450
|
-
return new AuthenticationRequiredError({ scopes, getTokenOptions, message: error.message });
|
|
451
|
-
}
|
|
452
|
-
// transformations.ts
|
|
453
|
-
function publicToMsal(account) {
|
|
454
|
-
const [environment] = account.authority.match(/([a-z]*\.[a-z]*\.[a-z]*)/) || [""];
|
|
455
|
-
return Object.assign(Object.assign({}, account), { localAccountId: account.homeAccountId, environment });
|
|
456
|
-
}
|
|
457
|
-
function msalToPublic(clientId, account) {
|
|
458
|
-
const record = {
|
|
459
|
-
authority: getAuthority(account.tenantId, account.environment),
|
|
460
|
-
homeAccountId: account.homeAccountId,
|
|
461
|
-
tenantId: account.tenantId || DefaultTenantId,
|
|
462
|
-
username: account.username,
|
|
463
|
-
clientId,
|
|
464
|
-
version: LatestAuthenticationRecordVersion,
|
|
465
|
-
};
|
|
466
|
-
return record;
|
|
467
|
-
}
|
|
468
|
-
/**
|
|
469
|
-
* Serializes an `AuthenticationRecord` into a string.
|
|
470
|
-
*
|
|
471
|
-
* The output of a serialized authentication record will contain the following properties:
|
|
472
|
-
*
|
|
473
|
-
* - "authority"
|
|
474
|
-
* - "homeAccountId"
|
|
475
|
-
* - "clientId"
|
|
476
|
-
* - "tenantId"
|
|
477
|
-
* - "username"
|
|
478
|
-
* - "version"
|
|
479
|
-
*
|
|
480
|
-
* To later convert this string to a serialized `AuthenticationRecord`, please use the exported function `deserializeAuthenticationRecord()`.
|
|
481
|
-
*/
|
|
482
|
-
function serializeAuthenticationRecord(record) {
|
|
483
|
-
return JSON.stringify(record);
|
|
484
|
-
}
|
|
485
|
-
/**
|
|
486
|
-
* Deserializes a previously serialized authentication record from a string into an object.
|
|
487
|
-
*
|
|
488
|
-
* The input string must contain the following properties:
|
|
489
|
-
*
|
|
490
|
-
* - "authority"
|
|
491
|
-
* - "homeAccountId"
|
|
492
|
-
* - "clientId"
|
|
493
|
-
* - "tenantId"
|
|
494
|
-
* - "username"
|
|
495
|
-
* - "version"
|
|
496
|
-
*
|
|
497
|
-
* If the version we receive is unsupported, an error will be thrown.
|
|
498
|
-
*
|
|
499
|
-
* At the moment, the only available version is: "1.0", which is always set when the authentication record is serialized.
|
|
500
|
-
*
|
|
501
|
-
* @param serializedRecord - Authentication record previously serialized into string.
|
|
502
|
-
* @returns AuthenticationRecord.
|
|
503
|
-
*/
|
|
504
|
-
function deserializeAuthenticationRecord(serializedRecord) {
|
|
505
|
-
const parsed = JSON.parse(serializedRecord);
|
|
506
|
-
if (parsed.version && parsed.version !== LatestAuthenticationRecordVersion) {
|
|
507
|
-
throw Error("Unsupported AuthenticationRecord version");
|
|
508
|
-
}
|
|
509
|
-
return parsed;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
// Copyright (c) Microsoft Corporation.
|
|
513
|
-
// Licensed under the MIT license.
|
|
514
|
-
function createConfigurationErrorMessage(tenantId) {
|
|
515
|
-
return `The current credential is not configured to acquire tokens for tenant ${tenantId}. To enable acquiring tokens for this tenant add it to the AdditionallyAllowedTenants on the credential options, or add "*" to AdditionallyAllowedTenants to allow acquiring tokens for any tenant.`;
|
|
516
|
-
}
|
|
517
|
-
/**
|
|
518
|
-
* Of getToken contains a tenantId, this functions allows picking this tenantId as the appropriate for authentication,
|
|
519
|
-
* unless multitenant authentication has been disabled through the AZURE_IDENTITY_DISABLE_MULTITENANTAUTH (on Node.js),
|
|
520
|
-
* or unless the original tenant Id is `adfs`.
|
|
521
|
-
* @internal
|
|
522
|
-
*/
|
|
523
|
-
function processMultiTenantRequest(tenantId, getTokenOptions, additionallyAllowedTenantIds = [], logger) {
|
|
524
|
-
var _a;
|
|
525
|
-
let resolvedTenantId;
|
|
526
|
-
if (process.env.AZURE_IDENTITY_DISABLE_MULTITENANTAUTH) {
|
|
527
|
-
resolvedTenantId = tenantId;
|
|
528
|
-
}
|
|
529
|
-
else if (tenantId === "adfs") {
|
|
530
|
-
resolvedTenantId = tenantId;
|
|
531
|
-
}
|
|
532
|
-
else {
|
|
533
|
-
resolvedTenantId = (_a = getTokenOptions === null || getTokenOptions === void 0 ? void 0 : getTokenOptions.tenantId) !== null && _a !== void 0 ? _a : tenantId;
|
|
534
|
-
}
|
|
535
|
-
if (tenantId &&
|
|
536
|
-
resolvedTenantId !== tenantId &&
|
|
537
|
-
!additionallyAllowedTenantIds.includes("*") &&
|
|
538
|
-
!additionallyAllowedTenantIds.some((t) => t.localeCompare(resolvedTenantId) === 0)) {
|
|
539
|
-
const message = createConfigurationErrorMessage(tenantId);
|
|
540
|
-
logger === null || logger === void 0 ? void 0 : logger.info(message);
|
|
541
|
-
throw new CredentialUnavailableError(message);
|
|
542
|
-
}
|
|
543
|
-
return resolvedTenantId;
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
// Copyright (c) Microsoft Corporation.
|
|
547
|
-
// Licensed under the MIT license.
|
|
548
|
-
/**
|
|
549
|
-
* @internal
|
|
550
|
-
*/
|
|
551
|
-
function checkTenantId(logger, tenantId) {
|
|
552
|
-
if (!tenantId.match(/^[0-9a-zA-Z-.]+$/)) {
|
|
553
|
-
const error = new Error("Invalid tenant id provided. You can locate your tenant id by following the instructions listed here: https://learn.microsoft.com/partner-center/find-ids-and-domain-names.");
|
|
554
|
-
logger.info(formatError("", error));
|
|
555
|
-
throw error;
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
/**
|
|
559
|
-
* @internal
|
|
560
|
-
*/
|
|
561
|
-
function resolveTenantId(logger, tenantId, clientId) {
|
|
562
|
-
if (tenantId) {
|
|
563
|
-
checkTenantId(logger, tenantId);
|
|
564
|
-
return tenantId;
|
|
565
|
-
}
|
|
566
|
-
if (!clientId) {
|
|
567
|
-
clientId = DeveloperSignOnClientId;
|
|
568
|
-
}
|
|
569
|
-
if (clientId !== DeveloperSignOnClientId) {
|
|
570
|
-
return "common";
|
|
571
|
-
}
|
|
572
|
-
return "organizations";
|
|
573
|
-
}
|
|
574
|
-
/**
|
|
575
|
-
* @internal
|
|
576
|
-
*/
|
|
577
|
-
function resolveAdditionallyAllowedTenantIds(additionallyAllowedTenants) {
|
|
578
|
-
if (!additionallyAllowedTenants || additionallyAllowedTenants.length === 0) {
|
|
579
|
-
return [];
|
|
580
|
-
}
|
|
581
|
-
if (additionallyAllowedTenants.includes("*")) {
|
|
582
|
-
return ALL_TENANTS;
|
|
583
|
-
}
|
|
584
|
-
return additionallyAllowedTenants;
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
// Copyright (c) Microsoft Corporation.
|
|
588
|
-
// Licensed under the MIT license.
|
|
589
|
-
function getIdentityTokenEndpointSuffix(tenantId) {
|
|
590
|
-
if (tenantId === "adfs") {
|
|
591
|
-
return "oauth2/token";
|
|
592
|
-
}
|
|
593
|
-
else {
|
|
594
|
-
return "oauth2/v2.0/token";
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
// Copyright (c) Microsoft Corporation.
|
|
599
|
-
// Licensed under the MIT license.
|
|
600
|
-
/**
|
|
601
|
-
* Creates a span using the global tracer.
|
|
602
|
-
* @internal
|
|
603
|
-
*/
|
|
604
|
-
const tracingClient = coreTracing.createTracingClient({
|
|
605
|
-
namespace: "Microsoft.AAD",
|
|
606
|
-
packageName: "@azure/identity",
|
|
607
|
-
packageVersion: SDK_VERSION,
|
|
608
|
-
});
|
|
609
|
-
|
|
610
|
-
// Copyright (c) Microsoft Corporation.
|
|
611
|
-
// Licensed under the MIT license.
|
|
612
|
-
const DefaultScopeSuffix = "/.default";
|
|
613
|
-
const imdsHost = "http://169.254.169.254";
|
|
614
|
-
const imdsEndpointPath = "/metadata/identity/oauth2/token";
|
|
615
|
-
const imdsApiVersion = "2018-02-01";
|
|
616
|
-
const azureArcAPIVersion = "2019-11-01";
|
|
617
|
-
const azureFabricVersion = "2019-07-01-preview";
|
|
618
|
-
|
|
619
|
-
// Copyright (c) Microsoft Corporation.
|
|
620
|
-
// Licensed under the MIT license.
|
|
428
|
+
const tracingClient = coreTracing.createTracingClient({
|
|
429
|
+
namespace: "Microsoft.AAD",
|
|
430
|
+
packageName: "@azure/identity",
|
|
431
|
+
packageVersion: SDK_VERSION,
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
// Copyright (c) Microsoft Corporation.
|
|
435
|
+
// Licensed under the MIT license.
|
|
436
|
+
const DefaultScopeSuffix = "/.default";
|
|
437
|
+
const imdsHost = "http://169.254.169.254";
|
|
438
|
+
const imdsEndpointPath = "/metadata/identity/oauth2/token";
|
|
439
|
+
const imdsApiVersion = "2018-02-01";
|
|
440
|
+
const azureArcAPIVersion = "2019-11-01";
|
|
441
|
+
const azureFabricVersion = "2019-07-01-preview";
|
|
442
|
+
|
|
443
|
+
// Copyright (c) Microsoft Corporation.
|
|
444
|
+
// Licensed under the MIT license.
|
|
621
445
|
/**
|
|
622
446
|
* Most MSIs send requests to the IMDS endpoint, or a similar endpoint.
|
|
623
447
|
* These are GET requests that require sending a `resource` parameter on the query.
|
|
@@ -899,1082 +723,1261 @@ class IdentityClient extends coreClient.ServiceClient {
|
|
|
899
723
|
|
|
900
724
|
// Copyright (c) Microsoft Corporation.
|
|
901
725
|
// Licensed under the MIT license.
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'westus' region. */
|
|
910
|
-
RegionalAuthority["USWest"] = "westus";
|
|
911
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'westus2' region. */
|
|
912
|
-
RegionalAuthority["USWest2"] = "westus2";
|
|
913
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'centralus' region. */
|
|
914
|
-
RegionalAuthority["USCentral"] = "centralus";
|
|
915
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'eastus' region. */
|
|
916
|
-
RegionalAuthority["USEast"] = "eastus";
|
|
917
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'eastus2' region. */
|
|
918
|
-
RegionalAuthority["USEast2"] = "eastus2";
|
|
919
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'northcentralus' region. */
|
|
920
|
-
RegionalAuthority["USNorthCentral"] = "northcentralus";
|
|
921
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'southcentralus' region. */
|
|
922
|
-
RegionalAuthority["USSouthCentral"] = "southcentralus";
|
|
923
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'westcentralus' region. */
|
|
924
|
-
RegionalAuthority["USWestCentral"] = "westcentralus";
|
|
925
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'canadacentral' region. */
|
|
926
|
-
RegionalAuthority["CanadaCentral"] = "canadacentral";
|
|
927
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'canadaeast' region. */
|
|
928
|
-
RegionalAuthority["CanadaEast"] = "canadaeast";
|
|
929
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'brazilsouth' region. */
|
|
930
|
-
RegionalAuthority["BrazilSouth"] = "brazilsouth";
|
|
931
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'northeurope' region. */
|
|
932
|
-
RegionalAuthority["EuropeNorth"] = "northeurope";
|
|
933
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'westeurope' region. */
|
|
934
|
-
RegionalAuthority["EuropeWest"] = "westeurope";
|
|
935
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'uksouth' region. */
|
|
936
|
-
RegionalAuthority["UKSouth"] = "uksouth";
|
|
937
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'ukwest' region. */
|
|
938
|
-
RegionalAuthority["UKWest"] = "ukwest";
|
|
939
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'francecentral' region. */
|
|
940
|
-
RegionalAuthority["FranceCentral"] = "francecentral";
|
|
941
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'francesouth' region. */
|
|
942
|
-
RegionalAuthority["FranceSouth"] = "francesouth";
|
|
943
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'switzerlandnorth' region. */
|
|
944
|
-
RegionalAuthority["SwitzerlandNorth"] = "switzerlandnorth";
|
|
945
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'switzerlandwest' region. */
|
|
946
|
-
RegionalAuthority["SwitzerlandWest"] = "switzerlandwest";
|
|
947
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'germanynorth' region. */
|
|
948
|
-
RegionalAuthority["GermanyNorth"] = "germanynorth";
|
|
949
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'germanywestcentral' region. */
|
|
950
|
-
RegionalAuthority["GermanyWestCentral"] = "germanywestcentral";
|
|
951
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'norwaywest' region. */
|
|
952
|
-
RegionalAuthority["NorwayWest"] = "norwaywest";
|
|
953
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'norwayeast' region. */
|
|
954
|
-
RegionalAuthority["NorwayEast"] = "norwayeast";
|
|
955
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'eastasia' region. */
|
|
956
|
-
RegionalAuthority["AsiaEast"] = "eastasia";
|
|
957
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'southeastasia' region. */
|
|
958
|
-
RegionalAuthority["AsiaSouthEast"] = "southeastasia";
|
|
959
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'japaneast' region. */
|
|
960
|
-
RegionalAuthority["JapanEast"] = "japaneast";
|
|
961
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'japanwest' region. */
|
|
962
|
-
RegionalAuthority["JapanWest"] = "japanwest";
|
|
963
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'australiaeast' region. */
|
|
964
|
-
RegionalAuthority["AustraliaEast"] = "australiaeast";
|
|
965
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'australiasoutheast' region. */
|
|
966
|
-
RegionalAuthority["AustraliaSouthEast"] = "australiasoutheast";
|
|
967
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'australiacentral' region. */
|
|
968
|
-
RegionalAuthority["AustraliaCentral"] = "australiacentral";
|
|
969
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'australiacentral2' region. */
|
|
970
|
-
RegionalAuthority["AustraliaCentral2"] = "australiacentral2";
|
|
971
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'centralindia' region. */
|
|
972
|
-
RegionalAuthority["IndiaCentral"] = "centralindia";
|
|
973
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'southindia' region. */
|
|
974
|
-
RegionalAuthority["IndiaSouth"] = "southindia";
|
|
975
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'westindia' region. */
|
|
976
|
-
RegionalAuthority["IndiaWest"] = "westindia";
|
|
977
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'koreasouth' region. */
|
|
978
|
-
RegionalAuthority["KoreaSouth"] = "koreasouth";
|
|
979
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'koreacentral' region. */
|
|
980
|
-
RegionalAuthority["KoreaCentral"] = "koreacentral";
|
|
981
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'uaecentral' region. */
|
|
982
|
-
RegionalAuthority["UAECentral"] = "uaecentral";
|
|
983
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'uaenorth' region. */
|
|
984
|
-
RegionalAuthority["UAENorth"] = "uaenorth";
|
|
985
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'southafricanorth' region. */
|
|
986
|
-
RegionalAuthority["SouthAfricaNorth"] = "southafricanorth";
|
|
987
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'southafricawest' region. */
|
|
988
|
-
RegionalAuthority["SouthAfricaWest"] = "southafricawest";
|
|
989
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'chinanorth' region. */
|
|
990
|
-
RegionalAuthority["ChinaNorth"] = "chinanorth";
|
|
991
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'chinaeast' region. */
|
|
992
|
-
RegionalAuthority["ChinaEast"] = "chinaeast";
|
|
993
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'chinanorth2' region. */
|
|
994
|
-
RegionalAuthority["ChinaNorth2"] = "chinanorth2";
|
|
995
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'chinaeast2' region. */
|
|
996
|
-
RegionalAuthority["ChinaEast2"] = "chinaeast2";
|
|
997
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'germanycentral' region. */
|
|
998
|
-
RegionalAuthority["GermanyCentral"] = "germanycentral";
|
|
999
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'germanynortheast' region. */
|
|
1000
|
-
RegionalAuthority["GermanyNorthEast"] = "germanynortheast";
|
|
1001
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'usgovvirginia' region. */
|
|
1002
|
-
RegionalAuthority["GovernmentUSVirginia"] = "usgovvirginia";
|
|
1003
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'usgoviowa' region. */
|
|
1004
|
-
RegionalAuthority["GovernmentUSIowa"] = "usgoviowa";
|
|
1005
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'usgovarizona' region. */
|
|
1006
|
-
RegionalAuthority["GovernmentUSArizona"] = "usgovarizona";
|
|
1007
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'usgovtexas' region. */
|
|
1008
|
-
RegionalAuthority["GovernmentUSTexas"] = "usgovtexas";
|
|
1009
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'usdodeast' region. */
|
|
1010
|
-
RegionalAuthority["GovernmentUSDodEast"] = "usdodeast";
|
|
1011
|
-
/** Uses the {@link RegionalAuthority} for the Azure 'usdodcentral' region. */
|
|
1012
|
-
RegionalAuthority["GovernmentUSDodCentral"] = "usdodcentral";
|
|
1013
|
-
})(RegionalAuthority || (RegionalAuthority = {}));
|
|
1014
|
-
|
|
1015
|
-
// Copyright (c) Microsoft Corporation.
|
|
1016
|
-
// Licensed under the MIT license.
|
|
1017
|
-
/**
|
|
1018
|
-
* The current persistence provider, undefined by default.
|
|
1019
|
-
* @internal
|
|
1020
|
-
*/
|
|
1021
|
-
let persistenceProvider = undefined;
|
|
1022
|
-
/**
|
|
1023
|
-
* An object that allows setting the persistence provider.
|
|
1024
|
-
* @internal
|
|
1025
|
-
*/
|
|
1026
|
-
const msalNodeFlowCacheControl = {
|
|
1027
|
-
setPersistence(pluginProvider) {
|
|
1028
|
-
persistenceProvider = pluginProvider;
|
|
726
|
+
const CommonTenantId = "common";
|
|
727
|
+
const AzureAccountClientId = "aebc6443-996d-45c2-90f0-388ff96faa56"; // VSC: 'aebc6443-996d-45c2-90f0-388ff96faa56'
|
|
728
|
+
const logger$o = credentialLogger("VisualStudioCodeCredential");
|
|
729
|
+
let findCredentials = undefined;
|
|
730
|
+
const vsCodeCredentialControl = {
|
|
731
|
+
setVsCodeCredentialFinder(finder) {
|
|
732
|
+
findCredentials = finder;
|
|
1029
733
|
},
|
|
1030
734
|
};
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
735
|
+
// Map of unsupported Tenant IDs and the errors we will be throwing.
|
|
736
|
+
const unsupportedTenantIds = {
|
|
737
|
+
adfs: "The VisualStudioCodeCredential does not support authentication with ADFS tenants.",
|
|
738
|
+
};
|
|
739
|
+
function checkUnsupportedTenant(tenantId) {
|
|
740
|
+
// If the Tenant ID isn't supported, we throw.
|
|
741
|
+
const unsupportedTenantError = unsupportedTenantIds[tenantId];
|
|
742
|
+
if (unsupportedTenantError) {
|
|
743
|
+
throw new CredentialUnavailableError(unsupportedTenantError);
|
|
744
|
+
}
|
|
1038
745
|
}
|
|
746
|
+
const mapVSCodeAuthorityHosts = {
|
|
747
|
+
AzureCloud: exports.AzureAuthorityHosts.AzurePublicCloud,
|
|
748
|
+
AzureChina: exports.AzureAuthorityHosts.AzureChina,
|
|
749
|
+
AzureGermanCloud: exports.AzureAuthorityHosts.AzureGermany,
|
|
750
|
+
AzureUSGovernment: exports.AzureAuthorityHosts.AzureGovernment,
|
|
751
|
+
};
|
|
1039
752
|
/**
|
|
1040
|
-
*
|
|
1041
|
-
*
|
|
753
|
+
* Attempts to load a specific property from the VSCode configurations of the current OS.
|
|
754
|
+
* If it fails at any point, returns undefined.
|
|
1042
755
|
*/
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
756
|
+
function getPropertyFromVSCode(property) {
|
|
757
|
+
const settingsPath = ["User", "settings.json"];
|
|
758
|
+
// Eventually we can add more folders for more versions of VSCode.
|
|
759
|
+
const vsCodeFolder = "Code";
|
|
760
|
+
const homedir = os.homedir();
|
|
761
|
+
function loadProperty(...pathSegments) {
|
|
762
|
+
const fullPath = path.join(...pathSegments, vsCodeFolder, ...settingsPath);
|
|
763
|
+
const settings = JSON.parse(fs.readFileSync(fullPath, { encoding: "utf8" }));
|
|
764
|
+
return settings[property];
|
|
765
|
+
}
|
|
766
|
+
try {
|
|
767
|
+
let appData;
|
|
768
|
+
switch (process.platform) {
|
|
769
|
+
case "win32":
|
|
770
|
+
appData = process.env.APPDATA;
|
|
771
|
+
return appData ? loadProperty(appData) : undefined;
|
|
772
|
+
case "darwin":
|
|
773
|
+
return loadProperty(homedir, "Library", "Application Support");
|
|
774
|
+
case "linux":
|
|
775
|
+
return loadProperty(homedir, ".config");
|
|
776
|
+
default:
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
catch (e) {
|
|
781
|
+
logger$o.info(`Failed to load the Visual Studio Code configuration file. Error: ${e.message}`);
|
|
782
|
+
return;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
1050
785
|
/**
|
|
1051
|
-
*
|
|
1052
|
-
*
|
|
1053
|
-
*
|
|
1054
|
-
* It also provides with utility protected methods that can be used from any of the clients,
|
|
1055
|
-
* which includes handlers for successful responses and errors.
|
|
786
|
+
* Connects to Azure using the credential provided by the VSCode extension 'Azure Account'.
|
|
787
|
+
* Once the user has logged in via the extension, this credential can share the same refresh token
|
|
788
|
+
* that is cached by the extension.
|
|
1056
789
|
*
|
|
1057
|
-
*
|
|
790
|
+
* It's a [known issue](https://github.com/Azure/azure-sdk-for-js/issues/20500) that this credential doesn't
|
|
791
|
+
* work with [Azure Account extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.azure-account)
|
|
792
|
+
* versions newer than **0.9.11**. A long-term fix to this problem is in progress. In the meantime, consider
|
|
793
|
+
* authenticating with {@link AzureCliCredential}.
|
|
1058
794
|
*/
|
|
1059
|
-
class
|
|
795
|
+
class VisualStudioCodeCredential {
|
|
796
|
+
/**
|
|
797
|
+
* Creates an instance of VisualStudioCodeCredential to use for automatically authenticating via VSCode.
|
|
798
|
+
*
|
|
799
|
+
* **Note**: `VisualStudioCodeCredential` is provided by a plugin package:
|
|
800
|
+
* `@azure/identity-vscode`. If this package is not installed and registered
|
|
801
|
+
* using the plugin API (`useIdentityPlugin`), then authentication using
|
|
802
|
+
* `VisualStudioCodeCredential` will not be available.
|
|
803
|
+
*
|
|
804
|
+
* @param options - Options for configuring the client which makes the authentication request.
|
|
805
|
+
*/
|
|
1060
806
|
constructor(options) {
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
this.
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
this.
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
if (options === null || options === void 0 ? void 0 : options.getAssertion) {
|
|
1071
|
-
this.getAssertion = options.getAssertion;
|
|
1072
|
-
}
|
|
1073
|
-
this.enableBroker = (_b = options === null || options === void 0 ? void 0 : options.brokerOptions) === null || _b === void 0 ? void 0 : _b.enabled;
|
|
1074
|
-
this.enableMsaPassthrough = (_c = options === null || options === void 0 ? void 0 : options.brokerOptions) === null || _c === void 0 ? void 0 : _c.legacyEnableMsaPassthrough;
|
|
1075
|
-
this.parentWindowHandle = (_d = options.brokerOptions) === null || _d === void 0 ? void 0 : _d.parentWindowHandle;
|
|
1076
|
-
// If persistence has been configured
|
|
1077
|
-
if (persistenceProvider !== undefined && ((_e = options.tokenCachePersistenceOptions) === null || _e === void 0 ? void 0 : _e.enabled)) {
|
|
1078
|
-
const nonCaeOptions = Object.assign({ name: `${options.tokenCachePersistenceOptions.name}.${CACHE_NON_CAE_SUFFIX}` }, options.tokenCachePersistenceOptions);
|
|
1079
|
-
const caeOptions = Object.assign({ name: `${options.tokenCachePersistenceOptions.name}.${CACHE_CAE_SUFFIX}` }, options.tokenCachePersistenceOptions);
|
|
1080
|
-
this.createCachePlugin = () => persistenceProvider(nonCaeOptions);
|
|
1081
|
-
this.createCachePluginCae = () => persistenceProvider(caeOptions);
|
|
1082
|
-
}
|
|
1083
|
-
else if ((_f = options.tokenCachePersistenceOptions) === null || _f === void 0 ? void 0 : _f.enabled) {
|
|
1084
|
-
throw new Error([
|
|
1085
|
-
"Persistent token caching was requested, but no persistence provider was configured.",
|
|
1086
|
-
"You must install the identity-cache-persistence plugin package (`npm install --save @azure/identity-cache-persistence`)",
|
|
1087
|
-
"and enable it by importing `useIdentityPlugin` from `@azure/identity` and calling",
|
|
1088
|
-
"`useIdentityPlugin(cachePersistencePlugin)` before using `tokenCachePersistenceOptions`.",
|
|
1089
|
-
].join(" "));
|
|
1090
|
-
}
|
|
1091
|
-
// If broker has not been configured
|
|
1092
|
-
if (!hasNativeBroker() && this.enableBroker) {
|
|
1093
|
-
throw new Error([
|
|
1094
|
-
"Broker for WAM was requested to be enabled, but no native broker was configured.",
|
|
1095
|
-
"You must install the identity-broker plugin package (`npm install --save @azure/identity-broker`)",
|
|
1096
|
-
"and enable it by importing `useIdentityPlugin` from `@azure/identity` and calling",
|
|
1097
|
-
"`useIdentityPlugin(createNativeBrokerPlugin())` before using `enableBroker`.",
|
|
1098
|
-
].join(" "));
|
|
807
|
+
// We want to make sure we use the one assigned by the user on the VSCode settings.
|
|
808
|
+
// Or just `AzureCloud` by default.
|
|
809
|
+
this.cloudName = (getPropertyFromVSCode("azure.cloud") || "AzureCloud");
|
|
810
|
+
// Picking an authority host based on the cloud name.
|
|
811
|
+
const authorityHost = mapVSCodeAuthorityHosts[this.cloudName];
|
|
812
|
+
this.identityClient = new IdentityClient(Object.assign({ authorityHost }, options));
|
|
813
|
+
if (options && options.tenantId) {
|
|
814
|
+
checkTenantId(logger$o, options.tenantId);
|
|
815
|
+
this.tenantId = options.tenantId;
|
|
1099
816
|
}
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
this.azureRegion = "AUTO_DISCOVER";
|
|
817
|
+
else {
|
|
818
|
+
this.tenantId = CommonTenantId;
|
|
1103
819
|
}
|
|
820
|
+
this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants);
|
|
821
|
+
checkUnsupportedTenant(this.tenantId);
|
|
1104
822
|
}
|
|
1105
823
|
/**
|
|
1106
|
-
*
|
|
824
|
+
* Runs preparations for any further getToken request.
|
|
1107
825
|
*/
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
const
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
const authority = getAuthority(tenantId, this.authorityHost);
|
|
1114
|
-
this.identityClient = new IdentityClient(Object.assign(Object.assign({}, options.tokenCredentialOptions), { authorityHost: authority, loggingOptions: options.loggingOptions }));
|
|
1115
|
-
const clientCapabilities = [];
|
|
1116
|
-
return {
|
|
1117
|
-
auth: {
|
|
1118
|
-
clientId,
|
|
1119
|
-
authority,
|
|
1120
|
-
knownAuthorities: getKnownAuthorities(tenantId, authority, options.disableInstanceDiscovery),
|
|
1121
|
-
clientCapabilities,
|
|
1122
|
-
},
|
|
1123
|
-
// Cache is defined in this.prepare();
|
|
1124
|
-
system: {
|
|
1125
|
-
networkClient: this.identityClient,
|
|
1126
|
-
loggerOptions: {
|
|
1127
|
-
loggerCallback: defaultLoggerCallback(options.logger),
|
|
1128
|
-
logLevel: getMSALLogLevel(logger$q.getLogLevel()),
|
|
1129
|
-
piiLoggingEnabled: (_a = options.loggingOptions) === null || _a === void 0 ? void 0 : _a.enableUnsafeSupportLogging,
|
|
1130
|
-
},
|
|
1131
|
-
},
|
|
1132
|
-
};
|
|
1133
|
-
}
|
|
1134
|
-
getApp(appType, enableCae) {
|
|
1135
|
-
const app = enableCae ? this.caeApp : this.app;
|
|
1136
|
-
if (appType === "publicFirst") {
|
|
1137
|
-
return (app.public || app.confidential);
|
|
1138
|
-
}
|
|
1139
|
-
else if (appType === "confidentialFirst") {
|
|
1140
|
-
return (app.confidential || app.public);
|
|
1141
|
-
}
|
|
1142
|
-
else if (appType === "confidential") {
|
|
1143
|
-
return app.confidential;
|
|
1144
|
-
}
|
|
1145
|
-
else {
|
|
1146
|
-
return app.public;
|
|
826
|
+
async prepare() {
|
|
827
|
+
// Attempts to load the tenant from the VSCode configuration file.
|
|
828
|
+
const settingsTenant = getPropertyFromVSCode("azure.tenant");
|
|
829
|
+
if (settingsTenant) {
|
|
830
|
+
this.tenantId = settingsTenant;
|
|
1147
831
|
}
|
|
832
|
+
checkUnsupportedTenant(this.tenantId);
|
|
1148
833
|
}
|
|
1149
834
|
/**
|
|
1150
|
-
*
|
|
835
|
+
* Runs preparations for any further getToken, but only once.
|
|
1151
836
|
*/
|
|
1152
|
-
|
|
1153
|
-
if (
|
|
1154
|
-
|
|
1155
|
-
// This will abort any pending request in the IdentityClient,
|
|
1156
|
-
// based on the received or generated correlationId
|
|
1157
|
-
this.identityClient.abortRequests(options.correlationId);
|
|
1158
|
-
});
|
|
1159
|
-
}
|
|
1160
|
-
const app = (options === null || options === void 0 ? void 0 : options.enableCae) ? this.caeApp : this.app;
|
|
1161
|
-
if (options === null || options === void 0 ? void 0 : options.enableCae) {
|
|
1162
|
-
this.msalConfig.auth.clientCapabilities = ["cp1"];
|
|
837
|
+
prepareOnce() {
|
|
838
|
+
if (!this.preparePromise) {
|
|
839
|
+
this.preparePromise = this.prepare();
|
|
1163
840
|
}
|
|
1164
|
-
|
|
1165
|
-
|
|
841
|
+
return this.preparePromise;
|
|
842
|
+
}
|
|
843
|
+
/**
|
|
844
|
+
* Returns the token found by searching VSCode's authentication cache or
|
|
845
|
+
* returns null if no token could be found.
|
|
846
|
+
*
|
|
847
|
+
* @param scopes - The list of scopes for which the token will have access.
|
|
848
|
+
* @param options - The options used to configure any requests this
|
|
849
|
+
* `TokenCredential` implementation might make.
|
|
850
|
+
*/
|
|
851
|
+
async getToken(scopes, options) {
|
|
852
|
+
var _a, _b;
|
|
853
|
+
await this.prepareOnce();
|
|
854
|
+
const tenantId = processMultiTenantRequest(this.tenantId, options, this.additionallyAllowedTenantIds, logger$o) || this.tenantId;
|
|
855
|
+
if (findCredentials === undefined) {
|
|
856
|
+
throw new CredentialUnavailableError([
|
|
857
|
+
"No implementation of `VisualStudioCodeCredential` is available.",
|
|
858
|
+
"You must install the identity-vscode plugin package (`npm install --save-dev @azure/identity-vscode`)",
|
|
859
|
+
"and enable it by importing `useIdentityPlugin` from `@azure/identity` and calling",
|
|
860
|
+
"`useIdentityPlugin(vsCodePlugin)` before creating a `VisualStudioCodeCredential`.",
|
|
861
|
+
"To troubleshoot, visit https://aka.ms/azsdk/js/identity/vscodecredential/troubleshoot.",
|
|
862
|
+
].join(" "));
|
|
1166
863
|
}
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
864
|
+
let scopeString = typeof scopes === "string" ? scopes : scopes.join(" ");
|
|
865
|
+
// Check to make sure the scope we get back is a valid scope
|
|
866
|
+
if (!scopeString.match(/^[0-9a-zA-Z-.:/]+$/)) {
|
|
867
|
+
const error = new Error("Invalid scope was specified by the user or calling client");
|
|
868
|
+
logger$o.getToken.info(formatError(scopes, error));
|
|
869
|
+
throw error;
|
|
1171
870
|
}
|
|
1172
|
-
if (
|
|
1173
|
-
|
|
1174
|
-
cachePlugin: await this.createCachePlugin(),
|
|
1175
|
-
};
|
|
871
|
+
if (scopeString.indexOf("offline_access") < 0) {
|
|
872
|
+
scopeString += " offline_access";
|
|
1176
873
|
}
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
874
|
+
// findCredentials returns an array similar to:
|
|
875
|
+
// [
|
|
876
|
+
// {
|
|
877
|
+
// account: "",
|
|
878
|
+
// password: "",
|
|
879
|
+
// },
|
|
880
|
+
// /* ... */
|
|
881
|
+
// ]
|
|
882
|
+
const credentials = await findCredentials();
|
|
883
|
+
// If we can't find the credential based on the name, we'll pick the first one available.
|
|
884
|
+
const { password: refreshToken } = (_b = (_a = credentials.find(({ account }) => account === this.cloudName)) !== null && _a !== void 0 ? _a : credentials[0]) !== null && _b !== void 0 ? _b : {};
|
|
885
|
+
if (refreshToken) {
|
|
886
|
+
const tokenResponse = await this.identityClient.refreshAccessToken(tenantId, AzureAccountClientId, scopeString, refreshToken, undefined);
|
|
887
|
+
if (tokenResponse) {
|
|
888
|
+
logger$o.getToken.info(formatSuccess(scopes));
|
|
889
|
+
return tokenResponse.accessToken;
|
|
890
|
+
}
|
|
891
|
+
else {
|
|
892
|
+
const error = new CredentialUnavailableError("Could not retrieve the token associated with Visual Studio Code. Have you connected using the 'Azure Account' extension recently? To troubleshoot, visit https://aka.ms/azsdk/js/identity/vscodecredential/troubleshoot.");
|
|
893
|
+
logger$o.getToken.info(formatError(scopes, error));
|
|
894
|
+
throw error;
|
|
1184
895
|
}
|
|
1185
|
-
}
|
|
1186
|
-
if (options === null || options === void 0 ? void 0 : options.enableCae) {
|
|
1187
|
-
this.caeApp.public = new msalCommon__namespace.PublicClientApplication(this.msalConfig);
|
|
1188
896
|
}
|
|
1189
897
|
else {
|
|
1190
|
-
|
|
898
|
+
const error = new CredentialUnavailableError("Could not retrieve the token associated with Visual Studio Code. Did you connect using the 'Azure Account' extension? To troubleshoot, visit https://aka.ms/azsdk/js/identity/vscodecredential/troubleshoot.");
|
|
899
|
+
logger$o.getToken.info(formatError(scopes, error));
|
|
900
|
+
throw error;
|
|
1191
901
|
}
|
|
1192
|
-
|
|
1193
|
-
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
// Copyright (c) Microsoft Corporation.
|
|
906
|
+
// Licensed under the MIT license.
|
|
907
|
+
/**
|
|
908
|
+
* The context passed to an Identity plugin. This contains objects that
|
|
909
|
+
* plugins can use to set backend implementations.
|
|
910
|
+
* @internal
|
|
911
|
+
*/
|
|
912
|
+
const pluginContext = {
|
|
913
|
+
cachePluginControl: msalNodeFlowCacheControl,
|
|
914
|
+
nativeBrokerPluginControl: msalNodeFlowNativeBrokerControl,
|
|
915
|
+
vsCodeCredentialControl: vsCodeCredentialControl,
|
|
916
|
+
};
|
|
917
|
+
/**
|
|
918
|
+
* Extend Azure Identity with additional functionality. Pass a plugin from
|
|
919
|
+
* a plugin package, such as:
|
|
920
|
+
*
|
|
921
|
+
* - `@azure/identity-cache-persistence`: provides persistent token caching
|
|
922
|
+
* - `@azure/identity-vscode`: provides the dependencies of
|
|
923
|
+
* `VisualStudioCodeCredential` and enables it
|
|
924
|
+
*
|
|
925
|
+
* Example:
|
|
926
|
+
*
|
|
927
|
+
* ```javascript
|
|
928
|
+
* import { cachePersistencePlugin } from "@azure/identity-cache-persistence";
|
|
929
|
+
*
|
|
930
|
+
* import { useIdentityPlugin, DefaultAzureCredential } from "@azure/identity";
|
|
931
|
+
* useIdentityPlugin(cachePersistencePlugin);
|
|
932
|
+
*
|
|
933
|
+
* // The plugin has the capability to extend `DefaultAzureCredential` and to
|
|
934
|
+
* // add middleware to the underlying credentials, such as persistence.
|
|
935
|
+
* const credential = new DefaultAzureCredential({
|
|
936
|
+
* tokenCachePersistenceOptions: {
|
|
937
|
+
* enabled: true
|
|
938
|
+
* }
|
|
939
|
+
* });
|
|
940
|
+
* ```
|
|
941
|
+
*
|
|
942
|
+
* @param plugin - the plugin to register
|
|
943
|
+
*/
|
|
944
|
+
function useIdentityPlugin(plugin) {
|
|
945
|
+
plugin(pluginContext);
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
// Copyright (c) Microsoft Corporation.
|
|
949
|
+
// Licensed under the MIT license.
|
|
950
|
+
const msiName$6 = "ManagedIdentityCredential - AppServiceMSI 2017";
|
|
951
|
+
const logger$n = credentialLogger(msiName$6);
|
|
952
|
+
/**
|
|
953
|
+
* Generates the options used on the request for an access token.
|
|
954
|
+
*/
|
|
955
|
+
function prepareRequestOptions$5(scopes, clientId) {
|
|
956
|
+
const resource = mapScopesToResource(scopes);
|
|
957
|
+
if (!resource) {
|
|
958
|
+
throw new Error(`${msiName$6}: Multiple scopes are not supported.`);
|
|
959
|
+
}
|
|
960
|
+
const queryParameters = {
|
|
961
|
+
resource,
|
|
962
|
+
"api-version": "2017-09-01",
|
|
963
|
+
};
|
|
964
|
+
if (clientId) {
|
|
965
|
+
queryParameters.clientid = clientId;
|
|
966
|
+
}
|
|
967
|
+
const query = new URLSearchParams(queryParameters);
|
|
968
|
+
// This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
|
|
969
|
+
if (!process.env.MSI_ENDPOINT) {
|
|
970
|
+
throw new Error(`${msiName$6}: Missing environment variable: MSI_ENDPOINT`);
|
|
971
|
+
}
|
|
972
|
+
if (!process.env.MSI_SECRET) {
|
|
973
|
+
throw new Error(`${msiName$6}: Missing environment variable: MSI_SECRET`);
|
|
974
|
+
}
|
|
975
|
+
return {
|
|
976
|
+
url: `${process.env.MSI_ENDPOINT}?${query.toString()}`,
|
|
977
|
+
method: "GET",
|
|
978
|
+
headers: coreRestPipeline.createHttpHeaders({
|
|
979
|
+
Accept: "application/json",
|
|
980
|
+
secret: process.env.MSI_SECRET,
|
|
981
|
+
}),
|
|
982
|
+
};
|
|
983
|
+
}
|
|
984
|
+
/**
|
|
985
|
+
* Defines how to determine whether the Azure App Service MSI is available, and also how to retrieve a token from the Azure App Service MSI.
|
|
986
|
+
*/
|
|
987
|
+
const appServiceMsi2017 = {
|
|
988
|
+
name: "appServiceMsi2017",
|
|
989
|
+
async isAvailable({ scopes }) {
|
|
990
|
+
const resource = mapScopesToResource(scopes);
|
|
991
|
+
if (!resource) {
|
|
992
|
+
logger$n.info(`${msiName$6}: Unavailable. Multiple scopes are not supported.`);
|
|
993
|
+
return false;
|
|
1194
994
|
}
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
if (options === null || options === void 0 ? void 0 : options.enableCae) {
|
|
1200
|
-
this.caeApp.confidential = new msalCommon__namespace.ConfidentialClientApplication(this.msalConfig);
|
|
1201
|
-
}
|
|
1202
|
-
else {
|
|
1203
|
-
this.app.confidential = new msalCommon__namespace.ConfidentialClientApplication(this.msalConfig);
|
|
1204
|
-
}
|
|
995
|
+
const env = process.env;
|
|
996
|
+
const result = Boolean(env.MSI_ENDPOINT && env.MSI_SECRET);
|
|
997
|
+
if (!result) {
|
|
998
|
+
logger$n.info(`${msiName$6}: Unavailable. The environment variables needed are: MSI_ENDPOINT and MSI_SECRET.`);
|
|
1205
999
|
}
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1000
|
+
return result;
|
|
1001
|
+
},
|
|
1002
|
+
async getToken(configuration, getTokenOptions = {}) {
|
|
1003
|
+
const { identityClient, scopes, clientId, resourceId } = configuration;
|
|
1004
|
+
if (resourceId) {
|
|
1005
|
+
logger$n.warning(`${msiName$6}: managed Identity by resource Id is not supported. Argument resourceId might be ignored by the service.`);
|
|
1210
1006
|
}
|
|
1007
|
+
logger$n.info(`${msiName$6}: Using the endpoint and the secret coming form the environment variables: MSI_ENDPOINT=${process.env.MSI_ENDPOINT} and MSI_SECRET=[REDACTED].`);
|
|
1008
|
+
const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$5(scopes, clientId)), {
|
|
1009
|
+
// Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS).
|
|
1010
|
+
allowInsecureConnection: true }));
|
|
1011
|
+
const tokenResponse = await identityClient.sendTokenRequest(request);
|
|
1012
|
+
return (tokenResponse && tokenResponse.accessToken) || null;
|
|
1013
|
+
},
|
|
1014
|
+
};
|
|
1015
|
+
|
|
1016
|
+
// Copyright (c) Microsoft Corporation.
|
|
1017
|
+
// Licensed under the MIT license.
|
|
1018
|
+
const msiName$5 = "ManagedIdentityCredential - CloudShellMSI";
|
|
1019
|
+
const logger$m = credentialLogger(msiName$5);
|
|
1020
|
+
/**
|
|
1021
|
+
* Generates the options used on the request for an access token.
|
|
1022
|
+
*/
|
|
1023
|
+
function prepareRequestOptions$4(scopes, clientId, resourceId) {
|
|
1024
|
+
const resource = mapScopesToResource(scopes);
|
|
1025
|
+
if (!resource) {
|
|
1026
|
+
throw new Error(`${msiName$5}: Multiple scopes are not supported.`);
|
|
1211
1027
|
}
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
promise
|
|
1218
|
-
.then((msalToken) => {
|
|
1219
|
-
return resolve(msalToken);
|
|
1220
|
-
})
|
|
1221
|
-
.catch(reject);
|
|
1222
|
-
if (abortSignal) {
|
|
1223
|
-
abortSignal.addEventListener("abort", () => {
|
|
1224
|
-
onCancel === null || onCancel === void 0 ? void 0 : onCancel();
|
|
1225
|
-
});
|
|
1226
|
-
}
|
|
1227
|
-
});
|
|
1028
|
+
const body = {
|
|
1029
|
+
resource,
|
|
1030
|
+
};
|
|
1031
|
+
if (clientId) {
|
|
1032
|
+
body.client_id = clientId;
|
|
1228
1033
|
}
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1034
|
+
if (resourceId) {
|
|
1035
|
+
body.msi_res_id = resourceId;
|
|
1036
|
+
}
|
|
1037
|
+
// This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
|
|
1038
|
+
if (!process.env.MSI_ENDPOINT) {
|
|
1039
|
+
throw new Error(`${msiName$5}: Missing environment variable: MSI_ENDPOINT`);
|
|
1040
|
+
}
|
|
1041
|
+
const params = new URLSearchParams(body);
|
|
1042
|
+
return {
|
|
1043
|
+
url: process.env.MSI_ENDPOINT,
|
|
1044
|
+
method: "POST",
|
|
1045
|
+
body: params.toString(),
|
|
1046
|
+
headers: coreRestPipeline.createHttpHeaders({
|
|
1047
|
+
Accept: "application/json",
|
|
1048
|
+
Metadata: "true",
|
|
1049
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
1050
|
+
}),
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1053
|
+
/**
|
|
1054
|
+
* Defines how to determine whether the Azure Cloud Shell MSI is available, and also how to retrieve a token from the Azure Cloud Shell MSI.
|
|
1055
|
+
* Since Azure Managed Identities aren't available in the Azure Cloud Shell, we log a warning for users that try to access cloud shell using user assigned identity.
|
|
1056
|
+
*/
|
|
1057
|
+
const cloudShellMsi = {
|
|
1058
|
+
name: "cloudShellMsi",
|
|
1059
|
+
async isAvailable({ scopes }) {
|
|
1060
|
+
const resource = mapScopesToResource(scopes);
|
|
1061
|
+
if (!resource) {
|
|
1062
|
+
logger$m.info(`${msiName$5}: Unavailable. Multiple scopes are not supported.`);
|
|
1063
|
+
return false;
|
|
1235
1064
|
}
|
|
1236
|
-
const
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
return;
|
|
1065
|
+
const result = Boolean(process.env.MSI_ENDPOINT);
|
|
1066
|
+
if (!result) {
|
|
1067
|
+
logger$m.info(`${msiName$5}: Unavailable. The environment variable MSI_ENDPOINT is needed.`);
|
|
1240
1068
|
}
|
|
1241
|
-
|
|
1242
|
-
|
|
1069
|
+
return result;
|
|
1070
|
+
},
|
|
1071
|
+
async getToken(configuration, getTokenOptions = {}) {
|
|
1072
|
+
const { identityClient, scopes, clientId, resourceId } = configuration;
|
|
1073
|
+
if (clientId) {
|
|
1074
|
+
logger$m.warning(`${msiName$5}: user-assigned identities not supported. The argument clientId might be ignored by the service.`);
|
|
1243
1075
|
}
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
.info(`More than one account was found authenticated for this Client ID and Tenant ID.
|
|
1247
|
-
However, no "authenticationRecord" has been provided for this credential,
|
|
1248
|
-
therefore we're unable to pick between these accounts.
|
|
1249
|
-
A new login attempt will be requested, to ensure the correct account is picked.
|
|
1250
|
-
To work with multiple accounts for the same Client ID and Tenant ID, please provide an "authenticationRecord" when initializing a credential to prevent this from happening.`);
|
|
1251
|
-
return;
|
|
1076
|
+
if (resourceId) {
|
|
1077
|
+
logger$m.warning(`${msiName$5}: user defined managed Identity by resource Id not supported. The argument resourceId might be ignored by the service.`);
|
|
1252
1078
|
}
|
|
1253
|
-
|
|
1079
|
+
logger$m.info(`${msiName$5}: Using the endpoint coming form the environment variable MSI_ENDPOINT = ${process.env.MSI_ENDPOINT}.`);
|
|
1080
|
+
const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$4(scopes, clientId, resourceId)), {
|
|
1081
|
+
// Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS).
|
|
1082
|
+
allowInsecureConnection: true }));
|
|
1083
|
+
const tokenResponse = await identityClient.sendTokenRequest(request);
|
|
1084
|
+
return (tokenResponse && tokenResponse.accessToken) || null;
|
|
1085
|
+
},
|
|
1086
|
+
};
|
|
1087
|
+
|
|
1088
|
+
// Copyright (c) Microsoft Corporation.
|
|
1089
|
+
// Licensed under the MIT license.
|
|
1090
|
+
const msiName$4 = "ManagedIdentityCredential - IMDS";
|
|
1091
|
+
const logger$l = credentialLogger(msiName$4);
|
|
1092
|
+
/**
|
|
1093
|
+
* Generates the options used on the request for an access token.
|
|
1094
|
+
*/
|
|
1095
|
+
function prepareRequestOptions$3(scopes, clientId, resourceId, options) {
|
|
1096
|
+
var _a;
|
|
1097
|
+
const resource = mapScopesToResource(scopes);
|
|
1098
|
+
if (!resource) {
|
|
1099
|
+
throw new Error(`${msiName$4}: Multiple scopes are not supported.`);
|
|
1254
1100
|
}
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
scopes,
|
|
1264
|
-
getTokenOptions: options,
|
|
1265
|
-
message: "Silent authentication failed. We couldn't retrieve an active account from the cache.",
|
|
1266
|
-
});
|
|
1267
|
-
}
|
|
1268
|
-
const silentRequest = {
|
|
1269
|
-
// To be able to re-use the account, the Token Cache must also have been provided.
|
|
1270
|
-
account: publicToMsal(this.account),
|
|
1271
|
-
correlationId: options === null || options === void 0 ? void 0 : options.correlationId,
|
|
1272
|
-
scopes,
|
|
1273
|
-
authority: options === null || options === void 0 ? void 0 : options.authority,
|
|
1274
|
-
claims: options === null || options === void 0 ? void 0 : options.claims,
|
|
1101
|
+
const { skipQuery, skipMetadataHeader } = options || {};
|
|
1102
|
+
let query = "";
|
|
1103
|
+
// Pod Identity will try to process this request even if the Metadata header is missing.
|
|
1104
|
+
// We can exclude the request query to ensure no IMDS endpoint tries to process the ping request.
|
|
1105
|
+
if (!skipQuery) {
|
|
1106
|
+
const queryParameters = {
|
|
1107
|
+
resource,
|
|
1108
|
+
"api-version": imdsApiVersion,
|
|
1275
1109
|
};
|
|
1276
|
-
if (
|
|
1277
|
-
|
|
1278
|
-
silentRequest.tokenQueryParameters = {};
|
|
1279
|
-
}
|
|
1280
|
-
if (!this.parentWindowHandle) {
|
|
1281
|
-
// error should have been thrown from within the constructor of InteractiveBrowserCredential
|
|
1282
|
-
this.logger.warning("Parent window handle is not specified for the broker. This may cause unexpected behavior. Please provide the parentWindowHandle.");
|
|
1283
|
-
}
|
|
1284
|
-
if (this.enableMsaPassthrough) {
|
|
1285
|
-
silentRequest.tokenQueryParameters["msal_request_type"] = "consumer_passthrough";
|
|
1286
|
-
}
|
|
1287
|
-
}
|
|
1288
|
-
try {
|
|
1289
|
-
this.logger.info("Attempting to acquire token silently");
|
|
1290
|
-
/**
|
|
1291
|
-
* The following code to retrieve all accounts is done as a workaround in an attempt to force the
|
|
1292
|
-
* refresh of the token cache with the token and the account passed in through the
|
|
1293
|
-
* `authenticationRecord` parameter. See issue - https://github.com/Azure/azure-sdk-for-js/issues/24349#issuecomment-1496715651
|
|
1294
|
-
* This workaround serves as a workaround for silent authentication not happening when authenticationRecord is passed.
|
|
1295
|
-
*/
|
|
1296
|
-
await ((_a = this.getApp("publicFirst", options === null || options === void 0 ? void 0 : options.enableCae)) === null || _a === void 0 ? void 0 : _a.getTokenCache().getAllAccounts());
|
|
1297
|
-
const response = (_c = (await ((_b = this.getApp("confidential", options === null || options === void 0 ? void 0 : options.enableCae)) === null || _b === void 0 ? void 0 : _b.acquireTokenSilent(silentRequest)))) !== null && _c !== void 0 ? _c : (await this.getApp("public", options === null || options === void 0 ? void 0 : options.enableCae).acquireTokenSilent(silentRequest));
|
|
1298
|
-
return this.handleResult(scopes, response || undefined);
|
|
1110
|
+
if (clientId) {
|
|
1111
|
+
queryParameters.client_id = clientId;
|
|
1299
1112
|
}
|
|
1300
|
-
|
|
1301
|
-
|
|
1113
|
+
if (resourceId) {
|
|
1114
|
+
queryParameters.msi_res_id = resourceId;
|
|
1302
1115
|
}
|
|
1116
|
+
const params = new URLSearchParams(queryParameters);
|
|
1117
|
+
query = `?${params.toString()}`;
|
|
1303
1118
|
}
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1119
|
+
const url = new URL(imdsEndpointPath, (_a = process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) !== null && _a !== void 0 ? _a : imdsHost);
|
|
1120
|
+
const rawHeaders = {
|
|
1121
|
+
Accept: "application/json",
|
|
1122
|
+
Metadata: "true",
|
|
1123
|
+
};
|
|
1124
|
+
// Remove the Metadata header to invoke a request error from some IMDS endpoints.
|
|
1125
|
+
if (skipMetadataHeader) {
|
|
1126
|
+
delete rawHeaders.Metadata;
|
|
1127
|
+
}
|
|
1128
|
+
return {
|
|
1129
|
+
// In this case, the `?` should be added in the "query" variable `skipQuery` is not set.
|
|
1130
|
+
url: `${url}${query}`,
|
|
1131
|
+
method: "GET",
|
|
1132
|
+
headers: coreRestPipeline.createHttpHeaders(rawHeaders),
|
|
1133
|
+
};
|
|
1134
|
+
}
|
|
1135
|
+
// 800ms -> 1600ms -> 3200ms
|
|
1136
|
+
const imdsMsiRetryConfig = {
|
|
1137
|
+
maxRetries: 3,
|
|
1138
|
+
startDelayInMs: 800,
|
|
1139
|
+
intervalIncrement: 2,
|
|
1140
|
+
};
|
|
1141
|
+
/**
|
|
1142
|
+
* Defines how to determine whether the Azure IMDS MSI is available, and also how to retrieve a token from the Azure IMDS MSI.
|
|
1143
|
+
*/
|
|
1144
|
+
const imdsMsi = {
|
|
1145
|
+
name: "imdsMsi",
|
|
1146
|
+
async isAvailable({ scopes, identityClient, clientId, resourceId, getTokenOptions = {}, }) {
|
|
1147
|
+
const resource = mapScopesToResource(scopes);
|
|
1148
|
+
if (!resource) {
|
|
1149
|
+
logger$l.info(`${msiName$4}: Unavailable. Multiple scopes are not supported.`);
|
|
1150
|
+
return false;
|
|
1151
|
+
}
|
|
1152
|
+
// if the PodIdentityEndpoint environment variable was set no need to probe the endpoint, it can be assumed to exist
|
|
1153
|
+
if (process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) {
|
|
1154
|
+
return true;
|
|
1155
|
+
}
|
|
1156
|
+
if (!identityClient) {
|
|
1157
|
+
throw new Error("Missing IdentityClient");
|
|
1158
|
+
}
|
|
1159
|
+
const requestOptions = prepareRequestOptions$3(resource, clientId, resourceId, {
|
|
1160
|
+
skipMetadataHeader: true,
|
|
1161
|
+
skipQuery: true,
|
|
1162
|
+
});
|
|
1163
|
+
return tracingClient.withSpan("ManagedIdentityCredential-pingImdsEndpoint", getTokenOptions, async (options) => {
|
|
1164
|
+
var _a, _b;
|
|
1165
|
+
requestOptions.tracingOptions = options.tracingOptions;
|
|
1166
|
+
// Create a request with a timeout since we expect that
|
|
1167
|
+
// not having a "Metadata" header should cause an error to be
|
|
1168
|
+
// returned quickly from the endpoint, proving its availability.
|
|
1169
|
+
const request = coreRestPipeline.createPipelineRequest(requestOptions);
|
|
1170
|
+
// Default to 1000 if the default of 0 is used.
|
|
1171
|
+
// Negative values can still be used to disable the timeout.
|
|
1172
|
+
request.timeout = ((_a = options.requestOptions) === null || _a === void 0 ? void 0 : _a.timeout) || 1000;
|
|
1173
|
+
// This MSI uses the imdsEndpoint to get the token, which only uses http://
|
|
1174
|
+
request.allowInsecureConnection = true;
|
|
1175
|
+
let response;
|
|
1176
|
+
try {
|
|
1177
|
+
logger$l.info(`${msiName$4}: Pinging the Azure IMDS endpoint`);
|
|
1178
|
+
response = await identityClient.sendRequest(request);
|
|
1321
1179
|
}
|
|
1322
|
-
|
|
1323
|
-
|
|
1180
|
+
catch (err) {
|
|
1181
|
+
// If the request failed, or Node.js was unable to establish a connection,
|
|
1182
|
+
// or the host was down, we'll assume the IMDS endpoint isn't available.
|
|
1183
|
+
if (coreUtil.isError(err)) {
|
|
1184
|
+
logger$l.verbose(`${msiName$4}: Caught error ${err.name}: ${err.message}`);
|
|
1185
|
+
}
|
|
1186
|
+
// This is a special case for Docker Desktop which responds with a 403 with a message that contains "A socket operation was attempted to an unreachable network"
|
|
1187
|
+
// rather than just timing out, as expected.
|
|
1188
|
+
logger$l.info(`${msiName$4}: The Azure IMDS endpoint is unavailable`);
|
|
1189
|
+
return false;
|
|
1324
1190
|
}
|
|
1325
|
-
|
|
1326
|
-
|
|
1191
|
+
if (response.status === 403) {
|
|
1192
|
+
if ((_b = response.bodyAsText) === null || _b === void 0 ? void 0 : _b.includes("A socket operation was attempted to an unreachable network")) {
|
|
1193
|
+
logger$l.info(`${msiName$4}: The Azure IMDS endpoint is unavailable`);
|
|
1194
|
+
logger$l.info(`${msiName$4}: ${response.bodyAsText}`);
|
|
1195
|
+
return false;
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
// If we received any response, the endpoint is available
|
|
1199
|
+
logger$l.info(`${msiName$4}: The Azure IMDS endpoint is available`);
|
|
1200
|
+
return true;
|
|
1201
|
+
});
|
|
1202
|
+
},
|
|
1203
|
+
async getToken(configuration, getTokenOptions = {}) {
|
|
1204
|
+
const { identityClient, scopes, clientId, resourceId } = configuration;
|
|
1205
|
+
if (process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) {
|
|
1206
|
+
logger$l.info(`${msiName$4}: Using the Azure IMDS endpoint coming from the environment variable AZURE_POD_IDENTITY_AUTHORITY_HOST=${process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST}.`);
|
|
1327
1207
|
}
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1208
|
+
else {
|
|
1209
|
+
logger$l.info(`${msiName$4}: Using the default Azure IMDS endpoint ${imdsHost}.`);
|
|
1210
|
+
}
|
|
1211
|
+
let nextDelayInMs = imdsMsiRetryConfig.startDelayInMs;
|
|
1212
|
+
for (let retries = 0; retries < imdsMsiRetryConfig.maxRetries; retries++) {
|
|
1213
|
+
try {
|
|
1214
|
+
const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$3(scopes, clientId, resourceId)), { allowInsecureConnection: true }));
|
|
1215
|
+
const tokenResponse = await identityClient.sendTokenRequest(request);
|
|
1216
|
+
return (tokenResponse && tokenResponse.accessToken) || null;
|
|
1331
1217
|
}
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
}
|
|
1218
|
+
catch (error) {
|
|
1219
|
+
if (error.statusCode === 404) {
|
|
1220
|
+
await coreUtil.delay(nextDelayInMs);
|
|
1221
|
+
nextDelayInMs *= imdsMsiRetryConfig.intervalIncrement;
|
|
1222
|
+
continue;
|
|
1223
|
+
}
|
|
1224
|
+
throw error;
|
|
1338
1225
|
}
|
|
1339
|
-
this.logger.info(`Silent authentication failed, falling back to interactive method.`);
|
|
1340
|
-
return this.doGetToken(scopes, options);
|
|
1341
1226
|
}
|
|
1227
|
+
throw new AuthenticationError(404, `${msiName$4}: Failed to retrieve IMDS token after ${imdsMsiRetryConfig.maxRetries} retries.`);
|
|
1228
|
+
},
|
|
1229
|
+
};
|
|
1230
|
+
|
|
1231
|
+
// Copyright (c) Microsoft Corporation.
|
|
1232
|
+
// Licensed under the MIT license.
|
|
1233
|
+
const msiName$3 = "ManagedIdentityCredential - Azure Arc MSI";
|
|
1234
|
+
const logger$k = credentialLogger(msiName$3);
|
|
1235
|
+
/**
|
|
1236
|
+
* Generates the options used on the request for an access token.
|
|
1237
|
+
*/
|
|
1238
|
+
function prepareRequestOptions$2(scopes, clientId, resourceId) {
|
|
1239
|
+
const resource = mapScopesToResource(scopes);
|
|
1240
|
+
if (!resource) {
|
|
1241
|
+
throw new Error(`${msiName$3}: Multiple scopes are not supported.`);
|
|
1342
1242
|
}
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1243
|
+
const queryParameters = {
|
|
1244
|
+
resource,
|
|
1245
|
+
"api-version": azureArcAPIVersion,
|
|
1246
|
+
};
|
|
1247
|
+
if (clientId) {
|
|
1248
|
+
queryParameters.client_id = clientId;
|
|
1249
|
+
}
|
|
1250
|
+
if (resourceId) {
|
|
1251
|
+
queryParameters.msi_res_id = resourceId;
|
|
1252
|
+
}
|
|
1253
|
+
// This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
|
|
1254
|
+
if (!process.env.IDENTITY_ENDPOINT) {
|
|
1255
|
+
throw new Error(`${msiName$3}: Missing environment variable: IDENTITY_ENDPOINT`);
|
|
1256
|
+
}
|
|
1257
|
+
const query = new URLSearchParams(queryParameters);
|
|
1258
|
+
return coreRestPipeline.createPipelineRequest({
|
|
1259
|
+
// Should be similar to: http://localhost:40342/metadata/identity/oauth2/token
|
|
1260
|
+
url: `${process.env.IDENTITY_ENDPOINT}?${query.toString()}`,
|
|
1261
|
+
method: "GET",
|
|
1262
|
+
headers: coreRestPipeline.createHttpHeaders({
|
|
1263
|
+
Accept: "application/json",
|
|
1264
|
+
Metadata: "true",
|
|
1265
|
+
}),
|
|
1266
|
+
});
|
|
1267
|
+
}
|
|
1268
|
+
/**
|
|
1269
|
+
* Retrieves the file contents at the given path using promises.
|
|
1270
|
+
* Useful since `fs`'s readFileSync locks the thread, and to avoid extra dependencies.
|
|
1271
|
+
*/
|
|
1272
|
+
function readFileAsync$1(path, options) {
|
|
1273
|
+
return new Promise((resolve, reject) => fs.readFile(path, options, (err, data) => {
|
|
1274
|
+
if (err) {
|
|
1275
|
+
reject(err);
|
|
1351
1276
|
}
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1277
|
+
resolve(data);
|
|
1278
|
+
}));
|
|
1279
|
+
}
|
|
1280
|
+
/**
|
|
1281
|
+
* Does a request to the authentication provider that results in a file path.
|
|
1282
|
+
*/
|
|
1283
|
+
async function filePathRequest(identityClient, requestPrepareOptions) {
|
|
1284
|
+
const response = await identityClient.sendRequest(coreRestPipeline.createPipelineRequest(requestPrepareOptions));
|
|
1285
|
+
if (response.status !== 401) {
|
|
1286
|
+
let message = "";
|
|
1287
|
+
if (response.bodyAsText) {
|
|
1288
|
+
message = ` Response: ${response.bodyAsText}`;
|
|
1289
|
+
}
|
|
1290
|
+
throw new AuthenticationError(response.status, `${msiName$3}: To authenticate with Azure Arc MSI, status code 401 is expected on the first request. ${message}`);
|
|
1291
|
+
}
|
|
1292
|
+
const authHeader = response.headers.get("www-authenticate") || "";
|
|
1293
|
+
try {
|
|
1294
|
+
return authHeader.split("=").slice(1)[0];
|
|
1295
|
+
}
|
|
1296
|
+
catch (e) {
|
|
1297
|
+
throw Error(`Invalid www-authenticate header format: ${authHeader}`);
|
|
1358
1298
|
}
|
|
1359
1299
|
}
|
|
1300
|
+
/**
|
|
1301
|
+
* Defines how to determine whether the Azure Arc MSI is available, and also how to retrieve a token from the Azure Arc MSI.
|
|
1302
|
+
*/
|
|
1303
|
+
const arcMsi = {
|
|
1304
|
+
name: "arc",
|
|
1305
|
+
async isAvailable({ scopes }) {
|
|
1306
|
+
const resource = mapScopesToResource(scopes);
|
|
1307
|
+
if (!resource) {
|
|
1308
|
+
logger$k.info(`${msiName$3}: Unavailable. Multiple scopes are not supported.`);
|
|
1309
|
+
return false;
|
|
1310
|
+
}
|
|
1311
|
+
const result = Boolean(process.env.IMDS_ENDPOINT && process.env.IDENTITY_ENDPOINT);
|
|
1312
|
+
if (!result) {
|
|
1313
|
+
logger$k.info(`${msiName$3}: The environment variables needed are: IMDS_ENDPOINT and IDENTITY_ENDPOINT`);
|
|
1314
|
+
}
|
|
1315
|
+
return result;
|
|
1316
|
+
},
|
|
1317
|
+
async getToken(configuration, getTokenOptions = {}) {
|
|
1318
|
+
var _a;
|
|
1319
|
+
const { identityClient, scopes, clientId, resourceId } = configuration;
|
|
1320
|
+
if (clientId) {
|
|
1321
|
+
logger$k.warning(`${msiName$3}: user-assigned identities not supported. The argument clientId might be ignored by the service.`);
|
|
1322
|
+
}
|
|
1323
|
+
if (resourceId) {
|
|
1324
|
+
logger$k.warning(`${msiName$3}: user defined managed Identity by resource Id is not supported. Argument resourceId will be ignored.`);
|
|
1325
|
+
}
|
|
1326
|
+
logger$k.info(`${msiName$3}: Authenticating.`);
|
|
1327
|
+
const requestOptions = Object.assign(Object.assign({ disableJsonStringifyOnBody: true, deserializationMapper: undefined, abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$2(scopes, clientId, resourceId)), { allowInsecureConnection: true });
|
|
1328
|
+
const filePath = await filePathRequest(identityClient, requestOptions);
|
|
1329
|
+
if (!filePath) {
|
|
1330
|
+
throw new Error(`${msiName$3}: Failed to find the token file.`);
|
|
1331
|
+
}
|
|
1332
|
+
const key = await readFileAsync$1(filePath, { encoding: "utf-8" });
|
|
1333
|
+
(_a = requestOptions.headers) === null || _a === void 0 ? void 0 : _a.set("Authorization", `Basic ${key}`);
|
|
1334
|
+
const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({}, requestOptions), {
|
|
1335
|
+
// Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS).
|
|
1336
|
+
allowInsecureConnection: true }));
|
|
1337
|
+
const tokenResponse = await identityClient.sendTokenRequest(request);
|
|
1338
|
+
return (tokenResponse && tokenResponse.accessToken) || null;
|
|
1339
|
+
},
|
|
1340
|
+
};
|
|
1360
1341
|
|
|
1361
1342
|
// Copyright (c) Microsoft Corporation.
|
|
1362
1343
|
// Licensed under the MIT license.
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
function
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1344
|
+
/**
|
|
1345
|
+
* @internal
|
|
1346
|
+
*/
|
|
1347
|
+
const logger$j = credentialLogger("IdentityUtils");
|
|
1348
|
+
/**
|
|
1349
|
+
* Latest AuthenticationRecord version
|
|
1350
|
+
* @internal
|
|
1351
|
+
*/
|
|
1352
|
+
const LatestAuthenticationRecordVersion = "1.0";
|
|
1353
|
+
/**
|
|
1354
|
+
* Ensures the validity of the MSAL token
|
|
1355
|
+
* @internal
|
|
1356
|
+
*/
|
|
1357
|
+
function ensureValidMsalToken(scopes, msalToken, getTokenOptions) {
|
|
1358
|
+
const error = (message) => {
|
|
1359
|
+
logger$j.getToken.info(message);
|
|
1360
|
+
return new AuthenticationRequiredError({
|
|
1361
|
+
scopes: Array.isArray(scopes) ? scopes : [scopes],
|
|
1362
|
+
getTokenOptions,
|
|
1363
|
+
message,
|
|
1364
|
+
});
|
|
1365
|
+
};
|
|
1366
|
+
if (!msalToken) {
|
|
1367
|
+
throw error("No response");
|
|
1368
|
+
}
|
|
1369
|
+
if (!msalToken.expiresOn) {
|
|
1370
|
+
throw error(`Response had no "expiresOn" property.`);
|
|
1371
|
+
}
|
|
1372
|
+
if (!msalToken.accessToken) {
|
|
1373
|
+
throw error(`Response had no "accessToken" property.`);
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
/**
|
|
1377
|
+
* Generates a valid authority by combining a host with a tenantId.
|
|
1378
|
+
* @internal
|
|
1379
|
+
*/
|
|
1380
|
+
function getAuthority(tenantId, host) {
|
|
1381
|
+
if (!host) {
|
|
1382
|
+
host = DefaultAuthorityHost;
|
|
1383
|
+
}
|
|
1384
|
+
if (new RegExp(`${tenantId}/?$`).test(host)) {
|
|
1385
|
+
return host;
|
|
1386
|
+
}
|
|
1387
|
+
if (host.endsWith("/")) {
|
|
1388
|
+
return host + tenantId;
|
|
1389
|
+
}
|
|
1390
|
+
else {
|
|
1391
|
+
return `${host}/${tenantId}`;
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
/**
|
|
1395
|
+
* Generates the known authorities.
|
|
1396
|
+
* If the Tenant Id is `adfs`, the authority can't be validated since the format won't match the expected one.
|
|
1397
|
+
* For that reason, we have to force MSAL to disable validating the authority
|
|
1398
|
+
* by sending it within the known authorities in the MSAL configuration.
|
|
1399
|
+
* @internal
|
|
1400
|
+
*/
|
|
1401
|
+
function getKnownAuthorities(tenantId, authorityHost, disableInstanceDiscovery) {
|
|
1402
|
+
if ((tenantId === "adfs" && authorityHost) || disableInstanceDiscovery) {
|
|
1403
|
+
return [authorityHost];
|
|
1381
1404
|
}
|
|
1405
|
+
return [];
|
|
1382
1406
|
}
|
|
1383
|
-
const mapVSCodeAuthorityHosts = {
|
|
1384
|
-
AzureCloud: exports.AzureAuthorityHosts.AzurePublicCloud,
|
|
1385
|
-
AzureChina: exports.AzureAuthorityHosts.AzureChina,
|
|
1386
|
-
AzureGermanCloud: exports.AzureAuthorityHosts.AzureGermany,
|
|
1387
|
-
AzureUSGovernment: exports.AzureAuthorityHosts.AzureGovernment,
|
|
1388
|
-
};
|
|
1389
1407
|
/**
|
|
1390
|
-
*
|
|
1391
|
-
*
|
|
1408
|
+
* Generates a logger that can be passed to the MSAL clients.
|
|
1409
|
+
* @param credLogger - The logger of the credential.
|
|
1410
|
+
* @internal
|
|
1392
1411
|
*/
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
const vsCodeFolder = "Code";
|
|
1397
|
-
const homedir = os.homedir();
|
|
1398
|
-
function loadProperty(...pathSegments) {
|
|
1399
|
-
const fullPath = path.join(...pathSegments, vsCodeFolder, ...settingsPath);
|
|
1400
|
-
const settings = JSON.parse(fs.readFileSync(fullPath, { encoding: "utf8" }));
|
|
1401
|
-
return settings[property];
|
|
1412
|
+
const defaultLoggerCallback = (credLogger, platform = coreUtil.isNode ? "Node" : "Browser") => (level, message, containsPii) => {
|
|
1413
|
+
if (containsPii) {
|
|
1414
|
+
return;
|
|
1402
1415
|
}
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
+
switch (level) {
|
|
1417
|
+
case msalCommon__namespace.LogLevel.Error:
|
|
1418
|
+
credLogger.info(`MSAL ${platform} V2 error: ${message}`);
|
|
1419
|
+
return;
|
|
1420
|
+
case msalCommon__namespace.LogLevel.Info:
|
|
1421
|
+
credLogger.info(`MSAL ${platform} V2 info message: ${message}`);
|
|
1422
|
+
return;
|
|
1423
|
+
case msalCommon__namespace.LogLevel.Verbose:
|
|
1424
|
+
credLogger.info(`MSAL ${platform} V2 verbose message: ${message}`);
|
|
1425
|
+
return;
|
|
1426
|
+
case msalCommon__namespace.LogLevel.Warning:
|
|
1427
|
+
credLogger.info(`MSAL ${platform} V2 warning: ${message}`);
|
|
1428
|
+
return;
|
|
1416
1429
|
}
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1430
|
+
};
|
|
1431
|
+
/**
|
|
1432
|
+
* @internal
|
|
1433
|
+
*/
|
|
1434
|
+
function getMSALLogLevel(logLevel) {
|
|
1435
|
+
switch (logLevel) {
|
|
1436
|
+
case "error":
|
|
1437
|
+
return msalCommon__namespace.LogLevel.Error;
|
|
1438
|
+
case "info":
|
|
1439
|
+
return msalCommon__namespace.LogLevel.Info;
|
|
1440
|
+
case "verbose":
|
|
1441
|
+
return msalCommon__namespace.LogLevel.Verbose;
|
|
1442
|
+
case "warning":
|
|
1443
|
+
return msalCommon__namespace.LogLevel.Warning;
|
|
1444
|
+
default:
|
|
1445
|
+
// default msal logging level should be Info
|
|
1446
|
+
return msalCommon__namespace.LogLevel.Info;
|
|
1420
1447
|
}
|
|
1421
1448
|
}
|
|
1422
1449
|
/**
|
|
1423
|
-
*
|
|
1424
|
-
*
|
|
1425
|
-
* that is cached by the extension.
|
|
1450
|
+
* Wraps core-util's randomUUID in order to allow for mocking in tests.
|
|
1451
|
+
* This prepares the library for the upcoming core-util update to ESM.
|
|
1426
1452
|
*
|
|
1427
|
-
*
|
|
1428
|
-
*
|
|
1429
|
-
* versions newer than **0.9.11**. A long-term fix to this problem is in progress. In the meantime, consider
|
|
1430
|
-
* authenticating with {@link AzureCliCredential}.
|
|
1453
|
+
* @internal
|
|
1454
|
+
* @returns A string containing a random UUID
|
|
1431
1455
|
*/
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants);
|
|
1458
|
-
checkUnsupportedTenant(this.tenantId);
|
|
1459
|
-
}
|
|
1460
|
-
/**
|
|
1461
|
-
* Runs preparations for any further getToken request.
|
|
1462
|
-
*/
|
|
1463
|
-
async prepare() {
|
|
1464
|
-
// Attempts to load the tenant from the VSCode configuration file.
|
|
1465
|
-
const settingsTenant = getPropertyFromVSCode("azure.tenant");
|
|
1466
|
-
if (settingsTenant) {
|
|
1467
|
-
this.tenantId = settingsTenant;
|
|
1456
|
+
function randomUUID() {
|
|
1457
|
+
return coreUtil.randomUUID();
|
|
1458
|
+
}
|
|
1459
|
+
/**
|
|
1460
|
+
* Handles MSAL errors.
|
|
1461
|
+
*/
|
|
1462
|
+
function handleMsalError(scopes, error, getTokenOptions) {
|
|
1463
|
+
if (error.name === "AuthError" ||
|
|
1464
|
+
error.name === "ClientAuthError" ||
|
|
1465
|
+
error.name === "BrowserAuthError") {
|
|
1466
|
+
const msalError = error;
|
|
1467
|
+
switch (msalError.errorCode) {
|
|
1468
|
+
case "endpoints_resolution_error":
|
|
1469
|
+
logger$j.info(formatError(scopes, error.message));
|
|
1470
|
+
return new CredentialUnavailableError(error.message);
|
|
1471
|
+
case "device_code_polling_cancelled":
|
|
1472
|
+
return new abortController.AbortError("The authentication has been aborted by the caller.");
|
|
1473
|
+
case "consent_required":
|
|
1474
|
+
case "interaction_required":
|
|
1475
|
+
case "login_required":
|
|
1476
|
+
logger$j.info(formatError(scopes, `Authentication returned errorCode ${msalError.errorCode}`));
|
|
1477
|
+
break;
|
|
1478
|
+
default:
|
|
1479
|
+
logger$j.info(formatError(scopes, `Failed to acquire token: ${error.message}`));
|
|
1480
|
+
break;
|
|
1468
1481
|
}
|
|
1469
|
-
checkUnsupportedTenant(this.tenantId);
|
|
1470
1482
|
}
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
if (!this.preparePromise) {
|
|
1476
|
-
this.preparePromise = this.prepare();
|
|
1477
|
-
}
|
|
1478
|
-
return this.preparePromise;
|
|
1483
|
+
if (error.name === "ClientConfigurationError" ||
|
|
1484
|
+
error.name === "BrowserConfigurationAuthError" ||
|
|
1485
|
+
error.name === "AbortError") {
|
|
1486
|
+
return error;
|
|
1479
1487
|
}
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
*
|
|
1484
|
-
* @param scopes - The list of scopes for which the token will have access.
|
|
1485
|
-
* @param options - The options used to configure any requests this
|
|
1486
|
-
* `TokenCredential` implementation might make.
|
|
1487
|
-
*/
|
|
1488
|
-
async getToken(scopes, options) {
|
|
1489
|
-
var _a, _b;
|
|
1490
|
-
await this.prepareOnce();
|
|
1491
|
-
const tenantId = processMultiTenantRequest(this.tenantId, options, this.additionallyAllowedTenantIds, logger$n) || this.tenantId;
|
|
1492
|
-
if (findCredentials === undefined) {
|
|
1493
|
-
throw new CredentialUnavailableError([
|
|
1494
|
-
"No implementation of `VisualStudioCodeCredential` is available.",
|
|
1495
|
-
"You must install the identity-vscode plugin package (`npm install --save-dev @azure/identity-vscode`)",
|
|
1496
|
-
"and enable it by importing `useIdentityPlugin` from `@azure/identity` and calling",
|
|
1497
|
-
"`useIdentityPlugin(vsCodePlugin)` before creating a `VisualStudioCodeCredential`.",
|
|
1498
|
-
"To troubleshoot, visit https://aka.ms/azsdk/js/identity/vscodecredential/troubleshoot.",
|
|
1499
|
-
].join(" "));
|
|
1500
|
-
}
|
|
1501
|
-
let scopeString = typeof scopes === "string" ? scopes : scopes.join(" ");
|
|
1502
|
-
// Check to make sure the scope we get back is a valid scope
|
|
1503
|
-
if (!scopeString.match(/^[0-9a-zA-Z-.:/]+$/)) {
|
|
1504
|
-
const error = new Error("Invalid scope was specified by the user or calling client");
|
|
1505
|
-
logger$n.getToken.info(formatError(scopes, error));
|
|
1506
|
-
throw error;
|
|
1507
|
-
}
|
|
1508
|
-
if (scopeString.indexOf("offline_access") < 0) {
|
|
1509
|
-
scopeString += " offline_access";
|
|
1510
|
-
}
|
|
1511
|
-
// findCredentials returns an array similar to:
|
|
1512
|
-
// [
|
|
1513
|
-
// {
|
|
1514
|
-
// account: "",
|
|
1515
|
-
// password: "",
|
|
1516
|
-
// },
|
|
1517
|
-
// /* ... */
|
|
1518
|
-
// ]
|
|
1519
|
-
const credentials = await findCredentials();
|
|
1520
|
-
// If we can't find the credential based on the name, we'll pick the first one available.
|
|
1521
|
-
const { password: refreshToken } = (_b = (_a = credentials.find(({ account }) => account === this.cloudName)) !== null && _a !== void 0 ? _a : credentials[0]) !== null && _b !== void 0 ? _b : {};
|
|
1522
|
-
if (refreshToken) {
|
|
1523
|
-
const tokenResponse = await this.identityClient.refreshAccessToken(tenantId, AzureAccountClientId, scopeString, refreshToken, undefined);
|
|
1524
|
-
if (tokenResponse) {
|
|
1525
|
-
logger$n.getToken.info(formatSuccess(scopes));
|
|
1526
|
-
return tokenResponse.accessToken;
|
|
1527
|
-
}
|
|
1528
|
-
else {
|
|
1529
|
-
const error = new CredentialUnavailableError("Could not retrieve the token associated with Visual Studio Code. Have you connected using the 'Azure Account' extension recently? To troubleshoot, visit https://aka.ms/azsdk/js/identity/vscodecredential/troubleshoot.");
|
|
1530
|
-
logger$n.getToken.info(formatError(scopes, error));
|
|
1531
|
-
throw error;
|
|
1532
|
-
}
|
|
1533
|
-
}
|
|
1534
|
-
else {
|
|
1535
|
-
const error = new CredentialUnavailableError("Could not retrieve the token associated with Visual Studio Code. Did you connect using the 'Azure Account' extension? To troubleshoot, visit https://aka.ms/azsdk/js/identity/vscodecredential/troubleshoot.");
|
|
1536
|
-
logger$n.getToken.info(formatError(scopes, error));
|
|
1537
|
-
throw error;
|
|
1538
|
-
}
|
|
1488
|
+
if (error.name === "NativeAuthError") {
|
|
1489
|
+
logger$j.info(formatError(scopes, `Error from the native broker: ${error.message} with status code: ${error.statusCode}`));
|
|
1490
|
+
return error;
|
|
1539
1491
|
}
|
|
1492
|
+
return new AuthenticationRequiredError({ scopes, getTokenOptions, message: error.message });
|
|
1493
|
+
}
|
|
1494
|
+
// transformations.ts
|
|
1495
|
+
function publicToMsal(account) {
|
|
1496
|
+
const [environment] = account.authority.match(/([a-z]*\.[a-z]*\.[a-z]*)/) || [""];
|
|
1497
|
+
return Object.assign(Object.assign({}, account), { localAccountId: account.homeAccountId, environment });
|
|
1498
|
+
}
|
|
1499
|
+
function msalToPublic(clientId, account) {
|
|
1500
|
+
const record = {
|
|
1501
|
+
authority: getAuthority(account.tenantId, account.environment),
|
|
1502
|
+
homeAccountId: account.homeAccountId,
|
|
1503
|
+
tenantId: account.tenantId || DefaultTenantId,
|
|
1504
|
+
username: account.username,
|
|
1505
|
+
clientId,
|
|
1506
|
+
version: LatestAuthenticationRecordVersion,
|
|
1507
|
+
};
|
|
1508
|
+
return record;
|
|
1540
1509
|
}
|
|
1541
|
-
|
|
1542
|
-
// Copyright (c) Microsoft Corporation.
|
|
1543
|
-
// Licensed under the MIT license.
|
|
1544
|
-
/**
|
|
1545
|
-
* The context passed to an Identity plugin. This contains objects that
|
|
1546
|
-
* plugins can use to set backend implementations.
|
|
1547
|
-
* @internal
|
|
1548
|
-
*/
|
|
1549
|
-
const pluginContext = {
|
|
1550
|
-
cachePluginControl: msalNodeFlowCacheControl,
|
|
1551
|
-
nativeBrokerPluginControl: msalNodeFlowNativeBrokerControl,
|
|
1552
|
-
vsCodeCredentialControl: vsCodeCredentialControl,
|
|
1553
|
-
};
|
|
1554
1510
|
/**
|
|
1555
|
-
*
|
|
1556
|
-
* a plugin package, such as:
|
|
1557
|
-
*
|
|
1558
|
-
* - `@azure/identity-cache-persistence`: provides persistent token caching
|
|
1559
|
-
* - `@azure/identity-vscode`: provides the dependencies of
|
|
1560
|
-
* `VisualStudioCodeCredential` and enables it
|
|
1561
|
-
*
|
|
1562
|
-
* Example:
|
|
1563
|
-
*
|
|
1564
|
-
* ```javascript
|
|
1565
|
-
* import { cachePersistencePlugin } from "@azure/identity-cache-persistence";
|
|
1511
|
+
* Serializes an `AuthenticationRecord` into a string.
|
|
1566
1512
|
*
|
|
1567
|
-
*
|
|
1568
|
-
* useIdentityPlugin(cachePersistencePlugin);
|
|
1513
|
+
* The output of a serialized authentication record will contain the following properties:
|
|
1569
1514
|
*
|
|
1570
|
-
*
|
|
1571
|
-
*
|
|
1572
|
-
*
|
|
1573
|
-
*
|
|
1574
|
-
*
|
|
1575
|
-
*
|
|
1576
|
-
* });
|
|
1577
|
-
* ```
|
|
1515
|
+
* - "authority"
|
|
1516
|
+
* - "homeAccountId"
|
|
1517
|
+
* - "clientId"
|
|
1518
|
+
* - "tenantId"
|
|
1519
|
+
* - "username"
|
|
1520
|
+
* - "version"
|
|
1578
1521
|
*
|
|
1579
|
-
*
|
|
1522
|
+
* To later convert this string to a serialized `AuthenticationRecord`, please use the exported function `deserializeAuthenticationRecord()`.
|
|
1580
1523
|
*/
|
|
1581
|
-
function
|
|
1582
|
-
|
|
1524
|
+
function serializeAuthenticationRecord(record) {
|
|
1525
|
+
return JSON.stringify(record);
|
|
1583
1526
|
}
|
|
1584
|
-
|
|
1585
|
-
// Copyright (c) Microsoft Corporation.
|
|
1586
|
-
// Licensed under the MIT license.
|
|
1587
|
-
const msiName$6 = "ManagedIdentityCredential - AppServiceMSI 2017";
|
|
1588
|
-
const logger$m = credentialLogger(msiName$6);
|
|
1589
1527
|
/**
|
|
1590
|
-
*
|
|
1528
|
+
* Deserializes a previously serialized authentication record from a string into an object.
|
|
1529
|
+
*
|
|
1530
|
+
* The input string must contain the following properties:
|
|
1531
|
+
*
|
|
1532
|
+
* - "authority"
|
|
1533
|
+
* - "homeAccountId"
|
|
1534
|
+
* - "clientId"
|
|
1535
|
+
* - "tenantId"
|
|
1536
|
+
* - "username"
|
|
1537
|
+
* - "version"
|
|
1538
|
+
*
|
|
1539
|
+
* If the version we receive is unsupported, an error will be thrown.
|
|
1540
|
+
*
|
|
1541
|
+
* At the moment, the only available version is: "1.0", which is always set when the authentication record is serialized.
|
|
1542
|
+
*
|
|
1543
|
+
* @param serializedRecord - Authentication record previously serialized into string.
|
|
1544
|
+
* @returns AuthenticationRecord.
|
|
1591
1545
|
*/
|
|
1592
|
-
function
|
|
1593
|
-
const
|
|
1594
|
-
if (
|
|
1595
|
-
throw
|
|
1596
|
-
}
|
|
1597
|
-
const queryParameters = {
|
|
1598
|
-
resource,
|
|
1599
|
-
"api-version": "2017-09-01",
|
|
1600
|
-
};
|
|
1601
|
-
if (clientId) {
|
|
1602
|
-
queryParameters.clientid = clientId;
|
|
1603
|
-
}
|
|
1604
|
-
const query = new URLSearchParams(queryParameters);
|
|
1605
|
-
// This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
|
|
1606
|
-
if (!process.env.MSI_ENDPOINT) {
|
|
1607
|
-
throw new Error(`${msiName$6}: Missing environment variable: MSI_ENDPOINT`);
|
|
1608
|
-
}
|
|
1609
|
-
if (!process.env.MSI_SECRET) {
|
|
1610
|
-
throw new Error(`${msiName$6}: Missing environment variable: MSI_SECRET`);
|
|
1546
|
+
function deserializeAuthenticationRecord(serializedRecord) {
|
|
1547
|
+
const parsed = JSON.parse(serializedRecord);
|
|
1548
|
+
if (parsed.version && parsed.version !== LatestAuthenticationRecordVersion) {
|
|
1549
|
+
throw Error("Unsupported AuthenticationRecord version");
|
|
1611
1550
|
}
|
|
1612
|
-
return
|
|
1613
|
-
url: `${process.env.MSI_ENDPOINT}?${query.toString()}`,
|
|
1614
|
-
method: "GET",
|
|
1615
|
-
headers: coreRestPipeline.createHttpHeaders({
|
|
1616
|
-
Accept: "application/json",
|
|
1617
|
-
secret: process.env.MSI_SECRET,
|
|
1618
|
-
}),
|
|
1619
|
-
};
|
|
1551
|
+
return parsed;
|
|
1620
1552
|
}
|
|
1621
|
-
/**
|
|
1622
|
-
* Defines how to determine whether the Azure App Service MSI is available, and also how to retrieve a token from the Azure App Service MSI.
|
|
1623
|
-
*/
|
|
1624
|
-
const appServiceMsi2017 = {
|
|
1625
|
-
name: "appServiceMsi2017",
|
|
1626
|
-
async isAvailable({ scopes }) {
|
|
1627
|
-
const resource = mapScopesToResource(scopes);
|
|
1628
|
-
if (!resource) {
|
|
1629
|
-
logger$m.info(`${msiName$6}: Unavailable. Multiple scopes are not supported.`);
|
|
1630
|
-
return false;
|
|
1631
|
-
}
|
|
1632
|
-
const env = process.env;
|
|
1633
|
-
const result = Boolean(env.MSI_ENDPOINT && env.MSI_SECRET);
|
|
1634
|
-
if (!result) {
|
|
1635
|
-
logger$m.info(`${msiName$6}: Unavailable. The environment variables needed are: MSI_ENDPOINT and MSI_SECRET.`);
|
|
1636
|
-
}
|
|
1637
|
-
return result;
|
|
1638
|
-
},
|
|
1639
|
-
async getToken(configuration, getTokenOptions = {}) {
|
|
1640
|
-
const { identityClient, scopes, clientId, resourceId } = configuration;
|
|
1641
|
-
if (resourceId) {
|
|
1642
|
-
logger$m.warning(`${msiName$6}: managed Identity by resource Id is not supported. Argument resourceId might be ignored by the service.`);
|
|
1643
|
-
}
|
|
1644
|
-
logger$m.info(`${msiName$6}: Using the endpoint and the secret coming form the environment variables: MSI_ENDPOINT=${process.env.MSI_ENDPOINT} and MSI_SECRET=[REDACTED].`);
|
|
1645
|
-
const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$5(scopes, clientId)), {
|
|
1646
|
-
// Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS).
|
|
1647
|
-
allowInsecureConnection: true }));
|
|
1648
|
-
const tokenResponse = await identityClient.sendTokenRequest(request);
|
|
1649
|
-
return (tokenResponse && tokenResponse.accessToken) || null;
|
|
1650
|
-
},
|
|
1651
|
-
};
|
|
1652
1553
|
|
|
1653
1554
|
// Copyright (c) Microsoft Corporation.
|
|
1654
1555
|
// Licensed under the MIT license.
|
|
1655
|
-
const msiName$5 = "ManagedIdentityCredential - CloudShellMSI";
|
|
1656
|
-
const logger$l = credentialLogger(msiName$5);
|
|
1657
|
-
/**
|
|
1658
|
-
* Generates the options used on the request for an access token.
|
|
1659
|
-
*/
|
|
1660
|
-
function prepareRequestOptions$4(scopes, clientId, resourceId) {
|
|
1661
|
-
const resource = mapScopesToResource(scopes);
|
|
1662
|
-
if (!resource) {
|
|
1663
|
-
throw new Error(`${msiName$5}: Multiple scopes are not supported.`);
|
|
1664
|
-
}
|
|
1665
|
-
const body = {
|
|
1666
|
-
resource,
|
|
1667
|
-
};
|
|
1668
|
-
if (clientId) {
|
|
1669
|
-
body.client_id = clientId;
|
|
1670
|
-
}
|
|
1671
|
-
if (resourceId) {
|
|
1672
|
-
body.msi_res_id = resourceId;
|
|
1673
|
-
}
|
|
1674
|
-
// This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
|
|
1675
|
-
if (!process.env.MSI_ENDPOINT) {
|
|
1676
|
-
throw new Error(`${msiName$5}: Missing environment variable: MSI_ENDPOINT`);
|
|
1677
|
-
}
|
|
1678
|
-
const params = new URLSearchParams(body);
|
|
1679
|
-
return {
|
|
1680
|
-
url: process.env.MSI_ENDPOINT,
|
|
1681
|
-
method: "POST",
|
|
1682
|
-
body: params.toString(),
|
|
1683
|
-
headers: coreRestPipeline.createHttpHeaders({
|
|
1684
|
-
Accept: "application/json",
|
|
1685
|
-
Metadata: "true",
|
|
1686
|
-
"Content-Type": "application/x-www-form-urlencoded",
|
|
1687
|
-
}),
|
|
1688
|
-
};
|
|
1689
|
-
}
|
|
1690
1556
|
/**
|
|
1691
|
-
*
|
|
1692
|
-
* Since Azure Managed Identities aren't available in the Azure Cloud Shell, we log a warning for users that try to access cloud shell using user assigned identity.
|
|
1557
|
+
* Helps specify a regional authority, or "AutoDiscoverRegion" to auto-detect the region.
|
|
1693
1558
|
*/
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
}
|
|
1723
|
-
|
|
1559
|
+
var RegionalAuthority;
|
|
1560
|
+
(function (RegionalAuthority) {
|
|
1561
|
+
/** Instructs MSAL to attempt to discover the region */
|
|
1562
|
+
RegionalAuthority["AutoDiscoverRegion"] = "AutoDiscoverRegion";
|
|
1563
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'westus' region. */
|
|
1564
|
+
RegionalAuthority["USWest"] = "westus";
|
|
1565
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'westus2' region. */
|
|
1566
|
+
RegionalAuthority["USWest2"] = "westus2";
|
|
1567
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'centralus' region. */
|
|
1568
|
+
RegionalAuthority["USCentral"] = "centralus";
|
|
1569
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'eastus' region. */
|
|
1570
|
+
RegionalAuthority["USEast"] = "eastus";
|
|
1571
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'eastus2' region. */
|
|
1572
|
+
RegionalAuthority["USEast2"] = "eastus2";
|
|
1573
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'northcentralus' region. */
|
|
1574
|
+
RegionalAuthority["USNorthCentral"] = "northcentralus";
|
|
1575
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'southcentralus' region. */
|
|
1576
|
+
RegionalAuthority["USSouthCentral"] = "southcentralus";
|
|
1577
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'westcentralus' region. */
|
|
1578
|
+
RegionalAuthority["USWestCentral"] = "westcentralus";
|
|
1579
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'canadacentral' region. */
|
|
1580
|
+
RegionalAuthority["CanadaCentral"] = "canadacentral";
|
|
1581
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'canadaeast' region. */
|
|
1582
|
+
RegionalAuthority["CanadaEast"] = "canadaeast";
|
|
1583
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'brazilsouth' region. */
|
|
1584
|
+
RegionalAuthority["BrazilSouth"] = "brazilsouth";
|
|
1585
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'northeurope' region. */
|
|
1586
|
+
RegionalAuthority["EuropeNorth"] = "northeurope";
|
|
1587
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'westeurope' region. */
|
|
1588
|
+
RegionalAuthority["EuropeWest"] = "westeurope";
|
|
1589
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'uksouth' region. */
|
|
1590
|
+
RegionalAuthority["UKSouth"] = "uksouth";
|
|
1591
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'ukwest' region. */
|
|
1592
|
+
RegionalAuthority["UKWest"] = "ukwest";
|
|
1593
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'francecentral' region. */
|
|
1594
|
+
RegionalAuthority["FranceCentral"] = "francecentral";
|
|
1595
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'francesouth' region. */
|
|
1596
|
+
RegionalAuthority["FranceSouth"] = "francesouth";
|
|
1597
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'switzerlandnorth' region. */
|
|
1598
|
+
RegionalAuthority["SwitzerlandNorth"] = "switzerlandnorth";
|
|
1599
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'switzerlandwest' region. */
|
|
1600
|
+
RegionalAuthority["SwitzerlandWest"] = "switzerlandwest";
|
|
1601
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'germanynorth' region. */
|
|
1602
|
+
RegionalAuthority["GermanyNorth"] = "germanynorth";
|
|
1603
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'germanywestcentral' region. */
|
|
1604
|
+
RegionalAuthority["GermanyWestCentral"] = "germanywestcentral";
|
|
1605
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'norwaywest' region. */
|
|
1606
|
+
RegionalAuthority["NorwayWest"] = "norwaywest";
|
|
1607
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'norwayeast' region. */
|
|
1608
|
+
RegionalAuthority["NorwayEast"] = "norwayeast";
|
|
1609
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'eastasia' region. */
|
|
1610
|
+
RegionalAuthority["AsiaEast"] = "eastasia";
|
|
1611
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'southeastasia' region. */
|
|
1612
|
+
RegionalAuthority["AsiaSouthEast"] = "southeastasia";
|
|
1613
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'japaneast' region. */
|
|
1614
|
+
RegionalAuthority["JapanEast"] = "japaneast";
|
|
1615
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'japanwest' region. */
|
|
1616
|
+
RegionalAuthority["JapanWest"] = "japanwest";
|
|
1617
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'australiaeast' region. */
|
|
1618
|
+
RegionalAuthority["AustraliaEast"] = "australiaeast";
|
|
1619
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'australiasoutheast' region. */
|
|
1620
|
+
RegionalAuthority["AustraliaSouthEast"] = "australiasoutheast";
|
|
1621
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'australiacentral' region. */
|
|
1622
|
+
RegionalAuthority["AustraliaCentral"] = "australiacentral";
|
|
1623
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'australiacentral2' region. */
|
|
1624
|
+
RegionalAuthority["AustraliaCentral2"] = "australiacentral2";
|
|
1625
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'centralindia' region. */
|
|
1626
|
+
RegionalAuthority["IndiaCentral"] = "centralindia";
|
|
1627
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'southindia' region. */
|
|
1628
|
+
RegionalAuthority["IndiaSouth"] = "southindia";
|
|
1629
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'westindia' region. */
|
|
1630
|
+
RegionalAuthority["IndiaWest"] = "westindia";
|
|
1631
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'koreasouth' region. */
|
|
1632
|
+
RegionalAuthority["KoreaSouth"] = "koreasouth";
|
|
1633
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'koreacentral' region. */
|
|
1634
|
+
RegionalAuthority["KoreaCentral"] = "koreacentral";
|
|
1635
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'uaecentral' region. */
|
|
1636
|
+
RegionalAuthority["UAECentral"] = "uaecentral";
|
|
1637
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'uaenorth' region. */
|
|
1638
|
+
RegionalAuthority["UAENorth"] = "uaenorth";
|
|
1639
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'southafricanorth' region. */
|
|
1640
|
+
RegionalAuthority["SouthAfricaNorth"] = "southafricanorth";
|
|
1641
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'southafricawest' region. */
|
|
1642
|
+
RegionalAuthority["SouthAfricaWest"] = "southafricawest";
|
|
1643
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'chinanorth' region. */
|
|
1644
|
+
RegionalAuthority["ChinaNorth"] = "chinanorth";
|
|
1645
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'chinaeast' region. */
|
|
1646
|
+
RegionalAuthority["ChinaEast"] = "chinaeast";
|
|
1647
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'chinanorth2' region. */
|
|
1648
|
+
RegionalAuthority["ChinaNorth2"] = "chinanorth2";
|
|
1649
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'chinaeast2' region. */
|
|
1650
|
+
RegionalAuthority["ChinaEast2"] = "chinaeast2";
|
|
1651
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'germanycentral' region. */
|
|
1652
|
+
RegionalAuthority["GermanyCentral"] = "germanycentral";
|
|
1653
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'germanynortheast' region. */
|
|
1654
|
+
RegionalAuthority["GermanyNorthEast"] = "germanynortheast";
|
|
1655
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'usgovvirginia' region. */
|
|
1656
|
+
RegionalAuthority["GovernmentUSVirginia"] = "usgovvirginia";
|
|
1657
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'usgoviowa' region. */
|
|
1658
|
+
RegionalAuthority["GovernmentUSIowa"] = "usgoviowa";
|
|
1659
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'usgovarizona' region. */
|
|
1660
|
+
RegionalAuthority["GovernmentUSArizona"] = "usgovarizona";
|
|
1661
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'usgovtexas' region. */
|
|
1662
|
+
RegionalAuthority["GovernmentUSTexas"] = "usgovtexas";
|
|
1663
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'usdodeast' region. */
|
|
1664
|
+
RegionalAuthority["GovernmentUSDodEast"] = "usdodeast";
|
|
1665
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'usdodcentral' region. */
|
|
1666
|
+
RegionalAuthority["GovernmentUSDodCentral"] = "usdodcentral";
|
|
1667
|
+
})(RegionalAuthority || (RegionalAuthority = {}));
|
|
1724
1668
|
|
|
1725
1669
|
// Copyright (c) Microsoft Corporation.
|
|
1726
1670
|
// Licensed under the MIT license.
|
|
1727
|
-
const msiName$4 = "ManagedIdentityCredential - IMDS";
|
|
1728
|
-
const logger$k = credentialLogger(msiName$4);
|
|
1729
1671
|
/**
|
|
1730
|
-
*
|
|
1672
|
+
* MSAL partial base client for Node.js.
|
|
1673
|
+
*
|
|
1674
|
+
* It completes the input configuration with some default values.
|
|
1675
|
+
* It also provides with utility protected methods that can be used from any of the clients,
|
|
1676
|
+
* which includes handlers for successful responses and errors.
|
|
1677
|
+
*
|
|
1678
|
+
* @internal
|
|
1731
1679
|
*/
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1680
|
+
class MsalNode {
|
|
1681
|
+
constructor(options) {
|
|
1682
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1683
|
+
this.app = {};
|
|
1684
|
+
this.caeApp = {};
|
|
1685
|
+
this.requiresConfidential = false;
|
|
1686
|
+
this.logger = options.logger;
|
|
1687
|
+
this.msalConfig = this.defaultNodeMsalConfig(options);
|
|
1688
|
+
this.tenantId = resolveTenantId(options.logger, options.tenantId, options.clientId);
|
|
1689
|
+
this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds((_a = options === null || options === void 0 ? void 0 : options.tokenCredentialOptions) === null || _a === void 0 ? void 0 : _a.additionallyAllowedTenants);
|
|
1690
|
+
this.clientId = this.msalConfig.auth.clientId;
|
|
1691
|
+
if (options === null || options === void 0 ? void 0 : options.getAssertion) {
|
|
1692
|
+
this.getAssertion = options.getAssertion;
|
|
1693
|
+
}
|
|
1694
|
+
this.enableBroker = (_b = options === null || options === void 0 ? void 0 : options.brokerOptions) === null || _b === void 0 ? void 0 : _b.enabled;
|
|
1695
|
+
this.enableMsaPassthrough = (_c = options === null || options === void 0 ? void 0 : options.brokerOptions) === null || _c === void 0 ? void 0 : _c.legacyEnableMsaPassthrough;
|
|
1696
|
+
this.parentWindowHandle = (_d = options.brokerOptions) === null || _d === void 0 ? void 0 : _d.parentWindowHandle;
|
|
1697
|
+
// If persistence has been configured
|
|
1698
|
+
if (persistenceProvider !== undefined && ((_e = options.tokenCachePersistenceOptions) === null || _e === void 0 ? void 0 : _e.enabled)) {
|
|
1699
|
+
const nonCaeOptions = Object.assign({ name: `${options.tokenCachePersistenceOptions.name}.${CACHE_NON_CAE_SUFFIX}` }, options.tokenCachePersistenceOptions);
|
|
1700
|
+
const caeOptions = Object.assign({ name: `${options.tokenCachePersistenceOptions.name}.${CACHE_CAE_SUFFIX}` }, options.tokenCachePersistenceOptions);
|
|
1701
|
+
this.createCachePlugin = () => persistenceProvider(nonCaeOptions);
|
|
1702
|
+
this.createCachePluginCae = () => persistenceProvider(caeOptions);
|
|
1703
|
+
}
|
|
1704
|
+
else if ((_f = options.tokenCachePersistenceOptions) === null || _f === void 0 ? void 0 : _f.enabled) {
|
|
1705
|
+
throw new Error([
|
|
1706
|
+
"Persistent token caching was requested, but no persistence provider was configured.",
|
|
1707
|
+
"You must install the identity-cache-persistence plugin package (`npm install --save @azure/identity-cache-persistence`)",
|
|
1708
|
+
"and enable it by importing `useIdentityPlugin` from `@azure/identity` and calling",
|
|
1709
|
+
"`useIdentityPlugin(cachePersistencePlugin)` before using `tokenCachePersistenceOptions`.",
|
|
1710
|
+
].join(" "));
|
|
1711
|
+
}
|
|
1712
|
+
// If broker has not been configured
|
|
1713
|
+
if (!hasNativeBroker() && this.enableBroker) {
|
|
1714
|
+
throw new Error([
|
|
1715
|
+
"Broker for WAM was requested to be enabled, but no native broker was configured.",
|
|
1716
|
+
"You must install the identity-broker plugin package (`npm install --save @azure/identity-broker`)",
|
|
1717
|
+
"and enable it by importing `useIdentityPlugin` from `@azure/identity` and calling",
|
|
1718
|
+
"`useIdentityPlugin(createNativeBrokerPlugin())` before using `enableBroker`.",
|
|
1719
|
+
].join(" "));
|
|
1720
|
+
}
|
|
1721
|
+
this.azureRegion = (_g = options.regionalAuthority) !== null && _g !== void 0 ? _g : process.env.AZURE_REGIONAL_AUTHORITY_NAME;
|
|
1722
|
+
if (this.azureRegion === RegionalAuthority.AutoDiscoverRegion) {
|
|
1723
|
+
this.azureRegion = "AUTO_DISCOVER";
|
|
1724
|
+
}
|
|
1737
1725
|
}
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
const
|
|
1744
|
-
|
|
1745
|
-
|
|
1726
|
+
/**
|
|
1727
|
+
* Generates a MSAL configuration that generally works for Node.js
|
|
1728
|
+
*/
|
|
1729
|
+
defaultNodeMsalConfig(options) {
|
|
1730
|
+
var _a;
|
|
1731
|
+
const clientId = options.clientId || DeveloperSignOnClientId;
|
|
1732
|
+
const tenantId = resolveTenantId(options.logger, options.tenantId, options.clientId);
|
|
1733
|
+
this.authorityHost = options.authorityHost || process.env.AZURE_AUTHORITY_HOST;
|
|
1734
|
+
const authority = getAuthority(tenantId, this.authorityHost);
|
|
1735
|
+
this.identityClient = new IdentityClient(Object.assign(Object.assign({}, options.tokenCredentialOptions), { authorityHost: authority, loggingOptions: options.loggingOptions }));
|
|
1736
|
+
const clientCapabilities = [];
|
|
1737
|
+
return {
|
|
1738
|
+
auth: {
|
|
1739
|
+
clientId,
|
|
1740
|
+
authority,
|
|
1741
|
+
knownAuthorities: getKnownAuthorities(tenantId, authority, options.disableInstanceDiscovery),
|
|
1742
|
+
clientCapabilities,
|
|
1743
|
+
},
|
|
1744
|
+
// Cache is defined in this.prepare();
|
|
1745
|
+
system: {
|
|
1746
|
+
networkClient: this.identityClient,
|
|
1747
|
+
loggerOptions: {
|
|
1748
|
+
loggerCallback: defaultLoggerCallback(options.logger),
|
|
1749
|
+
logLevel: getMSALLogLevel(logger$q.getLogLevel()),
|
|
1750
|
+
piiLoggingEnabled: (_a = options.loggingOptions) === null || _a === void 0 ? void 0 : _a.enableUnsafeSupportLogging,
|
|
1751
|
+
},
|
|
1752
|
+
},
|
|
1746
1753
|
};
|
|
1747
|
-
|
|
1748
|
-
|
|
1754
|
+
}
|
|
1755
|
+
getApp(appType, enableCae) {
|
|
1756
|
+
const app = enableCae ? this.caeApp : this.app;
|
|
1757
|
+
if (appType === "publicFirst") {
|
|
1758
|
+
return (app.public || app.confidential);
|
|
1749
1759
|
}
|
|
1750
|
-
if (
|
|
1751
|
-
|
|
1760
|
+
else if (appType === "confidentialFirst") {
|
|
1761
|
+
return (app.confidential || app.public);
|
|
1762
|
+
}
|
|
1763
|
+
else if (appType === "confidential") {
|
|
1764
|
+
return app.confidential;
|
|
1765
|
+
}
|
|
1766
|
+
else {
|
|
1767
|
+
return app.public;
|
|
1752
1768
|
}
|
|
1753
|
-
const params = new URLSearchParams(queryParameters);
|
|
1754
|
-
query = `?${params.toString()}`;
|
|
1755
|
-
}
|
|
1756
|
-
const url = new URL(imdsEndpointPath, (_a = process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) !== null && _a !== void 0 ? _a : imdsHost);
|
|
1757
|
-
const rawHeaders = {
|
|
1758
|
-
Accept: "application/json",
|
|
1759
|
-
Metadata: "true",
|
|
1760
|
-
};
|
|
1761
|
-
// Remove the Metadata header to invoke a request error from some IMDS endpoints.
|
|
1762
|
-
if (skipMetadataHeader) {
|
|
1763
|
-
delete rawHeaders.Metadata;
|
|
1764
1769
|
}
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
//
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
startDelayInMs: 800,
|
|
1776
|
-
intervalIncrement: 2,
|
|
1777
|
-
};
|
|
1778
|
-
/**
|
|
1779
|
-
* Defines how to determine whether the Azure IMDS MSI is available, and also how to retrieve a token from the Azure IMDS MSI.
|
|
1780
|
-
*/
|
|
1781
|
-
const imdsMsi = {
|
|
1782
|
-
name: "imdsMsi",
|
|
1783
|
-
async isAvailable({ scopes, identityClient, clientId, resourceId, getTokenOptions = {}, }) {
|
|
1784
|
-
const resource = mapScopesToResource(scopes);
|
|
1785
|
-
if (!resource) {
|
|
1786
|
-
logger$k.info(`${msiName$4}: Unavailable. Multiple scopes are not supported.`);
|
|
1787
|
-
return false;
|
|
1770
|
+
/**
|
|
1771
|
+
* Prepares the MSAL applications.
|
|
1772
|
+
*/
|
|
1773
|
+
async init(options) {
|
|
1774
|
+
if (options === null || options === void 0 ? void 0 : options.abortSignal) {
|
|
1775
|
+
options.abortSignal.addEventListener("abort", () => {
|
|
1776
|
+
// This will abort any pending request in the IdentityClient,
|
|
1777
|
+
// based on the received or generated correlationId
|
|
1778
|
+
this.identityClient.abortRequests(options.correlationId);
|
|
1779
|
+
});
|
|
1788
1780
|
}
|
|
1789
|
-
|
|
1790
|
-
if (
|
|
1791
|
-
|
|
1781
|
+
const app = (options === null || options === void 0 ? void 0 : options.enableCae) ? this.caeApp : this.app;
|
|
1782
|
+
if (options === null || options === void 0 ? void 0 : options.enableCae) {
|
|
1783
|
+
this.msalConfig.auth.clientCapabilities = ["cp1"];
|
|
1792
1784
|
}
|
|
1793
|
-
if (
|
|
1794
|
-
|
|
1785
|
+
if (app.public || app.confidential) {
|
|
1786
|
+
return;
|
|
1795
1787
|
}
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
try {
|
|
1814
|
-
logger$k.info(`${msiName$4}: Pinging the Azure IMDS endpoint`);
|
|
1815
|
-
response = await identityClient.sendRequest(request);
|
|
1816
|
-
}
|
|
1817
|
-
catch (err) {
|
|
1818
|
-
// If the request failed, or Node.js was unable to establish a connection,
|
|
1819
|
-
// or the host was down, we'll assume the IMDS endpoint isn't available.
|
|
1820
|
-
if (coreUtil.isError(err)) {
|
|
1821
|
-
logger$k.verbose(`${msiName$4}: Caught error ${err.name}: ${err.message}`);
|
|
1822
|
-
}
|
|
1823
|
-
// This is a special case for Docker Desktop which responds with a 403 with a message that contains "A socket operation was attempted to an unreachable network"
|
|
1824
|
-
// rather than just timing out, as expected.
|
|
1825
|
-
logger$k.info(`${msiName$4}: The Azure IMDS endpoint is unavailable`);
|
|
1826
|
-
return false;
|
|
1788
|
+
if ((options === null || options === void 0 ? void 0 : options.enableCae) && this.createCachePluginCae !== undefined) {
|
|
1789
|
+
this.msalConfig.cache = {
|
|
1790
|
+
cachePlugin: await this.createCachePluginCae(),
|
|
1791
|
+
};
|
|
1792
|
+
}
|
|
1793
|
+
if (this.createCachePlugin !== undefined) {
|
|
1794
|
+
this.msalConfig.cache = {
|
|
1795
|
+
cachePlugin: await this.createCachePlugin(),
|
|
1796
|
+
};
|
|
1797
|
+
}
|
|
1798
|
+
if (hasNativeBroker() && this.enableBroker) {
|
|
1799
|
+
this.msalConfig.broker = {
|
|
1800
|
+
nativeBrokerPlugin: nativeBrokerInfo.broker,
|
|
1801
|
+
};
|
|
1802
|
+
if (!this.parentWindowHandle) {
|
|
1803
|
+
// error should have been thrown from within the constructor of InteractiveBrowserCredential
|
|
1804
|
+
this.logger.warning("Parent window handle is not specified for the broker. This may cause unexpected behavior. Please provide the parentWindowHandle.");
|
|
1827
1805
|
}
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1806
|
+
}
|
|
1807
|
+
if (options === null || options === void 0 ? void 0 : options.enableCae) {
|
|
1808
|
+
this.caeApp.public = new msalCommon__namespace.PublicClientApplication(this.msalConfig);
|
|
1809
|
+
}
|
|
1810
|
+
else {
|
|
1811
|
+
this.app.public = new msalCommon__namespace.PublicClientApplication(this.msalConfig);
|
|
1812
|
+
}
|
|
1813
|
+
if (this.getAssertion) {
|
|
1814
|
+
this.msalConfig.auth.clientAssertion = await this.getAssertion();
|
|
1815
|
+
}
|
|
1816
|
+
// The confidential client requires either a secret, assertion or certificate.
|
|
1817
|
+
if (this.msalConfig.auth.clientSecret ||
|
|
1818
|
+
this.msalConfig.auth.clientAssertion ||
|
|
1819
|
+
this.msalConfig.auth.clientCertificate) {
|
|
1820
|
+
if (options === null || options === void 0 ? void 0 : options.enableCae) {
|
|
1821
|
+
this.caeApp.confidential = new msalCommon__namespace.ConfidentialClientApplication(this.msalConfig);
|
|
1822
|
+
}
|
|
1823
|
+
else {
|
|
1824
|
+
this.app.confidential = new msalCommon__namespace.ConfidentialClientApplication(this.msalConfig);
|
|
1834
1825
|
}
|
|
1835
|
-
// If we received any response, the endpoint is available
|
|
1836
|
-
logger$k.info(`${msiName$4}: The Azure IMDS endpoint is available`);
|
|
1837
|
-
return true;
|
|
1838
|
-
});
|
|
1839
|
-
},
|
|
1840
|
-
async getToken(configuration, getTokenOptions = {}) {
|
|
1841
|
-
const { identityClient, scopes, clientId, resourceId } = configuration;
|
|
1842
|
-
if (process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) {
|
|
1843
|
-
logger$k.info(`${msiName$4}: Using the Azure IMDS endpoint coming from the environment variable AZURE_POD_IDENTITY_AUTHORITY_HOST=${process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST}.`);
|
|
1844
1826
|
}
|
|
1845
1827
|
else {
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
let nextDelayInMs = imdsMsiRetryConfig.startDelayInMs;
|
|
1849
|
-
for (let retries = 0; retries < imdsMsiRetryConfig.maxRetries; retries++) {
|
|
1850
|
-
try {
|
|
1851
|
-
const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$3(scopes, clientId, resourceId)), { allowInsecureConnection: true }));
|
|
1852
|
-
const tokenResponse = await identityClient.sendTokenRequest(request);
|
|
1853
|
-
return (tokenResponse && tokenResponse.accessToken) || null;
|
|
1854
|
-
}
|
|
1855
|
-
catch (error) {
|
|
1856
|
-
if (error.statusCode === 404) {
|
|
1857
|
-
await coreUtil.delay(nextDelayInMs);
|
|
1858
|
-
nextDelayInMs *= imdsMsiRetryConfig.intervalIncrement;
|
|
1859
|
-
continue;
|
|
1860
|
-
}
|
|
1861
|
-
throw error;
|
|
1828
|
+
if (this.requiresConfidential) {
|
|
1829
|
+
throw new Error("Unable to generate the MSAL confidential client. Missing either the client's secret, certificate or assertion.");
|
|
1862
1830
|
}
|
|
1863
1831
|
}
|
|
1864
|
-
throw new AuthenticationError(404, `${msiName$4}: Failed to retrieve IMDS token after ${imdsMsiRetryConfig.maxRetries} retries.`);
|
|
1865
|
-
},
|
|
1866
|
-
};
|
|
1867
|
-
|
|
1868
|
-
// Copyright (c) Microsoft Corporation.
|
|
1869
|
-
// Licensed under the MIT license.
|
|
1870
|
-
const msiName$3 = "ManagedIdentityCredential - Azure Arc MSI";
|
|
1871
|
-
const logger$j = credentialLogger(msiName$3);
|
|
1872
|
-
/**
|
|
1873
|
-
* Generates the options used on the request for an access token.
|
|
1874
|
-
*/
|
|
1875
|
-
function prepareRequestOptions$2(scopes, clientId, resourceId) {
|
|
1876
|
-
const resource = mapScopesToResource(scopes);
|
|
1877
|
-
if (!resource) {
|
|
1878
|
-
throw new Error(`${msiName$3}: Multiple scopes are not supported.`);
|
|
1879
|
-
}
|
|
1880
|
-
const queryParameters = {
|
|
1881
|
-
resource,
|
|
1882
|
-
"api-version": azureArcAPIVersion,
|
|
1883
|
-
};
|
|
1884
|
-
if (clientId) {
|
|
1885
|
-
queryParameters.client_id = clientId;
|
|
1886
1832
|
}
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1833
|
+
/**
|
|
1834
|
+
* Allows the cancellation of a MSAL request.
|
|
1835
|
+
*/
|
|
1836
|
+
withCancellation(promise, abortSignal, onCancel) {
|
|
1837
|
+
return new Promise((resolve, reject) => {
|
|
1838
|
+
promise
|
|
1839
|
+
.then((msalToken) => {
|
|
1840
|
+
return resolve(msalToken);
|
|
1841
|
+
})
|
|
1842
|
+
.catch(reject);
|
|
1843
|
+
if (abortSignal) {
|
|
1844
|
+
abortSignal.addEventListener("abort", () => {
|
|
1845
|
+
onCancel === null || onCancel === void 0 ? void 0 : onCancel();
|
|
1846
|
+
});
|
|
1847
|
+
}
|
|
1848
|
+
});
|
|
1893
1849
|
}
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
Accept: "application/json",
|
|
1901
|
-
Metadata: "true",
|
|
1902
|
-
}),
|
|
1903
|
-
});
|
|
1904
|
-
}
|
|
1905
|
-
/**
|
|
1906
|
-
* Retrieves the file contents at the given path using promises.
|
|
1907
|
-
* Useful since `fs`'s readFileSync locks the thread, and to avoid extra dependencies.
|
|
1908
|
-
*/
|
|
1909
|
-
function readFileAsync$1(path, options) {
|
|
1910
|
-
return new Promise((resolve, reject) => fs.readFile(path, options, (err, data) => {
|
|
1911
|
-
if (err) {
|
|
1912
|
-
reject(err);
|
|
1850
|
+
/**
|
|
1851
|
+
* Returns the existing account, attempts to load the account from MSAL.
|
|
1852
|
+
*/
|
|
1853
|
+
async getActiveAccount(enableCae = false) {
|
|
1854
|
+
if (this.account) {
|
|
1855
|
+
return this.account;
|
|
1913
1856
|
}
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
* Does a request to the authentication provider that results in a file path.
|
|
1919
|
-
*/
|
|
1920
|
-
async function filePathRequest(identityClient, requestPrepareOptions) {
|
|
1921
|
-
const response = await identityClient.sendRequest(coreRestPipeline.createPipelineRequest(requestPrepareOptions));
|
|
1922
|
-
if (response.status !== 401) {
|
|
1923
|
-
let message = "";
|
|
1924
|
-
if (response.bodyAsText) {
|
|
1925
|
-
message = ` Response: ${response.bodyAsText}`;
|
|
1857
|
+
const cache = this.getApp("confidentialFirst", enableCae).getTokenCache();
|
|
1858
|
+
const accountsByTenant = await (cache === null || cache === void 0 ? void 0 : cache.getAllAccounts());
|
|
1859
|
+
if (!accountsByTenant) {
|
|
1860
|
+
return;
|
|
1926
1861
|
}
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1862
|
+
if (accountsByTenant.length === 1) {
|
|
1863
|
+
this.account = msalToPublic(this.clientId, accountsByTenant[0]);
|
|
1864
|
+
}
|
|
1865
|
+
else {
|
|
1866
|
+
this.logger
|
|
1867
|
+
.info(`More than one account was found authenticated for this Client ID and Tenant ID.
|
|
1868
|
+
However, no "authenticationRecord" has been provided for this credential,
|
|
1869
|
+
therefore we're unable to pick between these accounts.
|
|
1870
|
+
A new login attempt will be requested, to ensure the correct account is picked.
|
|
1871
|
+
To work with multiple accounts for the same Client ID and Tenant ID, please provide an "authenticationRecord" when initializing a credential to prevent this from happening.`);
|
|
1872
|
+
return;
|
|
1873
|
+
}
|
|
1874
|
+
return this.account;
|
|
1935
1875
|
}
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1876
|
+
/**
|
|
1877
|
+
* Attempts to retrieve a token from cache.
|
|
1878
|
+
*/
|
|
1879
|
+
async getTokenSilent(scopes, options) {
|
|
1880
|
+
var _a, _b, _c;
|
|
1881
|
+
await this.getActiveAccount(options === null || options === void 0 ? void 0 : options.enableCae);
|
|
1882
|
+
if (!this.account) {
|
|
1883
|
+
throw new AuthenticationRequiredError({
|
|
1884
|
+
scopes,
|
|
1885
|
+
getTokenOptions: options,
|
|
1886
|
+
message: "Silent authentication failed. We couldn't retrieve an active account from the cache.",
|
|
1887
|
+
});
|
|
1947
1888
|
}
|
|
1948
|
-
const
|
|
1949
|
-
|
|
1950
|
-
|
|
1889
|
+
const silentRequest = {
|
|
1890
|
+
// To be able to re-use the account, the Token Cache must also have been provided.
|
|
1891
|
+
account: publicToMsal(this.account),
|
|
1892
|
+
correlationId: options === null || options === void 0 ? void 0 : options.correlationId,
|
|
1893
|
+
scopes,
|
|
1894
|
+
authority: options === null || options === void 0 ? void 0 : options.authority,
|
|
1895
|
+
claims: options === null || options === void 0 ? void 0 : options.claims,
|
|
1896
|
+
};
|
|
1897
|
+
if (hasNativeBroker() && this.enableBroker) {
|
|
1898
|
+
if (!silentRequest.tokenQueryParameters) {
|
|
1899
|
+
silentRequest.tokenQueryParameters = {};
|
|
1900
|
+
}
|
|
1901
|
+
if (!this.parentWindowHandle) {
|
|
1902
|
+
// error should have been thrown from within the constructor of InteractiveBrowserCredential
|
|
1903
|
+
this.logger.warning("Parent window handle is not specified for the broker. This may cause unexpected behavior. Please provide the parentWindowHandle.");
|
|
1904
|
+
}
|
|
1905
|
+
if (this.enableMsaPassthrough) {
|
|
1906
|
+
silentRequest.tokenQueryParameters["msal_request_type"] = "consumer_passthrough";
|
|
1907
|
+
}
|
|
1951
1908
|
}
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1909
|
+
try {
|
|
1910
|
+
this.logger.info("Attempting to acquire token silently");
|
|
1911
|
+
/**
|
|
1912
|
+
* The following code to retrieve all accounts is done as a workaround in an attempt to force the
|
|
1913
|
+
* refresh of the token cache with the token and the account passed in through the
|
|
1914
|
+
* `authenticationRecord` parameter. See issue - https://github.com/Azure/azure-sdk-for-js/issues/24349#issuecomment-1496715651
|
|
1915
|
+
* This workaround serves as a workaround for silent authentication not happening when authenticationRecord is passed.
|
|
1916
|
+
*/
|
|
1917
|
+
await ((_a = this.getApp("publicFirst", options === null || options === void 0 ? void 0 : options.enableCae)) === null || _a === void 0 ? void 0 : _a.getTokenCache().getAllAccounts());
|
|
1918
|
+
const response = (_c = (await ((_b = this.getApp("confidential", options === null || options === void 0 ? void 0 : options.enableCae)) === null || _b === void 0 ? void 0 : _b.acquireTokenSilent(silentRequest)))) !== null && _c !== void 0 ? _c : (await this.getApp("public", options === null || options === void 0 ? void 0 : options.enableCae).acquireTokenSilent(silentRequest));
|
|
1919
|
+
return this.handleResult(scopes, response || undefined);
|
|
1959
1920
|
}
|
|
1960
|
-
|
|
1961
|
-
|
|
1921
|
+
catch (err) {
|
|
1922
|
+
throw handleMsalError(scopes, err, options);
|
|
1962
1923
|
}
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1924
|
+
}
|
|
1925
|
+
/**
|
|
1926
|
+
* Wrapper around each MSAL flow get token operation: doGetToken.
|
|
1927
|
+
* If disableAutomaticAuthentication is sent through the constructor, it will prevent MSAL from requesting the user input.
|
|
1928
|
+
*/
|
|
1929
|
+
async getToken(scopes, options = {}) {
|
|
1930
|
+
const tenantId = processMultiTenantRequest(this.tenantId, options, this.additionallyAllowedTenantIds) ||
|
|
1931
|
+
this.tenantId;
|
|
1932
|
+
options.authority = getAuthority(tenantId, this.authorityHost);
|
|
1933
|
+
options.correlationId = (options === null || options === void 0 ? void 0 : options.correlationId) || randomUUID();
|
|
1934
|
+
await this.init(options);
|
|
1935
|
+
try {
|
|
1936
|
+
// MSAL now caches tokens based on their claims,
|
|
1937
|
+
// so now one has to keep track fo claims in order to retrieve the newer tokens from acquireTokenSilent
|
|
1938
|
+
// This update happened on PR: https://github.com/AzureAD/microsoft-authentication-library-for-js/pull/4533
|
|
1939
|
+
const optionsClaims = options.claims;
|
|
1940
|
+
if (optionsClaims) {
|
|
1941
|
+
this.cachedClaims = optionsClaims;
|
|
1942
|
+
}
|
|
1943
|
+
if (this.cachedClaims && !optionsClaims) {
|
|
1944
|
+
options.claims = this.cachedClaims;
|
|
1945
|
+
}
|
|
1946
|
+
// We don't return the promise since we want to catch errors right here.
|
|
1947
|
+
return await this.getTokenSilent(scopes, options);
|
|
1968
1948
|
}
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1949
|
+
catch (err) {
|
|
1950
|
+
if (err.name !== "AuthenticationRequiredError") {
|
|
1951
|
+
throw err;
|
|
1952
|
+
}
|
|
1953
|
+
if (options === null || options === void 0 ? void 0 : options.disableAutomaticAuthentication) {
|
|
1954
|
+
throw new AuthenticationRequiredError({
|
|
1955
|
+
scopes,
|
|
1956
|
+
getTokenOptions: options,
|
|
1957
|
+
message: "Automatic authentication has been disabled. You may call the authentication() method.",
|
|
1958
|
+
});
|
|
1959
|
+
}
|
|
1960
|
+
this.logger.info(`Silent authentication failed, falling back to interactive method.`);
|
|
1961
|
+
return this.doGetToken(scopes, options);
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
/**
|
|
1965
|
+
* Handles the MSAL authentication result.
|
|
1966
|
+
* If the result has an account, we update the local account reference.
|
|
1967
|
+
* If the token received is invalid, an error will be thrown depending on what's missing.
|
|
1968
|
+
*/
|
|
1969
|
+
handleResult(scopes, result, getTokenOptions) {
|
|
1970
|
+
if (result === null || result === void 0 ? void 0 : result.account) {
|
|
1971
|
+
this.account = msalToPublic(this.clientId, result.account);
|
|
1972
|
+
}
|
|
1973
|
+
ensureValidMsalToken(scopes, result, getTokenOptions);
|
|
1974
|
+
this.logger.getToken.info(formatSuccess(scopes));
|
|
1975
|
+
return {
|
|
1976
|
+
token: result.accessToken,
|
|
1977
|
+
expiresOnTimestamp: result.expiresOn.getTime(),
|
|
1978
|
+
};
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1978
1981
|
|
|
1979
1982
|
// Copyright (c) Microsoft Corporation.
|
|
1980
1983
|
// Licensed under the MIT license.
|