@azure/identity 4.1.0-beta.1 → 4.1.0
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 +1473 -1396
- package/dist/index.js.map +1 -1
- package/dist-esm/src/constants.js +10 -3
- package/dist-esm/src/constants.js.map +1 -1
- package/dist-esm/src/credentials/authorizationCodeCredential.js +1 -1
- package/dist-esm/src/credentials/authorizationCodeCredential.js.map +1 -1
- package/dist-esm/src/credentials/azureDeveloperCliCredential.js +1 -1
- package/dist-esm/src/credentials/azureDeveloperCliCredential.js.map +1 -1
- package/dist-esm/src/credentials/clientAssertionCredential.js.map +1 -1
- package/dist-esm/src/credentials/clientSecretCredential.js +1 -1
- package/dist-esm/src/credentials/clientSecretCredential.js.map +1 -1
- package/dist-esm/src/credentials/defaultAzureCredential.js +9 -5
- package/dist-esm/src/credentials/defaultAzureCredential.js.map +1 -1
- package/dist-esm/src/credentials/interactiveBrowserCredential.js +4 -3
- package/dist-esm/src/credentials/interactiveBrowserCredential.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/imdsMsi.js +10 -16
- package/dist-esm/src/credentials/managedIdentityCredential/imdsMsi.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/index.js +22 -14
- package/dist-esm/src/credentials/managedIdentityCredential/index.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/models.js.map +1 -1
- package/dist-esm/src/credentials/onBehalfOfCredential.browser.js +1 -1
- package/dist-esm/src/credentials/onBehalfOfCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/onBehalfOfCredential.js +1 -1
- package/dist-esm/src/credentials/onBehalfOfCredential.js.map +1 -1
- package/dist-esm/src/msal/browserFlows/msalBrowserCommon.js.map +1 -1
- package/dist-esm/src/msal/msal.browser.js +5 -0
- package/dist-esm/src/msal/msal.browser.js.map +1 -0
- package/dist-esm/src/msal/msal.js +5 -0
- package/dist-esm/src/msal/msal.js.map +1 -0
- package/dist-esm/src/msal/nodeFlows/brokerOptions.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalClient.js +170 -0
- package/dist-esm/src/msal/nodeFlows/msalClient.js.map +1 -0
- package/dist-esm/src/msal/nodeFlows/msalNodeCommon.js +8 -42
- package/dist-esm/src/msal/nodeFlows/msalNodeCommon.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalOpenBrowser.js +60 -18
- package/dist-esm/src/msal/nodeFlows/msalOpenBrowser.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalPlugins.js +86 -0
- package/dist-esm/src/msal/nodeFlows/msalPlugins.js.map +1 -0
- package/dist-esm/src/msal/types.js.map +1 -1
- package/dist-esm/src/msal/utils.js +1 -1
- package/dist-esm/src/msal/utils.js.map +1 -1
- package/dist-esm/src/plugins/consumer.js +1 -1
- package/dist-esm/src/plugins/consumer.js.map +1 -1
- package/dist-esm/src/regionalAuthority.js +21 -0
- package/dist-esm/src/regionalAuthority.js.map +1 -1
- package/package.json +11 -11
- package/types/identity.d.ts +20 -11
- package/dist-esm/src/msal/utils.browser.js +0 -204
- package/dist-esm/src/msal/utils.browser.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -2,18 +2,18 @@
|
|
|
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');
|
|
15
|
-
var
|
|
14
|
+
var msalCommon = require('@azure/msal-node');
|
|
16
15
|
var https = require('https');
|
|
16
|
+
var promises = require('fs/promises');
|
|
17
17
|
var child_process = require('child_process');
|
|
18
18
|
var crypto = require('crypto');
|
|
19
19
|
var util = require('util');
|
|
@@ -44,7 +44,7 @@ var child_process__namespace = /*#__PURE__*/_interopNamespaceDefault(child_proce
|
|
|
44
44
|
/**
|
|
45
45
|
* Current version of the `@azure/identity` package.
|
|
46
46
|
*/
|
|
47
|
-
const SDK_VERSION = `4.1.0-beta.
|
|
47
|
+
const SDK_VERSION = `4.1.0-beta.2`;
|
|
48
48
|
/**
|
|
49
49
|
* The default client ID for authentication
|
|
50
50
|
* @internal
|
|
@@ -93,11 +93,54 @@ const ALL_TENANTS = ["*"];
|
|
|
93
93
|
/**
|
|
94
94
|
* @internal
|
|
95
95
|
*/
|
|
96
|
-
const CACHE_CAE_SUFFIX = "
|
|
96
|
+
const CACHE_CAE_SUFFIX = "cae";
|
|
97
|
+
/**
|
|
98
|
+
* @internal
|
|
99
|
+
*/
|
|
100
|
+
const CACHE_NON_CAE_SUFFIX = "nocae";
|
|
101
|
+
/**
|
|
102
|
+
* @internal
|
|
103
|
+
*
|
|
104
|
+
* The default name for the cache persistence plugin.
|
|
105
|
+
* Matches the constant defined in the cache persistence package.
|
|
106
|
+
*/
|
|
107
|
+
const DEFAULT_TOKEN_CACHE_NAME = "msal.cache";
|
|
108
|
+
|
|
109
|
+
// Copyright (c) Microsoft Corporation.
|
|
110
|
+
// Licensed under the MIT license.
|
|
111
|
+
/**
|
|
112
|
+
* The current persistence provider, undefined by default.
|
|
113
|
+
* @internal
|
|
114
|
+
*/
|
|
115
|
+
let persistenceProvider = undefined;
|
|
116
|
+
/**
|
|
117
|
+
* An object that allows setting the persistence provider.
|
|
118
|
+
* @internal
|
|
119
|
+
*/
|
|
120
|
+
const msalNodeFlowCacheControl = {
|
|
121
|
+
setPersistence(pluginProvider) {
|
|
122
|
+
persistenceProvider = pluginProvider;
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* The current native broker provider, undefined by default.
|
|
127
|
+
* @internal
|
|
128
|
+
*/
|
|
129
|
+
let nativeBrokerInfo = undefined;
|
|
130
|
+
function hasNativeBroker() {
|
|
131
|
+
return nativeBrokerInfo !== undefined;
|
|
132
|
+
}
|
|
97
133
|
/**
|
|
134
|
+
* An object that allows setting the native broker provider.
|
|
98
135
|
* @internal
|
|
99
136
|
*/
|
|
100
|
-
const
|
|
137
|
+
const msalNodeFlowNativeBrokerControl = {
|
|
138
|
+
setNativeBroker(broker) {
|
|
139
|
+
nativeBrokerInfo = {
|
|
140
|
+
broker,
|
|
141
|
+
};
|
|
142
|
+
},
|
|
143
|
+
};
|
|
101
144
|
|
|
102
145
|
// Copyright (c) Microsoft Corporation.
|
|
103
146
|
// Licensed under the MIT license.
|
|
@@ -297,218 +340,6 @@ class AuthenticationRequiredError extends Error {
|
|
|
297
340
|
}
|
|
298
341
|
}
|
|
299
342
|
|
|
300
|
-
// Copyright (c) Microsoft Corporation.
|
|
301
|
-
// Licensed under the MIT license.
|
|
302
|
-
/**
|
|
303
|
-
* @internal
|
|
304
|
-
*/
|
|
305
|
-
const logger$o = credentialLogger("IdentityUtils");
|
|
306
|
-
/**
|
|
307
|
-
* Latest AuthenticationRecord version
|
|
308
|
-
* @internal
|
|
309
|
-
*/
|
|
310
|
-
const LatestAuthenticationRecordVersion = "1.0";
|
|
311
|
-
/**
|
|
312
|
-
* Ensures the validity of the MSAL token
|
|
313
|
-
* @internal
|
|
314
|
-
*/
|
|
315
|
-
function ensureValidMsalToken(scopes, msalToken, getTokenOptions) {
|
|
316
|
-
const error = (message) => {
|
|
317
|
-
logger$o.getToken.info(message);
|
|
318
|
-
return new AuthenticationRequiredError({
|
|
319
|
-
scopes: Array.isArray(scopes) ? scopes : [scopes],
|
|
320
|
-
getTokenOptions,
|
|
321
|
-
message,
|
|
322
|
-
});
|
|
323
|
-
};
|
|
324
|
-
if (!msalToken) {
|
|
325
|
-
throw error("No response");
|
|
326
|
-
}
|
|
327
|
-
if (!msalToken.expiresOn) {
|
|
328
|
-
throw error(`Response had no "expiresOn" property.`);
|
|
329
|
-
}
|
|
330
|
-
if (!msalToken.accessToken) {
|
|
331
|
-
throw error(`Response had no "accessToken" property.`);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Generates a valid authority by combining a host with a tenantId.
|
|
336
|
-
* @internal
|
|
337
|
-
*/
|
|
338
|
-
function getAuthority(tenantId, host) {
|
|
339
|
-
if (!host) {
|
|
340
|
-
host = DefaultAuthorityHost;
|
|
341
|
-
}
|
|
342
|
-
if (new RegExp(`${tenantId}/?$`).test(host)) {
|
|
343
|
-
return host;
|
|
344
|
-
}
|
|
345
|
-
if (host.endsWith("/")) {
|
|
346
|
-
return host + tenantId;
|
|
347
|
-
}
|
|
348
|
-
else {
|
|
349
|
-
return `${host}/${tenantId}`;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
/**
|
|
353
|
-
* Generates the known authorities.
|
|
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.
|
|
357
|
-
* @internal
|
|
358
|
-
*/
|
|
359
|
-
function getKnownAuthorities(tenantId, authorityHost, disableInstanceDiscovery) {
|
|
360
|
-
if ((tenantId === "adfs" && authorityHost) || disableInstanceDiscovery) {
|
|
361
|
-
return [authorityHost];
|
|
362
|
-
}
|
|
363
|
-
return [];
|
|
364
|
-
}
|
|
365
|
-
/**
|
|
366
|
-
* Generates a logger that can be passed to the MSAL clients.
|
|
367
|
-
* @param credLogger - The logger of the credential.
|
|
368
|
-
* @internal
|
|
369
|
-
*/
|
|
370
|
-
const defaultLoggerCallback = (credLogger, platform = coreUtil.isNode ? "Node" : "Browser") => (level, message, containsPii) => {
|
|
371
|
-
if (containsPii) {
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
374
|
-
switch (level) {
|
|
375
|
-
case msalCommon__namespace.LogLevel.Error:
|
|
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
343
|
// Copyright (c) Microsoft Corporation.
|
|
513
344
|
// Licensed under the MIT license.
|
|
514
345
|
function createConfigurationErrorMessage(tenantId) {
|
|
@@ -899,1082 +730,1432 @@ class IdentityClient extends coreClient.ServiceClient {
|
|
|
899
730
|
|
|
900
731
|
// Copyright (c) Microsoft Corporation.
|
|
901
732
|
// 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;
|
|
733
|
+
const CommonTenantId = "common";
|
|
734
|
+
const AzureAccountClientId = "aebc6443-996d-45c2-90f0-388ff96faa56"; // VSC: 'aebc6443-996d-45c2-90f0-388ff96faa56'
|
|
735
|
+
const logger$o = credentialLogger("VisualStudioCodeCredential");
|
|
736
|
+
let findCredentials = undefined;
|
|
737
|
+
const vsCodeCredentialControl = {
|
|
738
|
+
setVsCodeCredentialFinder(finder) {
|
|
739
|
+
findCredentials = finder;
|
|
1029
740
|
},
|
|
1030
741
|
};
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
742
|
+
// Map of unsupported Tenant IDs and the errors we will be throwing.
|
|
743
|
+
const unsupportedTenantIds = {
|
|
744
|
+
adfs: "The VisualStudioCodeCredential does not support authentication with ADFS tenants.",
|
|
745
|
+
};
|
|
746
|
+
function checkUnsupportedTenant(tenantId) {
|
|
747
|
+
// If the Tenant ID isn't supported, we throw.
|
|
748
|
+
const unsupportedTenantError = unsupportedTenantIds[tenantId];
|
|
749
|
+
if (unsupportedTenantError) {
|
|
750
|
+
throw new CredentialUnavailableError(unsupportedTenantError);
|
|
751
|
+
}
|
|
1038
752
|
}
|
|
753
|
+
const mapVSCodeAuthorityHosts = {
|
|
754
|
+
AzureCloud: exports.AzureAuthorityHosts.AzurePublicCloud,
|
|
755
|
+
AzureChina: exports.AzureAuthorityHosts.AzureChina,
|
|
756
|
+
AzureGermanCloud: exports.AzureAuthorityHosts.AzureGermany,
|
|
757
|
+
AzureUSGovernment: exports.AzureAuthorityHosts.AzureGovernment,
|
|
758
|
+
};
|
|
1039
759
|
/**
|
|
1040
|
-
*
|
|
1041
|
-
*
|
|
760
|
+
* Attempts to load a specific property from the VSCode configurations of the current OS.
|
|
761
|
+
* If it fails at any point, returns undefined.
|
|
1042
762
|
*/
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
763
|
+
function getPropertyFromVSCode(property) {
|
|
764
|
+
const settingsPath = ["User", "settings.json"];
|
|
765
|
+
// Eventually we can add more folders for more versions of VSCode.
|
|
766
|
+
const vsCodeFolder = "Code";
|
|
767
|
+
const homedir = os.homedir();
|
|
768
|
+
function loadProperty(...pathSegments) {
|
|
769
|
+
const fullPath = path.join(...pathSegments, vsCodeFolder, ...settingsPath);
|
|
770
|
+
const settings = JSON.parse(fs.readFileSync(fullPath, { encoding: "utf8" }));
|
|
771
|
+
return settings[property];
|
|
772
|
+
}
|
|
773
|
+
try {
|
|
774
|
+
let appData;
|
|
775
|
+
switch (process.platform) {
|
|
776
|
+
case "win32":
|
|
777
|
+
appData = process.env.APPDATA;
|
|
778
|
+
return appData ? loadProperty(appData) : undefined;
|
|
779
|
+
case "darwin":
|
|
780
|
+
return loadProperty(homedir, "Library", "Application Support");
|
|
781
|
+
case "linux":
|
|
782
|
+
return loadProperty(homedir, ".config");
|
|
783
|
+
default:
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
catch (e) {
|
|
788
|
+
logger$o.info(`Failed to load the Visual Studio Code configuration file. Error: ${e.message}`);
|
|
789
|
+
return;
|
|
790
|
+
}
|
|
791
|
+
}
|
|
1050
792
|
/**
|
|
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.
|
|
793
|
+
* Connects to Azure using the credential provided by the VSCode extension 'Azure Account'.
|
|
794
|
+
* Once the user has logged in via the extension, this credential can share the same refresh token
|
|
795
|
+
* that is cached by the extension.
|
|
1056
796
|
*
|
|
1057
|
-
*
|
|
797
|
+
* It's a [known issue](https://github.com/Azure/azure-sdk-for-js/issues/20500) that this credential doesn't
|
|
798
|
+
* work with [Azure Account extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.azure-account)
|
|
799
|
+
* versions newer than **0.9.11**. A long-term fix to this problem is in progress. In the meantime, consider
|
|
800
|
+
* authenticating with {@link AzureCliCredential}.
|
|
1058
801
|
*/
|
|
1059
|
-
class
|
|
802
|
+
class VisualStudioCodeCredential {
|
|
803
|
+
/**
|
|
804
|
+
* Creates an instance of VisualStudioCodeCredential to use for automatically authenticating via VSCode.
|
|
805
|
+
*
|
|
806
|
+
* **Note**: `VisualStudioCodeCredential` is provided by a plugin package:
|
|
807
|
+
* `@azure/identity-vscode`. If this package is not installed and registered
|
|
808
|
+
* using the plugin API (`useIdentityPlugin`), then authentication using
|
|
809
|
+
* `VisualStudioCodeCredential` will not be available.
|
|
810
|
+
*
|
|
811
|
+
* @param options - Options for configuring the client which makes the authentication request.
|
|
812
|
+
*/
|
|
1060
813
|
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);
|
|
814
|
+
// We want to make sure we use the one assigned by the user on the VSCode settings.
|
|
815
|
+
// Or just `AzureCloud` by default.
|
|
816
|
+
this.cloudName = (getPropertyFromVSCode("azure.cloud") || "AzureCloud");
|
|
817
|
+
// Picking an authority host based on the cloud name.
|
|
818
|
+
const authorityHost = mapVSCodeAuthorityHosts[this.cloudName];
|
|
819
|
+
this.identityClient = new IdentityClient(Object.assign({ authorityHost }, options));
|
|
820
|
+
if (options && options.tenantId) {
|
|
821
|
+
checkTenantId(logger$o, options.tenantId);
|
|
822
|
+
this.tenantId = options.tenantId;
|
|
1082
823
|
}
|
|
1083
|
-
else
|
|
1084
|
-
|
|
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(" "));
|
|
1099
|
-
}
|
|
1100
|
-
this.azureRegion = (_g = options.regionalAuthority) !== null && _g !== void 0 ? _g : process.env.AZURE_REGIONAL_AUTHORITY_NAME;
|
|
1101
|
-
if (this.azureRegion === RegionalAuthority.AutoDiscoverRegion) {
|
|
1102
|
-
this.azureRegion = "AUTO_DISCOVER";
|
|
824
|
+
else {
|
|
825
|
+
this.tenantId = CommonTenantId;
|
|
1103
826
|
}
|
|
827
|
+
this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants);
|
|
828
|
+
checkUnsupportedTenant(this.tenantId);
|
|
1104
829
|
}
|
|
1105
830
|
/**
|
|
1106
|
-
*
|
|
831
|
+
* Runs preparations for any further getToken request.
|
|
1107
832
|
*/
|
|
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;
|
|
833
|
+
async prepare() {
|
|
834
|
+
// Attempts to load the tenant from the VSCode configuration file.
|
|
835
|
+
const settingsTenant = getPropertyFromVSCode("azure.tenant");
|
|
836
|
+
if (settingsTenant) {
|
|
837
|
+
this.tenantId = settingsTenant;
|
|
1147
838
|
}
|
|
839
|
+
checkUnsupportedTenant(this.tenantId);
|
|
1148
840
|
}
|
|
1149
841
|
/**
|
|
1150
|
-
*
|
|
842
|
+
* Runs preparations for any further getToken, but only once.
|
|
1151
843
|
*/
|
|
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"];
|
|
1163
|
-
}
|
|
1164
|
-
if (app.public || app.confidential) {
|
|
1165
|
-
return;
|
|
1166
|
-
}
|
|
1167
|
-
if ((options === null || options === void 0 ? void 0 : options.enableCae) && this.createCachePluginCae !== undefined) {
|
|
1168
|
-
this.msalConfig.cache = {
|
|
1169
|
-
cachePlugin: await this.createCachePluginCae(),
|
|
1170
|
-
};
|
|
1171
|
-
}
|
|
1172
|
-
if (this.createCachePlugin !== undefined) {
|
|
1173
|
-
this.msalConfig.cache = {
|
|
1174
|
-
cachePlugin: await this.createCachePlugin(),
|
|
1175
|
-
};
|
|
1176
|
-
}
|
|
1177
|
-
if (hasNativeBroker() && this.enableBroker) {
|
|
1178
|
-
this.msalConfig.broker = {
|
|
1179
|
-
nativeBrokerPlugin: nativeBrokerInfo.broker,
|
|
1180
|
-
};
|
|
1181
|
-
if (!this.parentWindowHandle) {
|
|
1182
|
-
// error should have been thrown from within the constructor of InteractiveBrowserCredential
|
|
1183
|
-
this.logger.warning("Parent window handle is not specified for the broker. This may cause unexpected behavior. Please provide the parentWindowHandle.");
|
|
1184
|
-
}
|
|
1185
|
-
}
|
|
1186
|
-
if (options === null || options === void 0 ? void 0 : options.enableCae) {
|
|
1187
|
-
this.caeApp.public = new msalCommon__namespace.PublicClientApplication(this.msalConfig);
|
|
1188
|
-
}
|
|
1189
|
-
else {
|
|
1190
|
-
this.app.public = new msalCommon__namespace.PublicClientApplication(this.msalConfig);
|
|
1191
|
-
}
|
|
1192
|
-
if (this.getAssertion) {
|
|
1193
|
-
this.msalConfig.auth.clientAssertion = await this.getAssertion();
|
|
1194
|
-
}
|
|
1195
|
-
// The confidential client requires either a secret, assertion or certificate.
|
|
1196
|
-
if (this.msalConfig.auth.clientSecret ||
|
|
1197
|
-
this.msalConfig.auth.clientAssertion ||
|
|
1198
|
-
this.msalConfig.auth.clientCertificate) {
|
|
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
|
-
}
|
|
1205
|
-
}
|
|
1206
|
-
else {
|
|
1207
|
-
if (this.requiresConfidential) {
|
|
1208
|
-
throw new Error("Unable to generate the MSAL confidential client. Missing either the client's secret, certificate or assertion.");
|
|
1209
|
-
}
|
|
844
|
+
prepareOnce() {
|
|
845
|
+
if (!this.preparePromise) {
|
|
846
|
+
this.preparePromise = this.prepare();
|
|
1210
847
|
}
|
|
848
|
+
return this.preparePromise;
|
|
1211
849
|
}
|
|
1212
850
|
/**
|
|
1213
|
-
*
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
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
|
-
});
|
|
1228
|
-
}
|
|
1229
|
-
/**
|
|
1230
|
-
* Returns the existing account, attempts to load the account from MSAL.
|
|
851
|
+
* Returns the token found by searching VSCode's authentication cache or
|
|
852
|
+
* returns null if no token could be found.
|
|
853
|
+
*
|
|
854
|
+
* @param scopes - The list of scopes for which the token will have access.
|
|
855
|
+
* @param options - The options used to configure any requests this
|
|
856
|
+
* `TokenCredential` implementation might make.
|
|
1231
857
|
*/
|
|
1232
|
-
async
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
858
|
+
async getToken(scopes, options) {
|
|
859
|
+
var _a, _b;
|
|
860
|
+
await this.prepareOnce();
|
|
861
|
+
const tenantId = processMultiTenantRequest(this.tenantId, options, this.additionallyAllowedTenantIds, logger$o) || this.tenantId;
|
|
862
|
+
if (findCredentials === undefined) {
|
|
863
|
+
throw new CredentialUnavailableError([
|
|
864
|
+
"No implementation of `VisualStudioCodeCredential` is available.",
|
|
865
|
+
"You must install the identity-vscode plugin package (`npm install --save-dev @azure/identity-vscode`)",
|
|
866
|
+
"and enable it by importing `useIdentityPlugin` from `@azure/identity` and calling",
|
|
867
|
+
"`useIdentityPlugin(vsCodePlugin)` before creating a `VisualStudioCodeCredential`.",
|
|
868
|
+
"To troubleshoot, visit https://aka.ms/azsdk/js/identity/vscodecredential/troubleshoot.",
|
|
869
|
+
].join(" "));
|
|
1243
870
|
}
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
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;
|
|
871
|
+
let scopeString = typeof scopes === "string" ? scopes : scopes.join(" ");
|
|
872
|
+
// Check to make sure the scope we get back is a valid scope
|
|
873
|
+
if (!scopeString.match(/^[0-9a-zA-Z-.:/]+$/)) {
|
|
874
|
+
const error = new Error("Invalid scope was specified by the user or calling client");
|
|
875
|
+
logger$o.getToken.info(formatError(scopes, error));
|
|
876
|
+
throw error;
|
|
1252
877
|
}
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
/**
|
|
1256
|
-
* Attempts to retrieve a token from cache.
|
|
1257
|
-
*/
|
|
1258
|
-
async getTokenSilent(scopes, options) {
|
|
1259
|
-
var _a, _b, _c;
|
|
1260
|
-
await this.getActiveAccount(options === null || options === void 0 ? void 0 : options.enableCae);
|
|
1261
|
-
if (!this.account) {
|
|
1262
|
-
throw new AuthenticationRequiredError({
|
|
1263
|
-
scopes,
|
|
1264
|
-
getTokenOptions: options,
|
|
1265
|
-
message: "Silent authentication failed. We couldn't retrieve an active account from the cache.",
|
|
1266
|
-
});
|
|
878
|
+
if (scopeString.indexOf("offline_access") < 0) {
|
|
879
|
+
scopeString += " offline_access";
|
|
1267
880
|
}
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
881
|
+
// findCredentials returns an array similar to:
|
|
882
|
+
// [
|
|
883
|
+
// {
|
|
884
|
+
// account: "",
|
|
885
|
+
// password: "",
|
|
886
|
+
// },
|
|
887
|
+
// /* ... */
|
|
888
|
+
// ]
|
|
889
|
+
const credentials = await findCredentials();
|
|
890
|
+
// If we can't find the credential based on the name, we'll pick the first one available.
|
|
891
|
+
const { password: refreshToken } = (_b = (_a = credentials.find(({ account }) => account === this.cloudName)) !== null && _a !== void 0 ? _a : credentials[0]) !== null && _b !== void 0 ? _b : {};
|
|
892
|
+
if (refreshToken) {
|
|
893
|
+
const tokenResponse = await this.identityClient.refreshAccessToken(tenantId, AzureAccountClientId, scopeString, refreshToken, undefined);
|
|
894
|
+
if (tokenResponse) {
|
|
895
|
+
logger$o.getToken.info(formatSuccess(scopes));
|
|
896
|
+
return tokenResponse.accessToken;
|
|
1283
897
|
}
|
|
1284
|
-
|
|
1285
|
-
|
|
898
|
+
else {
|
|
899
|
+
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.");
|
|
900
|
+
logger$o.getToken.info(formatError(scopes, error));
|
|
901
|
+
throw error;
|
|
1286
902
|
}
|
|
1287
903
|
}
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
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);
|
|
1299
|
-
}
|
|
1300
|
-
catch (err) {
|
|
1301
|
-
throw handleMsalError(scopes, err, options);
|
|
904
|
+
else {
|
|
905
|
+
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.");
|
|
906
|
+
logger$o.getToken.info(formatError(scopes, error));
|
|
907
|
+
throw error;
|
|
1302
908
|
}
|
|
1303
909
|
}
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
// Copyright (c) Microsoft Corporation.
|
|
913
|
+
// Licensed under the MIT license.
|
|
914
|
+
/**
|
|
915
|
+
* The context passed to an Identity plugin. This contains objects that
|
|
916
|
+
* plugins can use to set backend implementations.
|
|
917
|
+
* @internal
|
|
918
|
+
*/
|
|
919
|
+
const pluginContext = {
|
|
920
|
+
cachePluginControl: msalNodeFlowCacheControl,
|
|
921
|
+
nativeBrokerPluginControl: msalNodeFlowNativeBrokerControl,
|
|
922
|
+
vsCodeCredentialControl: vsCodeCredentialControl,
|
|
923
|
+
};
|
|
924
|
+
/**
|
|
925
|
+
* Extend Azure Identity with additional functionality. Pass a plugin from
|
|
926
|
+
* a plugin package, such as:
|
|
927
|
+
*
|
|
928
|
+
* - `@azure/identity-cache-persistence`: provides persistent token caching
|
|
929
|
+
* - `@azure/identity-vscode`: provides the dependencies of
|
|
930
|
+
* `VisualStudioCodeCredential` and enables it
|
|
931
|
+
*
|
|
932
|
+
* Example:
|
|
933
|
+
*
|
|
934
|
+
* ```javascript
|
|
935
|
+
* import { cachePersistencePlugin } from "@azure/identity-cache-persistence";
|
|
936
|
+
*
|
|
937
|
+
* import { useIdentityPlugin, DefaultAzureCredential } from "@azure/identity";
|
|
938
|
+
* useIdentityPlugin(cachePersistencePlugin);
|
|
939
|
+
*
|
|
940
|
+
* // The plugin has the capability to extend `DefaultAzureCredential` and to
|
|
941
|
+
* // add middleware to the underlying credentials, such as persistence.
|
|
942
|
+
* const credential = new DefaultAzureCredential({
|
|
943
|
+
* tokenCachePersistenceOptions: {
|
|
944
|
+
* enabled: true
|
|
945
|
+
* }
|
|
946
|
+
* });
|
|
947
|
+
* ```
|
|
948
|
+
*
|
|
949
|
+
* @param plugin - the plugin to register
|
|
950
|
+
*/
|
|
951
|
+
function useIdentityPlugin(plugin) {
|
|
952
|
+
plugin(pluginContext);
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
// Copyright (c) Microsoft Corporation.
|
|
956
|
+
// Licensed under the MIT license.
|
|
957
|
+
const msiName$6 = "ManagedIdentityCredential - AppServiceMSI 2017";
|
|
958
|
+
const logger$n = credentialLogger(msiName$6);
|
|
959
|
+
/**
|
|
960
|
+
* Generates the options used on the request for an access token.
|
|
961
|
+
*/
|
|
962
|
+
function prepareRequestOptions$5(scopes, clientId) {
|
|
963
|
+
const resource = mapScopesToResource(scopes);
|
|
964
|
+
if (!resource) {
|
|
965
|
+
throw new Error(`${msiName$6}: Multiple scopes are not supported.`);
|
|
966
|
+
}
|
|
967
|
+
const queryParameters = {
|
|
968
|
+
resource,
|
|
969
|
+
"api-version": "2017-09-01",
|
|
970
|
+
};
|
|
971
|
+
if (clientId) {
|
|
972
|
+
queryParameters.clientid = clientId;
|
|
973
|
+
}
|
|
974
|
+
const query = new URLSearchParams(queryParameters);
|
|
975
|
+
// This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
|
|
976
|
+
if (!process.env.MSI_ENDPOINT) {
|
|
977
|
+
throw new Error(`${msiName$6}: Missing environment variable: MSI_ENDPOINT`);
|
|
978
|
+
}
|
|
979
|
+
if (!process.env.MSI_SECRET) {
|
|
980
|
+
throw new Error(`${msiName$6}: Missing environment variable: MSI_SECRET`);
|
|
981
|
+
}
|
|
982
|
+
return {
|
|
983
|
+
url: `${process.env.MSI_ENDPOINT}?${query.toString()}`,
|
|
984
|
+
method: "GET",
|
|
985
|
+
headers: coreRestPipeline.createHttpHeaders({
|
|
986
|
+
Accept: "application/json",
|
|
987
|
+
secret: process.env.MSI_SECRET,
|
|
988
|
+
}),
|
|
989
|
+
};
|
|
990
|
+
}
|
|
991
|
+
/**
|
|
992
|
+
* 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.
|
|
993
|
+
*/
|
|
994
|
+
const appServiceMsi2017 = {
|
|
995
|
+
name: "appServiceMsi2017",
|
|
996
|
+
async isAvailable({ scopes }) {
|
|
997
|
+
const resource = mapScopesToResource(scopes);
|
|
998
|
+
if (!resource) {
|
|
999
|
+
logger$n.info(`${msiName$6}: Unavailable. Multiple scopes are not supported.`);
|
|
1000
|
+
return false;
|
|
1001
|
+
}
|
|
1002
|
+
const env = process.env;
|
|
1003
|
+
const result = Boolean(env.MSI_ENDPOINT && env.MSI_SECRET);
|
|
1004
|
+
if (!result) {
|
|
1005
|
+
logger$n.info(`${msiName$6}: Unavailable. The environment variables needed are: MSI_ENDPOINT and MSI_SECRET.`);
|
|
1006
|
+
}
|
|
1007
|
+
return result;
|
|
1008
|
+
},
|
|
1009
|
+
async getToken(configuration, getTokenOptions = {}) {
|
|
1010
|
+
const { identityClient, scopes, clientId, resourceId } = configuration;
|
|
1011
|
+
if (resourceId) {
|
|
1012
|
+
logger$n.warning(`${msiName$6}: managed Identity by resource Id is not supported. Argument resourceId might be ignored by the service.`);
|
|
1013
|
+
}
|
|
1014
|
+
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].`);
|
|
1015
|
+
const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$5(scopes, clientId)), {
|
|
1016
|
+
// Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS).
|
|
1017
|
+
allowInsecureConnection: true }));
|
|
1018
|
+
const tokenResponse = await identityClient.sendTokenRequest(request);
|
|
1019
|
+
return (tokenResponse && tokenResponse.accessToken) || null;
|
|
1020
|
+
},
|
|
1021
|
+
};
|
|
1022
|
+
|
|
1023
|
+
// Copyright (c) Microsoft Corporation.
|
|
1024
|
+
// Licensed under the MIT license.
|
|
1025
|
+
const msiName$5 = "ManagedIdentityCredential - AppServiceMSI 2019";
|
|
1026
|
+
const logger$m = credentialLogger(msiName$5);
|
|
1027
|
+
/**
|
|
1028
|
+
* Generates the options used on the request for an access token.
|
|
1029
|
+
*/
|
|
1030
|
+
function prepareRequestOptions$4(scopes, clientId, resourceId) {
|
|
1031
|
+
const resource = mapScopesToResource(scopes);
|
|
1032
|
+
if (!resource) {
|
|
1033
|
+
throw new Error(`${msiName$5}: Multiple scopes are not supported.`);
|
|
1034
|
+
}
|
|
1035
|
+
const queryParameters = {
|
|
1036
|
+
resource,
|
|
1037
|
+
"api-version": "2019-08-01",
|
|
1038
|
+
};
|
|
1039
|
+
if (clientId) {
|
|
1040
|
+
queryParameters.client_id = clientId;
|
|
1041
|
+
}
|
|
1042
|
+
if (resourceId) {
|
|
1043
|
+
queryParameters.mi_res_id = resourceId;
|
|
1044
|
+
}
|
|
1045
|
+
const query = new URLSearchParams(queryParameters);
|
|
1046
|
+
// This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
|
|
1047
|
+
if (!process.env.IDENTITY_ENDPOINT) {
|
|
1048
|
+
throw new Error(`${msiName$5}: Missing environment variable: IDENTITY_ENDPOINT`);
|
|
1049
|
+
}
|
|
1050
|
+
if (!process.env.IDENTITY_HEADER) {
|
|
1051
|
+
throw new Error(`${msiName$5}: Missing environment variable: IDENTITY_HEADER`);
|
|
1052
|
+
}
|
|
1053
|
+
return {
|
|
1054
|
+
url: `${process.env.IDENTITY_ENDPOINT}?${query.toString()}`,
|
|
1055
|
+
method: "GET",
|
|
1056
|
+
headers: coreRestPipeline.createHttpHeaders({
|
|
1057
|
+
Accept: "application/json",
|
|
1058
|
+
"X-IDENTITY-HEADER": process.env.IDENTITY_HEADER,
|
|
1059
|
+
}),
|
|
1060
|
+
};
|
|
1061
|
+
}
|
|
1062
|
+
/**
|
|
1063
|
+
* 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.
|
|
1064
|
+
*/
|
|
1065
|
+
const appServiceMsi2019 = {
|
|
1066
|
+
name: "appServiceMsi2019",
|
|
1067
|
+
async isAvailable({ scopes }) {
|
|
1068
|
+
const resource = mapScopesToResource(scopes);
|
|
1069
|
+
if (!resource) {
|
|
1070
|
+
logger$m.info(`${msiName$5}: Unavailable. Multiple scopes are not supported.`);
|
|
1071
|
+
return false;
|
|
1072
|
+
}
|
|
1073
|
+
const env = process.env;
|
|
1074
|
+
const result = Boolean(env.IDENTITY_ENDPOINT && env.IDENTITY_HEADER);
|
|
1075
|
+
if (!result) {
|
|
1076
|
+
logger$m.info(`${msiName$5}: Unavailable. The environment variables needed are: IDENTITY_ENDPOINT and IDENTITY_HEADER.`);
|
|
1077
|
+
}
|
|
1078
|
+
return result;
|
|
1079
|
+
},
|
|
1080
|
+
async getToken(configuration, getTokenOptions = {}) {
|
|
1081
|
+
const { identityClient, scopes, clientId, resourceId } = configuration;
|
|
1082
|
+
logger$m.info(`${msiName$5}: Using the endpoint and the secret coming form the environment variables: IDENTITY_ENDPOINT=${process.env.IDENTITY_ENDPOINT} and IDENTITY_HEADER=[REDACTED].`);
|
|
1083
|
+
const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$4(scopes, clientId, resourceId)), {
|
|
1084
|
+
// Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS).
|
|
1085
|
+
allowInsecureConnection: true }));
|
|
1086
|
+
const tokenResponse = await identityClient.sendTokenRequest(request);
|
|
1087
|
+
return (tokenResponse && tokenResponse.accessToken) || null;
|
|
1088
|
+
},
|
|
1089
|
+
};
|
|
1090
|
+
|
|
1091
|
+
// Copyright (c) Microsoft Corporation.
|
|
1092
|
+
// Licensed under the MIT license.
|
|
1093
|
+
const msiName$4 = "ManagedIdentityCredential - Azure Arc MSI";
|
|
1094
|
+
const logger$l = credentialLogger(msiName$4);
|
|
1095
|
+
/**
|
|
1096
|
+
* Generates the options used on the request for an access token.
|
|
1097
|
+
*/
|
|
1098
|
+
function prepareRequestOptions$3(scopes, clientId, resourceId) {
|
|
1099
|
+
const resource = mapScopesToResource(scopes);
|
|
1100
|
+
if (!resource) {
|
|
1101
|
+
throw new Error(`${msiName$4}: Multiple scopes are not supported.`);
|
|
1102
|
+
}
|
|
1103
|
+
const queryParameters = {
|
|
1104
|
+
resource,
|
|
1105
|
+
"api-version": azureArcAPIVersion,
|
|
1106
|
+
};
|
|
1107
|
+
if (clientId) {
|
|
1108
|
+
queryParameters.client_id = clientId;
|
|
1109
|
+
}
|
|
1110
|
+
if (resourceId) {
|
|
1111
|
+
queryParameters.msi_res_id = resourceId;
|
|
1112
|
+
}
|
|
1113
|
+
// This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
|
|
1114
|
+
if (!process.env.IDENTITY_ENDPOINT) {
|
|
1115
|
+
throw new Error(`${msiName$4}: Missing environment variable: IDENTITY_ENDPOINT`);
|
|
1116
|
+
}
|
|
1117
|
+
const query = new URLSearchParams(queryParameters);
|
|
1118
|
+
return coreRestPipeline.createPipelineRequest({
|
|
1119
|
+
// Should be similar to: http://localhost:40342/metadata/identity/oauth2/token
|
|
1120
|
+
url: `${process.env.IDENTITY_ENDPOINT}?${query.toString()}`,
|
|
1121
|
+
method: "GET",
|
|
1122
|
+
headers: coreRestPipeline.createHttpHeaders({
|
|
1123
|
+
Accept: "application/json",
|
|
1124
|
+
Metadata: "true",
|
|
1125
|
+
}),
|
|
1126
|
+
});
|
|
1127
|
+
}
|
|
1128
|
+
/**
|
|
1129
|
+
* Retrieves the file contents at the given path using promises.
|
|
1130
|
+
* Useful since `fs`'s readFileSync locks the thread, and to avoid extra dependencies.
|
|
1131
|
+
*/
|
|
1132
|
+
function readFileAsync$1(path, options) {
|
|
1133
|
+
return new Promise((resolve, reject) => fs.readFile(path, options, (err, data) => {
|
|
1134
|
+
if (err) {
|
|
1135
|
+
reject(err);
|
|
1136
|
+
}
|
|
1137
|
+
resolve(data);
|
|
1138
|
+
}));
|
|
1139
|
+
}
|
|
1140
|
+
/**
|
|
1141
|
+
* Does a request to the authentication provider that results in a file path.
|
|
1142
|
+
*/
|
|
1143
|
+
async function filePathRequest(identityClient, requestPrepareOptions) {
|
|
1144
|
+
const response = await identityClient.sendRequest(coreRestPipeline.createPipelineRequest(requestPrepareOptions));
|
|
1145
|
+
if (response.status !== 401) {
|
|
1146
|
+
let message = "";
|
|
1147
|
+
if (response.bodyAsText) {
|
|
1148
|
+
message = ` Response: ${response.bodyAsText}`;
|
|
1149
|
+
}
|
|
1150
|
+
throw new AuthenticationError(response.status, `${msiName$4}: To authenticate with Azure Arc MSI, status code 401 is expected on the first request. ${message}`);
|
|
1151
|
+
}
|
|
1152
|
+
const authHeader = response.headers.get("www-authenticate") || "";
|
|
1153
|
+
try {
|
|
1154
|
+
return authHeader.split("=").slice(1)[0];
|
|
1155
|
+
}
|
|
1156
|
+
catch (e) {
|
|
1157
|
+
throw Error(`Invalid www-authenticate header format: ${authHeader}`);
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
/**
|
|
1161
|
+
* Defines how to determine whether the Azure Arc MSI is available, and also how to retrieve a token from the Azure Arc MSI.
|
|
1162
|
+
*/
|
|
1163
|
+
const arcMsi = {
|
|
1164
|
+
name: "arc",
|
|
1165
|
+
async isAvailable({ scopes }) {
|
|
1166
|
+
const resource = mapScopesToResource(scopes);
|
|
1167
|
+
if (!resource) {
|
|
1168
|
+
logger$l.info(`${msiName$4}: Unavailable. Multiple scopes are not supported.`);
|
|
1169
|
+
return false;
|
|
1170
|
+
}
|
|
1171
|
+
const result = Boolean(process.env.IMDS_ENDPOINT && process.env.IDENTITY_ENDPOINT);
|
|
1172
|
+
if (!result) {
|
|
1173
|
+
logger$l.info(`${msiName$4}: The environment variables needed are: IMDS_ENDPOINT and IDENTITY_ENDPOINT`);
|
|
1174
|
+
}
|
|
1175
|
+
return result;
|
|
1176
|
+
},
|
|
1177
|
+
async getToken(configuration, getTokenOptions = {}) {
|
|
1178
|
+
var _a;
|
|
1179
|
+
const { identityClient, scopes, clientId, resourceId } = configuration;
|
|
1180
|
+
if (clientId) {
|
|
1181
|
+
logger$l.warning(`${msiName$4}: user-assigned identities not supported. The argument clientId might be ignored by the service.`);
|
|
1182
|
+
}
|
|
1183
|
+
if (resourceId) {
|
|
1184
|
+
logger$l.warning(`${msiName$4}: user defined managed Identity by resource Id is not supported. Argument resourceId will be ignored.`);
|
|
1185
|
+
}
|
|
1186
|
+
logger$l.info(`${msiName$4}: Authenticating.`);
|
|
1187
|
+
const requestOptions = Object.assign(Object.assign({ disableJsonStringifyOnBody: true, deserializationMapper: undefined, abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$3(scopes, clientId, resourceId)), { allowInsecureConnection: true });
|
|
1188
|
+
const filePath = await filePathRequest(identityClient, requestOptions);
|
|
1189
|
+
if (!filePath) {
|
|
1190
|
+
throw new Error(`${msiName$4}: Failed to find the token file.`);
|
|
1191
|
+
}
|
|
1192
|
+
const key = await readFileAsync$1(filePath, { encoding: "utf-8" });
|
|
1193
|
+
(_a = requestOptions.headers) === null || _a === void 0 ? void 0 : _a.set("Authorization", `Basic ${key}`);
|
|
1194
|
+
const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({}, requestOptions), {
|
|
1195
|
+
// Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS).
|
|
1196
|
+
allowInsecureConnection: true }));
|
|
1197
|
+
const tokenResponse = await identityClient.sendTokenRequest(request);
|
|
1198
|
+
return (tokenResponse && tokenResponse.accessToken) || null;
|
|
1199
|
+
},
|
|
1200
|
+
};
|
|
1201
|
+
|
|
1202
|
+
// Copyright (c) Microsoft Corporation.
|
|
1203
|
+
// Licensed under the MIT license.
|
|
1204
|
+
const msiName$3 = "ManagedIdentityCredential - CloudShellMSI";
|
|
1205
|
+
const logger$k = credentialLogger(msiName$3);
|
|
1206
|
+
/**
|
|
1207
|
+
* Generates the options used on the request for an access token.
|
|
1208
|
+
*/
|
|
1209
|
+
function prepareRequestOptions$2(scopes, clientId, resourceId) {
|
|
1210
|
+
const resource = mapScopesToResource(scopes);
|
|
1211
|
+
if (!resource) {
|
|
1212
|
+
throw new Error(`${msiName$3}: Multiple scopes are not supported.`);
|
|
1213
|
+
}
|
|
1214
|
+
const body = {
|
|
1215
|
+
resource,
|
|
1216
|
+
};
|
|
1217
|
+
if (clientId) {
|
|
1218
|
+
body.client_id = clientId;
|
|
1219
|
+
}
|
|
1220
|
+
if (resourceId) {
|
|
1221
|
+
body.msi_res_id = resourceId;
|
|
1222
|
+
}
|
|
1223
|
+
// This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
|
|
1224
|
+
if (!process.env.MSI_ENDPOINT) {
|
|
1225
|
+
throw new Error(`${msiName$3}: Missing environment variable: MSI_ENDPOINT`);
|
|
1226
|
+
}
|
|
1227
|
+
const params = new URLSearchParams(body);
|
|
1228
|
+
return {
|
|
1229
|
+
url: process.env.MSI_ENDPOINT,
|
|
1230
|
+
method: "POST",
|
|
1231
|
+
body: params.toString(),
|
|
1232
|
+
headers: coreRestPipeline.createHttpHeaders({
|
|
1233
|
+
Accept: "application/json",
|
|
1234
|
+
Metadata: "true",
|
|
1235
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
1236
|
+
}),
|
|
1237
|
+
};
|
|
1238
|
+
}
|
|
1239
|
+
/**
|
|
1240
|
+
* 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.
|
|
1241
|
+
* 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.
|
|
1242
|
+
*/
|
|
1243
|
+
const cloudShellMsi = {
|
|
1244
|
+
name: "cloudShellMsi",
|
|
1245
|
+
async isAvailable({ scopes }) {
|
|
1246
|
+
const resource = mapScopesToResource(scopes);
|
|
1247
|
+
if (!resource) {
|
|
1248
|
+
logger$k.info(`${msiName$3}: Unavailable. Multiple scopes are not supported.`);
|
|
1249
|
+
return false;
|
|
1327
1250
|
}
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
}
|
|
1339
|
-
this.logger.info(`Silent authentication failed, falling back to interactive method.`);
|
|
1340
|
-
return this.doGetToken(scopes, options);
|
|
1251
|
+
const result = Boolean(process.env.MSI_ENDPOINT);
|
|
1252
|
+
if (!result) {
|
|
1253
|
+
logger$k.info(`${msiName$3}: Unavailable. The environment variable MSI_ENDPOINT is needed.`);
|
|
1254
|
+
}
|
|
1255
|
+
return result;
|
|
1256
|
+
},
|
|
1257
|
+
async getToken(configuration, getTokenOptions = {}) {
|
|
1258
|
+
const { identityClient, scopes, clientId, resourceId } = configuration;
|
|
1259
|
+
if (clientId) {
|
|
1260
|
+
logger$k.warning(`${msiName$3}: user-assigned identities not supported. The argument clientId might be ignored by the service.`);
|
|
1341
1261
|
}
|
|
1262
|
+
if (resourceId) {
|
|
1263
|
+
logger$k.warning(`${msiName$3}: user defined managed Identity by resource Id not supported. The argument resourceId might be ignored by the service.`);
|
|
1264
|
+
}
|
|
1265
|
+
logger$k.info(`${msiName$3}: Using the endpoint coming form the environment variable MSI_ENDPOINT = ${process.env.MSI_ENDPOINT}.`);
|
|
1266
|
+
const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$2(scopes, clientId, resourceId)), {
|
|
1267
|
+
// Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS).
|
|
1268
|
+
allowInsecureConnection: true }));
|
|
1269
|
+
const tokenResponse = await identityClient.sendTokenRequest(request);
|
|
1270
|
+
return (tokenResponse && tokenResponse.accessToken) || null;
|
|
1271
|
+
},
|
|
1272
|
+
};
|
|
1273
|
+
|
|
1274
|
+
// Copyright (c) Microsoft Corporation.
|
|
1275
|
+
// Licensed under the MIT license.
|
|
1276
|
+
// This MSI can be easily tested by deploying a container to Azure Service Fabric with the Dockerfile:
|
|
1277
|
+
//
|
|
1278
|
+
// FROM node:12
|
|
1279
|
+
// RUN wget https://host.any/path/bash.sh
|
|
1280
|
+
// CMD ["bash", "bash.sh"]
|
|
1281
|
+
//
|
|
1282
|
+
// Where the bash script contains:
|
|
1283
|
+
//
|
|
1284
|
+
// curl --insecure $IDENTITY_ENDPOINT'?api-version=2019-07-01-preview&resource=https://vault.azure.net/' -H "Secret: $IDENTITY_HEADER"
|
|
1285
|
+
//
|
|
1286
|
+
const msiName$2 = "ManagedIdentityCredential - Fabric MSI";
|
|
1287
|
+
const logger$j = credentialLogger(msiName$2);
|
|
1288
|
+
/**
|
|
1289
|
+
* Generates the options used on the request for an access token.
|
|
1290
|
+
*/
|
|
1291
|
+
function prepareRequestOptions$1(scopes, clientId, resourceId) {
|
|
1292
|
+
const resource = mapScopesToResource(scopes);
|
|
1293
|
+
if (!resource) {
|
|
1294
|
+
throw new Error(`${msiName$2}: Multiple scopes are not supported.`);
|
|
1342
1295
|
}
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1296
|
+
const queryParameters = {
|
|
1297
|
+
resource,
|
|
1298
|
+
"api-version": azureFabricVersion,
|
|
1299
|
+
};
|
|
1300
|
+
if (clientId) {
|
|
1301
|
+
queryParameters.client_id = clientId;
|
|
1302
|
+
}
|
|
1303
|
+
if (resourceId) {
|
|
1304
|
+
queryParameters.msi_res_id = resourceId;
|
|
1305
|
+
}
|
|
1306
|
+
const query = new URLSearchParams(queryParameters);
|
|
1307
|
+
// This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
|
|
1308
|
+
if (!process.env.IDENTITY_ENDPOINT) {
|
|
1309
|
+
throw new Error("Missing environment variable: IDENTITY_ENDPOINT");
|
|
1310
|
+
}
|
|
1311
|
+
if (!process.env.IDENTITY_HEADER) {
|
|
1312
|
+
throw new Error("Missing environment variable: IDENTITY_HEADER");
|
|
1313
|
+
}
|
|
1314
|
+
return {
|
|
1315
|
+
url: `${process.env.IDENTITY_ENDPOINT}?${query.toString()}`,
|
|
1316
|
+
method: "GET",
|
|
1317
|
+
headers: coreRestPipeline.createHttpHeaders({
|
|
1318
|
+
Accept: "application/json",
|
|
1319
|
+
secret: process.env.IDENTITY_HEADER,
|
|
1320
|
+
}),
|
|
1321
|
+
};
|
|
1322
|
+
}
|
|
1323
|
+
/**
|
|
1324
|
+
* Defines how to determine whether the Azure Service Fabric MSI is available, and also how to retrieve a token from the Azure Service Fabric MSI.
|
|
1325
|
+
*/
|
|
1326
|
+
const fabricMsi = {
|
|
1327
|
+
name: "fabricMsi",
|
|
1328
|
+
async isAvailable({ scopes }) {
|
|
1329
|
+
const resource = mapScopesToResource(scopes);
|
|
1330
|
+
if (!resource) {
|
|
1331
|
+
logger$j.info(`${msiName$2}: Unavailable. Multiple scopes are not supported.`);
|
|
1332
|
+
return false;
|
|
1351
1333
|
}
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1334
|
+
const env = process.env;
|
|
1335
|
+
const result = Boolean(env.IDENTITY_ENDPOINT && env.IDENTITY_HEADER && env.IDENTITY_SERVER_THUMBPRINT);
|
|
1336
|
+
if (!result) {
|
|
1337
|
+
logger$j.info(`${msiName$2}: Unavailable. The environment variables needed are: IDENTITY_ENDPOINT, IDENTITY_HEADER and IDENTITY_SERVER_THUMBPRINT`);
|
|
1338
|
+
}
|
|
1339
|
+
return result;
|
|
1340
|
+
},
|
|
1341
|
+
async getToken(configuration, getTokenOptions = {}) {
|
|
1342
|
+
const { scopes, identityClient, clientId, resourceId } = configuration;
|
|
1343
|
+
if (resourceId) {
|
|
1344
|
+
logger$j.warning(`${msiName$2}: user defined managed Identity by resource Id is not supported. Argument resourceId might be ignored by the service.`);
|
|
1345
|
+
}
|
|
1346
|
+
logger$j.info([
|
|
1347
|
+
`${msiName$2}:`,
|
|
1348
|
+
"Using the endpoint and the secret coming from the environment variables:",
|
|
1349
|
+
`IDENTITY_ENDPOINT=${process.env.IDENTITY_ENDPOINT},`,
|
|
1350
|
+
"IDENTITY_HEADER=[REDACTED] and",
|
|
1351
|
+
"IDENTITY_SERVER_THUMBPRINT=[REDACTED].",
|
|
1352
|
+
].join(" "));
|
|
1353
|
+
const request = coreRestPipeline.createPipelineRequest(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$1(scopes, clientId, resourceId)));
|
|
1354
|
+
request.agent = new https.Agent({
|
|
1355
|
+
// This is necessary because Service Fabric provides a self-signed certificate.
|
|
1356
|
+
// The alternative path is to verify the certificate using the IDENTITY_SERVER_THUMBPRINT env variable.
|
|
1357
|
+
rejectUnauthorized: false,
|
|
1358
|
+
});
|
|
1359
|
+
const tokenResponse = await identityClient.sendTokenRequest(request);
|
|
1360
|
+
return (tokenResponse && tokenResponse.accessToken) || null;
|
|
1361
|
+
},
|
|
1362
|
+
};
|
|
1363
|
+
|
|
1364
|
+
// Copyright (c) Microsoft Corporation.
|
|
1365
|
+
// Licensed under the MIT license.
|
|
1366
|
+
/**
|
|
1367
|
+
* @internal
|
|
1368
|
+
*/
|
|
1369
|
+
const logger$i = credentialLogger("IdentityUtils");
|
|
1370
|
+
/**
|
|
1371
|
+
* Latest AuthenticationRecord version
|
|
1372
|
+
* @internal
|
|
1373
|
+
*/
|
|
1374
|
+
const LatestAuthenticationRecordVersion = "1.0";
|
|
1375
|
+
/**
|
|
1376
|
+
* Ensures the validity of the MSAL token
|
|
1377
|
+
* @internal
|
|
1378
|
+
*/
|
|
1379
|
+
function ensureValidMsalToken(scopes, msalToken, getTokenOptions) {
|
|
1380
|
+
const error = (message) => {
|
|
1381
|
+
logger$i.getToken.info(message);
|
|
1382
|
+
return new AuthenticationRequiredError({
|
|
1383
|
+
scopes: Array.isArray(scopes) ? scopes : [scopes],
|
|
1384
|
+
getTokenOptions,
|
|
1385
|
+
message,
|
|
1386
|
+
});
|
|
1387
|
+
};
|
|
1388
|
+
if (!msalToken) {
|
|
1389
|
+
throw error("No response");
|
|
1390
|
+
}
|
|
1391
|
+
if (!msalToken.expiresOn) {
|
|
1392
|
+
throw error(`Response had no "expiresOn" property.`);
|
|
1393
|
+
}
|
|
1394
|
+
if (!msalToken.accessToken) {
|
|
1395
|
+
throw error(`Response had no "accessToken" property.`);
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
/**
|
|
1399
|
+
* Generates a valid authority by combining a host with a tenantId.
|
|
1400
|
+
* @internal
|
|
1401
|
+
*/
|
|
1402
|
+
function getAuthority(tenantId, host) {
|
|
1403
|
+
if (!host) {
|
|
1404
|
+
host = DefaultAuthorityHost;
|
|
1405
|
+
}
|
|
1406
|
+
if (new RegExp(`${tenantId}/?$`).test(host)) {
|
|
1407
|
+
return host;
|
|
1408
|
+
}
|
|
1409
|
+
if (host.endsWith("/")) {
|
|
1410
|
+
return host + tenantId;
|
|
1411
|
+
}
|
|
1412
|
+
else {
|
|
1413
|
+
return `${host}/${tenantId}`;
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
/**
|
|
1417
|
+
* Generates the known authorities.
|
|
1418
|
+
* If the Tenant Id is `adfs`, the authority can't be validated since the format won't match the expected one.
|
|
1419
|
+
* For that reason, we have to force MSAL to disable validating the authority
|
|
1420
|
+
* by sending it within the known authorities in the MSAL configuration.
|
|
1421
|
+
* @internal
|
|
1422
|
+
*/
|
|
1423
|
+
function getKnownAuthorities(tenantId, authorityHost, disableInstanceDiscovery) {
|
|
1424
|
+
if ((tenantId === "adfs" && authorityHost) || disableInstanceDiscovery) {
|
|
1425
|
+
return [authorityHost];
|
|
1426
|
+
}
|
|
1427
|
+
return [];
|
|
1428
|
+
}
|
|
1429
|
+
/**
|
|
1430
|
+
* Generates a logger that can be passed to the MSAL clients.
|
|
1431
|
+
* @param credLogger - The logger of the credential.
|
|
1432
|
+
* @internal
|
|
1433
|
+
*/
|
|
1434
|
+
const defaultLoggerCallback = (credLogger, platform = coreUtil.isNode ? "Node" : "Browser") => (level, message, containsPii) => {
|
|
1435
|
+
if (containsPii) {
|
|
1436
|
+
return;
|
|
1437
|
+
}
|
|
1438
|
+
switch (level) {
|
|
1439
|
+
case msalCommon__namespace.LogLevel.Error:
|
|
1440
|
+
credLogger.info(`MSAL ${platform} V2 error: ${message}`);
|
|
1441
|
+
return;
|
|
1442
|
+
case msalCommon__namespace.LogLevel.Info:
|
|
1443
|
+
credLogger.info(`MSAL ${platform} V2 info message: ${message}`);
|
|
1444
|
+
return;
|
|
1445
|
+
case msalCommon__namespace.LogLevel.Verbose:
|
|
1446
|
+
credLogger.info(`MSAL ${platform} V2 verbose message: ${message}`);
|
|
1447
|
+
return;
|
|
1448
|
+
case msalCommon__namespace.LogLevel.Warning:
|
|
1449
|
+
credLogger.info(`MSAL ${platform} V2 warning: ${message}`);
|
|
1450
|
+
return;
|
|
1358
1451
|
}
|
|
1359
|
-
}
|
|
1360
|
-
|
|
1361
|
-
// Copyright (c) Microsoft Corporation.
|
|
1362
|
-
// Licensed under the MIT license.
|
|
1363
|
-
const CommonTenantId = "common";
|
|
1364
|
-
const AzureAccountClientId = "aebc6443-996d-45c2-90f0-388ff96faa56"; // VSC: 'aebc6443-996d-45c2-90f0-388ff96faa56'
|
|
1365
|
-
const logger$n = credentialLogger("VisualStudioCodeCredential");
|
|
1366
|
-
let findCredentials = undefined;
|
|
1367
|
-
const vsCodeCredentialControl = {
|
|
1368
|
-
setVsCodeCredentialFinder(finder) {
|
|
1369
|
-
findCredentials = finder;
|
|
1370
|
-
},
|
|
1371
|
-
};
|
|
1372
|
-
// Map of unsupported Tenant IDs and the errors we will be throwing.
|
|
1373
|
-
const unsupportedTenantIds = {
|
|
1374
|
-
adfs: "The VisualStudioCodeCredential does not support authentication with ADFS tenants.",
|
|
1375
1452
|
};
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1453
|
+
/**
|
|
1454
|
+
* @internal
|
|
1455
|
+
*/
|
|
1456
|
+
function getMSALLogLevel(logLevel) {
|
|
1457
|
+
switch (logLevel) {
|
|
1458
|
+
case "error":
|
|
1459
|
+
return msalCommon__namespace.LogLevel.Error;
|
|
1460
|
+
case "info":
|
|
1461
|
+
return msalCommon__namespace.LogLevel.Info;
|
|
1462
|
+
case "verbose":
|
|
1463
|
+
return msalCommon__namespace.LogLevel.Verbose;
|
|
1464
|
+
case "warning":
|
|
1465
|
+
return msalCommon__namespace.LogLevel.Warning;
|
|
1466
|
+
default:
|
|
1467
|
+
// default msal logging level should be Info
|
|
1468
|
+
return msalCommon__namespace.LogLevel.Info;
|
|
1381
1469
|
}
|
|
1382
1470
|
}
|
|
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
1471
|
/**
|
|
1390
|
-
*
|
|
1391
|
-
*
|
|
1472
|
+
* Wraps core-util's randomUUID in order to allow for mocking in tests.
|
|
1473
|
+
* This prepares the library for the upcoming core-util update to ESM.
|
|
1474
|
+
*
|
|
1475
|
+
* @internal
|
|
1476
|
+
* @returns A string containing a random UUID
|
|
1392
1477
|
*/
|
|
1393
|
-
function
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
case "
|
|
1412
|
-
|
|
1478
|
+
function randomUUID() {
|
|
1479
|
+
return coreUtil.randomUUID();
|
|
1480
|
+
}
|
|
1481
|
+
/**
|
|
1482
|
+
* Handles MSAL errors.
|
|
1483
|
+
*/
|
|
1484
|
+
function handleMsalError(scopes, error, getTokenOptions) {
|
|
1485
|
+
if (error.name === "AuthError" ||
|
|
1486
|
+
error.name === "ClientAuthError" ||
|
|
1487
|
+
error.name === "BrowserAuthError") {
|
|
1488
|
+
const msalError = error;
|
|
1489
|
+
switch (msalError.errorCode) {
|
|
1490
|
+
case "endpoints_resolution_error":
|
|
1491
|
+
logger$i.info(formatError(scopes, error.message));
|
|
1492
|
+
return new CredentialUnavailableError(error.message);
|
|
1493
|
+
case "device_code_polling_cancelled":
|
|
1494
|
+
return new abortController.AbortError("The authentication has been aborted by the caller.");
|
|
1495
|
+
case "consent_required":
|
|
1496
|
+
case "interaction_required":
|
|
1497
|
+
case "login_required":
|
|
1498
|
+
logger$i.info(formatError(scopes, `Authentication returned errorCode ${msalError.errorCode}`));
|
|
1499
|
+
break;
|
|
1413
1500
|
default:
|
|
1414
|
-
|
|
1501
|
+
logger$i.info(formatError(scopes, `Failed to acquire token: ${error.message}`));
|
|
1502
|
+
break;
|
|
1415
1503
|
}
|
|
1416
1504
|
}
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1505
|
+
if (error.name === "ClientConfigurationError" ||
|
|
1506
|
+
error.name === "BrowserConfigurationAuthError" ||
|
|
1507
|
+
error.name === "AbortError") {
|
|
1508
|
+
return error;
|
|
1509
|
+
}
|
|
1510
|
+
if (error.name === "NativeAuthError") {
|
|
1511
|
+
logger$i.info(formatError(scopes, `Error from the native broker: ${error.message} with status code: ${error.statusCode}`));
|
|
1512
|
+
return error;
|
|
1420
1513
|
}
|
|
1514
|
+
return new AuthenticationRequiredError({ scopes, getTokenOptions, message: error.message });
|
|
1515
|
+
}
|
|
1516
|
+
// transformations.ts
|
|
1517
|
+
function publicToMsal(account) {
|
|
1518
|
+
const [environment] = account.authority.match(/([a-z]*\.[a-z]*\.[a-z]*)/) || [""];
|
|
1519
|
+
return Object.assign(Object.assign({}, account), { localAccountId: account.homeAccountId, environment });
|
|
1520
|
+
}
|
|
1521
|
+
function msalToPublic(clientId, account) {
|
|
1522
|
+
const record = {
|
|
1523
|
+
authority: getAuthority(account.tenantId, account.environment),
|
|
1524
|
+
homeAccountId: account.homeAccountId,
|
|
1525
|
+
tenantId: account.tenantId || DefaultTenantId,
|
|
1526
|
+
username: account.username,
|
|
1527
|
+
clientId,
|
|
1528
|
+
version: LatestAuthenticationRecordVersion,
|
|
1529
|
+
};
|
|
1530
|
+
return record;
|
|
1421
1531
|
}
|
|
1422
1532
|
/**
|
|
1423
|
-
*
|
|
1424
|
-
* Once the user has logged in via the extension, this credential can share the same refresh token
|
|
1425
|
-
* that is cached by the extension.
|
|
1533
|
+
* Serializes an `AuthenticationRecord` into a string.
|
|
1426
1534
|
*
|
|
1427
|
-
*
|
|
1428
|
-
*
|
|
1429
|
-
*
|
|
1430
|
-
*
|
|
1535
|
+
* The output of a serialized authentication record will contain the following properties:
|
|
1536
|
+
*
|
|
1537
|
+
* - "authority"
|
|
1538
|
+
* - "homeAccountId"
|
|
1539
|
+
* - "clientId"
|
|
1540
|
+
* - "tenantId"
|
|
1541
|
+
* - "username"
|
|
1542
|
+
* - "version"
|
|
1543
|
+
*
|
|
1544
|
+
* To later convert this string to a serialized `AuthenticationRecord`, please use the exported function `deserializeAuthenticationRecord()`.
|
|
1431
1545
|
*/
|
|
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
|
-
|
|
1458
|
-
checkUnsupportedTenant(this.tenantId);
|
|
1546
|
+
function serializeAuthenticationRecord(record) {
|
|
1547
|
+
return JSON.stringify(record);
|
|
1548
|
+
}
|
|
1549
|
+
/**
|
|
1550
|
+
* Deserializes a previously serialized authentication record from a string into an object.
|
|
1551
|
+
*
|
|
1552
|
+
* The input string must contain the following properties:
|
|
1553
|
+
*
|
|
1554
|
+
* - "authority"
|
|
1555
|
+
* - "homeAccountId"
|
|
1556
|
+
* - "clientId"
|
|
1557
|
+
* - "tenantId"
|
|
1558
|
+
* - "username"
|
|
1559
|
+
* - "version"
|
|
1560
|
+
*
|
|
1561
|
+
* If the version we receive is unsupported, an error will be thrown.
|
|
1562
|
+
*
|
|
1563
|
+
* At the moment, the only available version is: "1.0", which is always set when the authentication record is serialized.
|
|
1564
|
+
*
|
|
1565
|
+
* @param serializedRecord - Authentication record previously serialized into string.
|
|
1566
|
+
* @returns AuthenticationRecord.
|
|
1567
|
+
*/
|
|
1568
|
+
function deserializeAuthenticationRecord(serializedRecord) {
|
|
1569
|
+
const parsed = JSON.parse(serializedRecord);
|
|
1570
|
+
if (parsed.version && parsed.version !== LatestAuthenticationRecordVersion) {
|
|
1571
|
+
throw Error("Unsupported AuthenticationRecord version");
|
|
1459
1572
|
}
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1573
|
+
return parsed;
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
// Copyright (c) Microsoft Corporation.
|
|
1577
|
+
// Licensed under the MIT license.
|
|
1578
|
+
const msiName$1 = "ManagedIdentityCredential - IMDS";
|
|
1579
|
+
const logger$h = credentialLogger(msiName$1);
|
|
1580
|
+
/**
|
|
1581
|
+
* Generates the options used on the request for an access token.
|
|
1582
|
+
*/
|
|
1583
|
+
function prepareRequestOptions(scopes, clientId, resourceId, options) {
|
|
1584
|
+
var _a;
|
|
1585
|
+
const resource = mapScopesToResource(scopes);
|
|
1586
|
+
if (!resource) {
|
|
1587
|
+
throw new Error(`${msiName$1}: Multiple scopes are not supported.`);
|
|
1470
1588
|
}
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1589
|
+
const { skipQuery, skipMetadataHeader } = options || {};
|
|
1590
|
+
let query = "";
|
|
1591
|
+
// Pod Identity will try to process this request even if the Metadata header is missing.
|
|
1592
|
+
// We can exclude the request query to ensure no IMDS endpoint tries to process the ping request.
|
|
1593
|
+
if (!skipQuery) {
|
|
1594
|
+
const queryParameters = {
|
|
1595
|
+
resource,
|
|
1596
|
+
"api-version": imdsApiVersion,
|
|
1597
|
+
};
|
|
1598
|
+
if (clientId) {
|
|
1599
|
+
queryParameters.client_id = clientId;
|
|
1477
1600
|
}
|
|
1478
|
-
|
|
1601
|
+
if (resourceId) {
|
|
1602
|
+
queryParameters.msi_res_id = resourceId;
|
|
1603
|
+
}
|
|
1604
|
+
const params = new URLSearchParams(queryParameters);
|
|
1605
|
+
query = `?${params.toString()}`;
|
|
1479
1606
|
}
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1607
|
+
const url = new URL(imdsEndpointPath, (_a = process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) !== null && _a !== void 0 ? _a : imdsHost);
|
|
1608
|
+
const rawHeaders = {
|
|
1609
|
+
Accept: "application/json",
|
|
1610
|
+
Metadata: "true",
|
|
1611
|
+
};
|
|
1612
|
+
// Remove the Metadata header to invoke a request error from some IMDS endpoints.
|
|
1613
|
+
if (skipMetadataHeader) {
|
|
1614
|
+
delete rawHeaders.Metadata;
|
|
1615
|
+
}
|
|
1616
|
+
return {
|
|
1617
|
+
// In this case, the `?` should be added in the "query" variable `skipQuery` is not set.
|
|
1618
|
+
url: `${url}${query}`,
|
|
1619
|
+
method: "GET",
|
|
1620
|
+
headers: coreRestPipeline.createHttpHeaders(rawHeaders),
|
|
1621
|
+
};
|
|
1622
|
+
}
|
|
1623
|
+
/**
|
|
1624
|
+
* Defines how to determine whether the Azure IMDS MSI is available, and also how to retrieve a token from the Azure IMDS MSI.
|
|
1625
|
+
*/
|
|
1626
|
+
const imdsMsi = {
|
|
1627
|
+
name: "imdsMsi",
|
|
1628
|
+
async isAvailable({ scopes, identityClient, clientId, resourceId, getTokenOptions = {}, }) {
|
|
1629
|
+
const resource = mapScopesToResource(scopes);
|
|
1630
|
+
if (!resource) {
|
|
1631
|
+
logger$h.info(`${msiName$1}: Unavailable. Multiple scopes are not supported.`);
|
|
1632
|
+
return false;
|
|
1500
1633
|
}
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
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;
|
|
1634
|
+
// if the PodIdentityEndpoint environment variable was set no need to probe the endpoint, it can be assumed to exist
|
|
1635
|
+
if (process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) {
|
|
1636
|
+
return true;
|
|
1507
1637
|
}
|
|
1508
|
-
if (
|
|
1509
|
-
|
|
1638
|
+
if (!identityClient) {
|
|
1639
|
+
throw new Error("Missing IdentityClient");
|
|
1510
1640
|
}
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1641
|
+
const requestOptions = prepareRequestOptions(resource, clientId, resourceId, {
|
|
1642
|
+
skipMetadataHeader: true,
|
|
1643
|
+
skipQuery: true,
|
|
1644
|
+
});
|
|
1645
|
+
return tracingClient.withSpan("ManagedIdentityCredential-pingImdsEndpoint", getTokenOptions, async (options) => {
|
|
1646
|
+
var _a, _b;
|
|
1647
|
+
requestOptions.tracingOptions = options.tracingOptions;
|
|
1648
|
+
// Create a request with a timeout since we expect that
|
|
1649
|
+
// not having a "Metadata" header should cause an error to be
|
|
1650
|
+
// returned quickly from the endpoint, proving its availability.
|
|
1651
|
+
const request = coreRestPipeline.createPipelineRequest(requestOptions);
|
|
1652
|
+
// Default to 1000 if the default of 0 is used.
|
|
1653
|
+
// Negative values can still be used to disable the timeout.
|
|
1654
|
+
request.timeout = ((_a = options.requestOptions) === null || _a === void 0 ? void 0 : _a.timeout) || 1000;
|
|
1655
|
+
// This MSI uses the imdsEndpoint to get the token, which only uses http://
|
|
1656
|
+
request.allowInsecureConnection = true;
|
|
1657
|
+
let response;
|
|
1658
|
+
try {
|
|
1659
|
+
logger$h.info(`${msiName$1}: Pinging the Azure IMDS endpoint`);
|
|
1660
|
+
response = await identityClient.sendRequest(request);
|
|
1527
1661
|
}
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1662
|
+
catch (err) {
|
|
1663
|
+
// If the request failed, or Node.js was unable to establish a connection,
|
|
1664
|
+
// or the host was down, we'll assume the IMDS endpoint isn't available.
|
|
1665
|
+
if (coreUtil.isError(err)) {
|
|
1666
|
+
logger$h.verbose(`${msiName$1}: Caught error ${err.name}: ${err.message}`);
|
|
1667
|
+
}
|
|
1668
|
+
// 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" or "A socket operation was attempted to an unreachable host"
|
|
1669
|
+
// rather than just timing out, as expected.
|
|
1670
|
+
logger$h.info(`${msiName$1}: The Azure IMDS endpoint is unavailable`);
|
|
1671
|
+
return false;
|
|
1672
|
+
}
|
|
1673
|
+
if (response.status === 403) {
|
|
1674
|
+
if ((_b = response.bodyAsText) === null || _b === void 0 ? void 0 : _b.includes("unreachable")) {
|
|
1675
|
+
logger$h.info(`${msiName$1}: The Azure IMDS endpoint is unavailable`);
|
|
1676
|
+
logger$h.info(`${msiName$1}: ${response.bodyAsText}`);
|
|
1677
|
+
return false;
|
|
1678
|
+
}
|
|
1532
1679
|
}
|
|
1680
|
+
// If we received any response, the endpoint is available
|
|
1681
|
+
logger$h.info(`${msiName$1}: The Azure IMDS endpoint is available`);
|
|
1682
|
+
return true;
|
|
1683
|
+
});
|
|
1684
|
+
},
|
|
1685
|
+
async getToken(configuration, getTokenOptions = {}) {
|
|
1686
|
+
const { identityClient, scopes, clientId, resourceId } = configuration;
|
|
1687
|
+
if (process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) {
|
|
1688
|
+
logger$h.info(`${msiName$1}: Using the Azure IMDS endpoint coming from the environment variable AZURE_POD_IDENTITY_AUTHORITY_HOST=${process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST}.`);
|
|
1533
1689
|
}
|
|
1534
1690
|
else {
|
|
1535
|
-
|
|
1536
|
-
logger$n.getToken.info(formatError(scopes, error));
|
|
1537
|
-
throw error;
|
|
1691
|
+
logger$h.info(`${msiName$1}: Using the default Azure IMDS endpoint ${imdsHost}.`);
|
|
1538
1692
|
}
|
|
1539
|
-
|
|
1540
|
-
|
|
1693
|
+
let nextDelayInMs = configuration.retryConfig.startDelayInMs;
|
|
1694
|
+
for (let retries = 0; retries < configuration.retryConfig.maxRetries; retries++) {
|
|
1695
|
+
try {
|
|
1696
|
+
const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions(scopes, clientId, resourceId)), { allowInsecureConnection: true }));
|
|
1697
|
+
const tokenResponse = await identityClient.sendTokenRequest(request);
|
|
1698
|
+
return (tokenResponse && tokenResponse.accessToken) || null;
|
|
1699
|
+
}
|
|
1700
|
+
catch (error) {
|
|
1701
|
+
if (error.statusCode === 404) {
|
|
1702
|
+
await coreUtil.delay(nextDelayInMs);
|
|
1703
|
+
nextDelayInMs *= configuration.retryConfig.intervalIncrement;
|
|
1704
|
+
continue;
|
|
1705
|
+
}
|
|
1706
|
+
throw error;
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
throw new AuthenticationError(404, `${msiName$1}: Failed to retrieve IMDS token after ${configuration.retryConfig.maxRetries} retries.`);
|
|
1710
|
+
},
|
|
1711
|
+
};
|
|
1541
1712
|
|
|
1542
1713
|
// Copyright (c) Microsoft Corporation.
|
|
1543
1714
|
// Licensed under the MIT license.
|
|
1544
1715
|
/**
|
|
1545
|
-
*
|
|
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
|
-
/**
|
|
1555
|
-
* Extend Azure Identity with additional functionality. Pass a plugin from
|
|
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";
|
|
1566
|
-
*
|
|
1567
|
-
* import { useIdentityPlugin, DefaultAzureCredential } from "@azure/identity";
|
|
1568
|
-
* useIdentityPlugin(cachePersistencePlugin);
|
|
1569
|
-
*
|
|
1570
|
-
* // The plugin has the capability to extend `DefaultAzureCredential` and to
|
|
1571
|
-
* // add middleware to the underlying credentials, such as persistence.
|
|
1572
|
-
* const credential = new DefaultAzureCredential({
|
|
1573
|
-
* tokenCachePersistenceOptions: {
|
|
1574
|
-
* enabled: true
|
|
1575
|
-
* }
|
|
1576
|
-
* });
|
|
1577
|
-
* ```
|
|
1578
|
-
*
|
|
1579
|
-
* @param plugin - the plugin to register
|
|
1716
|
+
* Helps specify a regional authority, or "AutoDiscoverRegion" to auto-detect the region.
|
|
1580
1717
|
*/
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1718
|
+
var RegionalAuthority;
|
|
1719
|
+
(function (RegionalAuthority) {
|
|
1720
|
+
/** Instructs MSAL to attempt to discover the region */
|
|
1721
|
+
RegionalAuthority["AutoDiscoverRegion"] = "AutoDiscoverRegion";
|
|
1722
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'westus' region. */
|
|
1723
|
+
RegionalAuthority["USWest"] = "westus";
|
|
1724
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'westus2' region. */
|
|
1725
|
+
RegionalAuthority["USWest2"] = "westus2";
|
|
1726
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'centralus' region. */
|
|
1727
|
+
RegionalAuthority["USCentral"] = "centralus";
|
|
1728
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'eastus' region. */
|
|
1729
|
+
RegionalAuthority["USEast"] = "eastus";
|
|
1730
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'eastus2' region. */
|
|
1731
|
+
RegionalAuthority["USEast2"] = "eastus2";
|
|
1732
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'northcentralus' region. */
|
|
1733
|
+
RegionalAuthority["USNorthCentral"] = "northcentralus";
|
|
1734
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'southcentralus' region. */
|
|
1735
|
+
RegionalAuthority["USSouthCentral"] = "southcentralus";
|
|
1736
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'westcentralus' region. */
|
|
1737
|
+
RegionalAuthority["USWestCentral"] = "westcentralus";
|
|
1738
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'canadacentral' region. */
|
|
1739
|
+
RegionalAuthority["CanadaCentral"] = "canadacentral";
|
|
1740
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'canadaeast' region. */
|
|
1741
|
+
RegionalAuthority["CanadaEast"] = "canadaeast";
|
|
1742
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'brazilsouth' region. */
|
|
1743
|
+
RegionalAuthority["BrazilSouth"] = "brazilsouth";
|
|
1744
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'northeurope' region. */
|
|
1745
|
+
RegionalAuthority["EuropeNorth"] = "northeurope";
|
|
1746
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'westeurope' region. */
|
|
1747
|
+
RegionalAuthority["EuropeWest"] = "westeurope";
|
|
1748
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'uksouth' region. */
|
|
1749
|
+
RegionalAuthority["UKSouth"] = "uksouth";
|
|
1750
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'ukwest' region. */
|
|
1751
|
+
RegionalAuthority["UKWest"] = "ukwest";
|
|
1752
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'francecentral' region. */
|
|
1753
|
+
RegionalAuthority["FranceCentral"] = "francecentral";
|
|
1754
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'francesouth' region. */
|
|
1755
|
+
RegionalAuthority["FranceSouth"] = "francesouth";
|
|
1756
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'switzerlandnorth' region. */
|
|
1757
|
+
RegionalAuthority["SwitzerlandNorth"] = "switzerlandnorth";
|
|
1758
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'switzerlandwest' region. */
|
|
1759
|
+
RegionalAuthority["SwitzerlandWest"] = "switzerlandwest";
|
|
1760
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'germanynorth' region. */
|
|
1761
|
+
RegionalAuthority["GermanyNorth"] = "germanynorth";
|
|
1762
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'germanywestcentral' region. */
|
|
1763
|
+
RegionalAuthority["GermanyWestCentral"] = "germanywestcentral";
|
|
1764
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'norwaywest' region. */
|
|
1765
|
+
RegionalAuthority["NorwayWest"] = "norwaywest";
|
|
1766
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'norwayeast' region. */
|
|
1767
|
+
RegionalAuthority["NorwayEast"] = "norwayeast";
|
|
1768
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'eastasia' region. */
|
|
1769
|
+
RegionalAuthority["AsiaEast"] = "eastasia";
|
|
1770
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'southeastasia' region. */
|
|
1771
|
+
RegionalAuthority["AsiaSouthEast"] = "southeastasia";
|
|
1772
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'japaneast' region. */
|
|
1773
|
+
RegionalAuthority["JapanEast"] = "japaneast";
|
|
1774
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'japanwest' region. */
|
|
1775
|
+
RegionalAuthority["JapanWest"] = "japanwest";
|
|
1776
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'australiaeast' region. */
|
|
1777
|
+
RegionalAuthority["AustraliaEast"] = "australiaeast";
|
|
1778
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'australiasoutheast' region. */
|
|
1779
|
+
RegionalAuthority["AustraliaSouthEast"] = "australiasoutheast";
|
|
1780
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'australiacentral' region. */
|
|
1781
|
+
RegionalAuthority["AustraliaCentral"] = "australiacentral";
|
|
1782
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'australiacentral2' region. */
|
|
1783
|
+
RegionalAuthority["AustraliaCentral2"] = "australiacentral2";
|
|
1784
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'centralindia' region. */
|
|
1785
|
+
RegionalAuthority["IndiaCentral"] = "centralindia";
|
|
1786
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'southindia' region. */
|
|
1787
|
+
RegionalAuthority["IndiaSouth"] = "southindia";
|
|
1788
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'westindia' region. */
|
|
1789
|
+
RegionalAuthority["IndiaWest"] = "westindia";
|
|
1790
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'koreasouth' region. */
|
|
1791
|
+
RegionalAuthority["KoreaSouth"] = "koreasouth";
|
|
1792
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'koreacentral' region. */
|
|
1793
|
+
RegionalAuthority["KoreaCentral"] = "koreacentral";
|
|
1794
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'uaecentral' region. */
|
|
1795
|
+
RegionalAuthority["UAECentral"] = "uaecentral";
|
|
1796
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'uaenorth' region. */
|
|
1797
|
+
RegionalAuthority["UAENorth"] = "uaenorth";
|
|
1798
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'southafricanorth' region. */
|
|
1799
|
+
RegionalAuthority["SouthAfricaNorth"] = "southafricanorth";
|
|
1800
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'southafricawest' region. */
|
|
1801
|
+
RegionalAuthority["SouthAfricaWest"] = "southafricawest";
|
|
1802
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'chinanorth' region. */
|
|
1803
|
+
RegionalAuthority["ChinaNorth"] = "chinanorth";
|
|
1804
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'chinaeast' region. */
|
|
1805
|
+
RegionalAuthority["ChinaEast"] = "chinaeast";
|
|
1806
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'chinanorth2' region. */
|
|
1807
|
+
RegionalAuthority["ChinaNorth2"] = "chinanorth2";
|
|
1808
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'chinaeast2' region. */
|
|
1809
|
+
RegionalAuthority["ChinaEast2"] = "chinaeast2";
|
|
1810
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'germanycentral' region. */
|
|
1811
|
+
RegionalAuthority["GermanyCentral"] = "germanycentral";
|
|
1812
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'germanynortheast' region. */
|
|
1813
|
+
RegionalAuthority["GermanyNorthEast"] = "germanynortheast";
|
|
1814
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'usgovvirginia' region. */
|
|
1815
|
+
RegionalAuthority["GovernmentUSVirginia"] = "usgovvirginia";
|
|
1816
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'usgoviowa' region. */
|
|
1817
|
+
RegionalAuthority["GovernmentUSIowa"] = "usgoviowa";
|
|
1818
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'usgovarizona' region. */
|
|
1819
|
+
RegionalAuthority["GovernmentUSArizona"] = "usgovarizona";
|
|
1820
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'usgovtexas' region. */
|
|
1821
|
+
RegionalAuthority["GovernmentUSTexas"] = "usgovtexas";
|
|
1822
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'usdodeast' region. */
|
|
1823
|
+
RegionalAuthority["GovernmentUSDodEast"] = "usdodeast";
|
|
1824
|
+
/** Uses the {@link RegionalAuthority} for the Azure 'usdodcentral' region. */
|
|
1825
|
+
RegionalAuthority["GovernmentUSDodCentral"] = "usdodcentral";
|
|
1826
|
+
})(RegionalAuthority || (RegionalAuthority = {}));
|
|
1589
1827
|
/**
|
|
1590
|
-
*
|
|
1828
|
+
* Calculates the correct regional authority based on the supplied value
|
|
1829
|
+
* and the AZURE_REGIONAL_AUTHORITY_NAME environment variable.
|
|
1830
|
+
*
|
|
1831
|
+
* Values will be returned verbatim, except for {@link RegionalAuthority.AutoDiscoverRegion}
|
|
1832
|
+
* which is mapped to a value MSAL can understand.
|
|
1833
|
+
*
|
|
1834
|
+
* @internal
|
|
1591
1835
|
*/
|
|
1592
|
-
function
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
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`);
|
|
1836
|
+
function calculateRegionalAuthority(regionalAuthority) {
|
|
1837
|
+
var _a, _b;
|
|
1838
|
+
let azureRegion = regionalAuthority;
|
|
1839
|
+
if (azureRegion === undefined &&
|
|
1840
|
+
((_b = (_a = globalThis.process) === null || _a === void 0 ? void 0 : _a.env) === null || _b === void 0 ? void 0 : _b.AZURE_REGIONAL_AUTHORITY_NAME) !== undefined) {
|
|
1841
|
+
azureRegion = process.env.AZURE_REGIONAL_AUTHORITY_NAME;
|
|
1608
1842
|
}
|
|
1609
|
-
if (
|
|
1610
|
-
|
|
1843
|
+
if (azureRegion === RegionalAuthority.AutoDiscoverRegion) {
|
|
1844
|
+
return "AUTO_DISCOVER";
|
|
1611
1845
|
}
|
|
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
|
-
};
|
|
1846
|
+
return azureRegion;
|
|
1620
1847
|
}
|
|
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
1848
|
|
|
1653
1849
|
// Copyright (c) Microsoft Corporation.
|
|
1654
1850
|
// 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
1851
|
/**
|
|
1691
|
-
*
|
|
1692
|
-
*
|
|
1852
|
+
* MSAL partial base client for Node.js.
|
|
1853
|
+
*
|
|
1854
|
+
* It completes the input configuration with some default values.
|
|
1855
|
+
* It also provides with utility protected methods that can be used from any of the clients,
|
|
1856
|
+
* which includes handlers for successful responses and errors.
|
|
1857
|
+
*
|
|
1858
|
+
* @internal
|
|
1693
1859
|
*/
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1860
|
+
class MsalNode {
|
|
1861
|
+
constructor(options) {
|
|
1862
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1863
|
+
this.app = {};
|
|
1864
|
+
this.caeApp = {};
|
|
1865
|
+
this.requiresConfidential = false;
|
|
1866
|
+
this.logger = options.logger;
|
|
1867
|
+
this.msalConfig = this.defaultNodeMsalConfig(options);
|
|
1868
|
+
this.tenantId = resolveTenantId(options.logger, options.tenantId, options.clientId);
|
|
1869
|
+
this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds((_a = options === null || options === void 0 ? void 0 : options.tokenCredentialOptions) === null || _a === void 0 ? void 0 : _a.additionallyAllowedTenants);
|
|
1870
|
+
this.clientId = this.msalConfig.auth.clientId;
|
|
1871
|
+
if (options === null || options === void 0 ? void 0 : options.getAssertion) {
|
|
1872
|
+
this.getAssertion = options.getAssertion;
|
|
1701
1873
|
}
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1874
|
+
this.enableBroker = (_b = options === null || options === void 0 ? void 0 : options.brokerOptions) === null || _b === void 0 ? void 0 : _b.enabled;
|
|
1875
|
+
this.enableMsaPassthrough = (_c = options === null || options === void 0 ? void 0 : options.brokerOptions) === null || _c === void 0 ? void 0 : _c.legacyEnableMsaPassthrough;
|
|
1876
|
+
this.parentWindowHandle = (_d = options.brokerOptions) === null || _d === void 0 ? void 0 : _d.parentWindowHandle;
|
|
1877
|
+
// If persistence has been configured
|
|
1878
|
+
if (persistenceProvider !== undefined && ((_e = options.tokenCachePersistenceOptions) === null || _e === void 0 ? void 0 : _e.enabled)) {
|
|
1879
|
+
const cacheBaseName = options.tokenCachePersistenceOptions.name || DEFAULT_TOKEN_CACHE_NAME;
|
|
1880
|
+
const nonCaeOptions = Object.assign({ name: `${cacheBaseName}.${CACHE_NON_CAE_SUFFIX}` }, options.tokenCachePersistenceOptions);
|
|
1881
|
+
const caeOptions = Object.assign({ name: `${cacheBaseName}.${CACHE_CAE_SUFFIX}` }, options.tokenCachePersistenceOptions);
|
|
1882
|
+
this.createCachePlugin = () => persistenceProvider(nonCaeOptions);
|
|
1883
|
+
this.createCachePluginCae = () => persistenceProvider(caeOptions);
|
|
1705
1884
|
}
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1885
|
+
else if ((_f = options.tokenCachePersistenceOptions) === null || _f === void 0 ? void 0 : _f.enabled) {
|
|
1886
|
+
throw new Error([
|
|
1887
|
+
"Persistent token caching was requested, but no persistence provider was configured.",
|
|
1888
|
+
"You must install the identity-cache-persistence plugin package (`npm install --save @azure/identity-cache-persistence`)",
|
|
1889
|
+
"and enable it by importing `useIdentityPlugin` from `@azure/identity` and calling",
|
|
1890
|
+
"`useIdentityPlugin(cachePersistencePlugin)` before using `tokenCachePersistenceOptions`.",
|
|
1891
|
+
].join(" "));
|
|
1712
1892
|
}
|
|
1713
|
-
|
|
1714
|
-
|
|
1893
|
+
// If broker has not been configured
|
|
1894
|
+
if (!hasNativeBroker() && this.enableBroker) {
|
|
1895
|
+
throw new Error([
|
|
1896
|
+
"Broker for WAM was requested to be enabled, but no native broker was configured.",
|
|
1897
|
+
"You must install the identity-broker plugin package (`npm install --save @azure/identity-broker`)",
|
|
1898
|
+
"and enable it by importing `useIdentityPlugin` from `@azure/identity` and calling",
|
|
1899
|
+
"`useIdentityPlugin(createNativeBrokerPlugin())` before using `enableBroker`.",
|
|
1900
|
+
].join(" "));
|
|
1715
1901
|
}
|
|
1716
|
-
|
|
1717
|
-
const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$4(scopes, clientId, resourceId)), {
|
|
1718
|
-
// Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS).
|
|
1719
|
-
allowInsecureConnection: true }));
|
|
1720
|
-
const tokenResponse = await identityClient.sendTokenRequest(request);
|
|
1721
|
-
return (tokenResponse && tokenResponse.accessToken) || null;
|
|
1722
|
-
},
|
|
1723
|
-
};
|
|
1724
|
-
|
|
1725
|
-
// Copyright (c) Microsoft Corporation.
|
|
1726
|
-
// Licensed under the MIT license.
|
|
1727
|
-
const msiName$4 = "ManagedIdentityCredential - IMDS";
|
|
1728
|
-
const logger$k = credentialLogger(msiName$4);
|
|
1729
|
-
/**
|
|
1730
|
-
* Generates the options used on the request for an access token.
|
|
1731
|
-
*/
|
|
1732
|
-
function prepareRequestOptions$3(scopes, clientId, resourceId, options) {
|
|
1733
|
-
var _a;
|
|
1734
|
-
const resource = mapScopesToResource(scopes);
|
|
1735
|
-
if (!resource) {
|
|
1736
|
-
throw new Error(`${msiName$4}: Multiple scopes are not supported.`);
|
|
1902
|
+
this.azureRegion = calculateRegionalAuthority(options.regionalAuthority);
|
|
1737
1903
|
}
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
const
|
|
1744
|
-
|
|
1745
|
-
|
|
1904
|
+
/**
|
|
1905
|
+
* Generates a MSAL configuration that generally works for Node.js
|
|
1906
|
+
*/
|
|
1907
|
+
defaultNodeMsalConfig(options) {
|
|
1908
|
+
var _a;
|
|
1909
|
+
const clientId = options.clientId || DeveloperSignOnClientId;
|
|
1910
|
+
const tenantId = resolveTenantId(options.logger, options.tenantId, options.clientId);
|
|
1911
|
+
this.authorityHost = options.authorityHost || process.env.AZURE_AUTHORITY_HOST;
|
|
1912
|
+
const authority = getAuthority(tenantId, this.authorityHost);
|
|
1913
|
+
this.identityClient = new IdentityClient(Object.assign(Object.assign({}, options.tokenCredentialOptions), { authorityHost: authority, loggingOptions: options.loggingOptions }));
|
|
1914
|
+
const clientCapabilities = [];
|
|
1915
|
+
return {
|
|
1916
|
+
auth: {
|
|
1917
|
+
clientId,
|
|
1918
|
+
authority,
|
|
1919
|
+
knownAuthorities: getKnownAuthorities(tenantId, authority, options.disableInstanceDiscovery),
|
|
1920
|
+
clientCapabilities,
|
|
1921
|
+
},
|
|
1922
|
+
// Cache is defined in this.prepare();
|
|
1923
|
+
system: {
|
|
1924
|
+
networkClient: this.identityClient,
|
|
1925
|
+
loggerOptions: {
|
|
1926
|
+
loggerCallback: defaultLoggerCallback(options.logger),
|
|
1927
|
+
logLevel: getMSALLogLevel(logger$q.getLogLevel()),
|
|
1928
|
+
piiLoggingEnabled: (_a = options.loggingOptions) === null || _a === void 0 ? void 0 : _a.enableUnsafeSupportLogging,
|
|
1929
|
+
},
|
|
1930
|
+
},
|
|
1746
1931
|
};
|
|
1747
|
-
|
|
1748
|
-
|
|
1932
|
+
}
|
|
1933
|
+
getApp(appType, enableCae) {
|
|
1934
|
+
const app = enableCae ? this.caeApp : this.app;
|
|
1935
|
+
if (appType === "publicFirst") {
|
|
1936
|
+
return (app.public || app.confidential);
|
|
1749
1937
|
}
|
|
1750
|
-
if (
|
|
1751
|
-
|
|
1938
|
+
else if (appType === "confidentialFirst") {
|
|
1939
|
+
return (app.confidential || app.public);
|
|
1940
|
+
}
|
|
1941
|
+
else if (appType === "confidential") {
|
|
1942
|
+
return app.confidential;
|
|
1943
|
+
}
|
|
1944
|
+
else {
|
|
1945
|
+
return app.public;
|
|
1752
1946
|
}
|
|
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
1947
|
}
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
//
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
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;
|
|
1948
|
+
/**
|
|
1949
|
+
* Prepares the MSAL applications.
|
|
1950
|
+
*/
|
|
1951
|
+
async init(options) {
|
|
1952
|
+
if (options === null || options === void 0 ? void 0 : options.abortSignal) {
|
|
1953
|
+
options.abortSignal.addEventListener("abort", () => {
|
|
1954
|
+
// This will abort any pending request in the IdentityClient,
|
|
1955
|
+
// based on the received or generated correlationId
|
|
1956
|
+
this.identityClient.abortRequests(options.correlationId);
|
|
1957
|
+
});
|
|
1958
|
+
}
|
|
1959
|
+
const app = (options === null || options === void 0 ? void 0 : options.enableCae) ? this.caeApp : this.app;
|
|
1960
|
+
if (options === null || options === void 0 ? void 0 : options.enableCae) {
|
|
1961
|
+
this.msalConfig.auth.clientCapabilities = ["cp1"];
|
|
1788
1962
|
}
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
return true;
|
|
1963
|
+
if (app.public || app.confidential) {
|
|
1964
|
+
return;
|
|
1792
1965
|
}
|
|
1793
|
-
if (
|
|
1794
|
-
|
|
1966
|
+
if ((options === null || options === void 0 ? void 0 : options.enableCae) && this.createCachePluginCae !== undefined) {
|
|
1967
|
+
this.msalConfig.cache = {
|
|
1968
|
+
cachePlugin: await this.createCachePluginCae(),
|
|
1969
|
+
};
|
|
1795
1970
|
}
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
// Negative values can still be used to disable the timeout.
|
|
1809
|
-
request.timeout = ((_a = options.requestOptions) === null || _a === void 0 ? void 0 : _a.timeout) || 1000;
|
|
1810
|
-
// This MSI uses the imdsEndpoint to get the token, which only uses http://
|
|
1811
|
-
request.allowInsecureConnection = true;
|
|
1812
|
-
let response;
|
|
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;
|
|
1827
|
-
}
|
|
1828
|
-
if (response.status === 403) {
|
|
1829
|
-
if ((_b = response.bodyAsText) === null || _b === void 0 ? void 0 : _b.includes("A socket operation was attempted to an unreachable network")) {
|
|
1830
|
-
logger$k.info(`${msiName$4}: The Azure IMDS endpoint is unavailable`);
|
|
1831
|
-
logger$k.info(`${msiName$4}: ${response.bodyAsText}`);
|
|
1832
|
-
return false;
|
|
1833
|
-
}
|
|
1971
|
+
if (this.createCachePlugin !== undefined) {
|
|
1972
|
+
this.msalConfig.cache = {
|
|
1973
|
+
cachePlugin: await this.createCachePlugin(),
|
|
1974
|
+
};
|
|
1975
|
+
}
|
|
1976
|
+
if (hasNativeBroker() && this.enableBroker) {
|
|
1977
|
+
this.msalConfig.broker = {
|
|
1978
|
+
nativeBrokerPlugin: nativeBrokerInfo.broker,
|
|
1979
|
+
};
|
|
1980
|
+
if (!this.parentWindowHandle) {
|
|
1981
|
+
// error should have been thrown from within the constructor of InteractiveBrowserCredential
|
|
1982
|
+
this.logger.warning("Parent window handle is not specified for the broker. This may cause unexpected behavior. Please provide the parentWindowHandle.");
|
|
1834
1983
|
}
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
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}.`);
|
|
1984
|
+
}
|
|
1985
|
+
if (options === null || options === void 0 ? void 0 : options.enableCae) {
|
|
1986
|
+
this.caeApp.public = new msalCommon__namespace.PublicClientApplication(this.msalConfig);
|
|
1844
1987
|
}
|
|
1845
1988
|
else {
|
|
1846
|
-
|
|
1989
|
+
this.app.public = new msalCommon__namespace.PublicClientApplication(this.msalConfig);
|
|
1847
1990
|
}
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1991
|
+
if (this.getAssertion) {
|
|
1992
|
+
this.msalConfig.auth.clientAssertion = await this.getAssertion();
|
|
1993
|
+
}
|
|
1994
|
+
// The confidential client requires either a secret, assertion or certificate.
|
|
1995
|
+
if (this.msalConfig.auth.clientSecret ||
|
|
1996
|
+
this.msalConfig.auth.clientAssertion ||
|
|
1997
|
+
this.msalConfig.auth.clientCertificate) {
|
|
1998
|
+
if (options === null || options === void 0 ? void 0 : options.enableCae) {
|
|
1999
|
+
this.caeApp.confidential = new msalCommon__namespace.ConfidentialClientApplication(this.msalConfig);
|
|
1854
2000
|
}
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
throw
|
|
2001
|
+
else {
|
|
2002
|
+
this.app.confidential = new msalCommon__namespace.ConfidentialClientApplication(this.msalConfig);
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
else {
|
|
2006
|
+
if (this.requiresConfidential) {
|
|
2007
|
+
throw new Error("Unable to generate the MSAL confidential client. Missing either the client's secret, certificate or assertion.");
|
|
1862
2008
|
}
|
|
1863
2009
|
}
|
|
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
2010
|
}
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
2011
|
+
/**
|
|
2012
|
+
* Allows the cancellation of a MSAL request.
|
|
2013
|
+
*/
|
|
2014
|
+
withCancellation(promise, abortSignal, onCancel) {
|
|
2015
|
+
return new Promise((resolve, reject) => {
|
|
2016
|
+
promise
|
|
2017
|
+
.then((msalToken) => {
|
|
2018
|
+
return resolve(msalToken);
|
|
2019
|
+
})
|
|
2020
|
+
.catch(reject);
|
|
2021
|
+
if (abortSignal) {
|
|
2022
|
+
abortSignal.addEventListener("abort", () => {
|
|
2023
|
+
onCancel === null || onCancel === void 0 ? void 0 : onCancel();
|
|
2024
|
+
});
|
|
2025
|
+
}
|
|
2026
|
+
});
|
|
1886
2027
|
}
|
|
1887
|
-
|
|
1888
|
-
|
|
2028
|
+
/**
|
|
2029
|
+
* Returns the existing account, attempts to load the account from MSAL.
|
|
2030
|
+
*/
|
|
2031
|
+
async getActiveAccount(enableCae = false) {
|
|
2032
|
+
if (this.account) {
|
|
2033
|
+
return this.account;
|
|
2034
|
+
}
|
|
2035
|
+
const cache = this.getApp("confidentialFirst", enableCae).getTokenCache();
|
|
2036
|
+
const accountsByTenant = await (cache === null || cache === void 0 ? void 0 : cache.getAllAccounts());
|
|
2037
|
+
if (!accountsByTenant) {
|
|
2038
|
+
return;
|
|
2039
|
+
}
|
|
2040
|
+
if (accountsByTenant.length === 1) {
|
|
2041
|
+
this.account = msalToPublic(this.clientId, accountsByTenant[0]);
|
|
2042
|
+
}
|
|
2043
|
+
else {
|
|
2044
|
+
this.logger
|
|
2045
|
+
.info(`More than one account was found authenticated for this Client ID and Tenant ID.
|
|
2046
|
+
However, no "authenticationRecord" has been provided for this credential,
|
|
2047
|
+
therefore we're unable to pick between these accounts.
|
|
2048
|
+
A new login attempt will be requested, to ensure the correct account is picked.
|
|
2049
|
+
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.`);
|
|
2050
|
+
return;
|
|
2051
|
+
}
|
|
2052
|
+
return this.account;
|
|
1889
2053
|
}
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
2054
|
+
/**
|
|
2055
|
+
* Attempts to retrieve a token from cache.
|
|
2056
|
+
*/
|
|
2057
|
+
async getTokenSilent(scopes, options) {
|
|
2058
|
+
var _a, _b, _c;
|
|
2059
|
+
await this.getActiveAccount(options === null || options === void 0 ? void 0 : options.enableCae);
|
|
2060
|
+
if (!this.account) {
|
|
2061
|
+
throw new AuthenticationRequiredError({
|
|
2062
|
+
scopes,
|
|
2063
|
+
getTokenOptions: options,
|
|
2064
|
+
message: "Silent authentication failed. We couldn't retrieve an active account from the cache.",
|
|
2065
|
+
});
|
|
2066
|
+
}
|
|
2067
|
+
const silentRequest = {
|
|
2068
|
+
// To be able to re-use the account, the Token Cache must also have been provided.
|
|
2069
|
+
account: publicToMsal(this.account),
|
|
2070
|
+
correlationId: options === null || options === void 0 ? void 0 : options.correlationId,
|
|
2071
|
+
scopes,
|
|
2072
|
+
authority: options === null || options === void 0 ? void 0 : options.authority,
|
|
2073
|
+
claims: options === null || options === void 0 ? void 0 : options.claims,
|
|
2074
|
+
};
|
|
2075
|
+
if (hasNativeBroker() && this.enableBroker) {
|
|
2076
|
+
if (!silentRequest.tokenQueryParameters) {
|
|
2077
|
+
silentRequest.tokenQueryParameters = {};
|
|
2078
|
+
}
|
|
2079
|
+
if (!this.parentWindowHandle) {
|
|
2080
|
+
// error should have been thrown from within the constructor of InteractiveBrowserCredential
|
|
2081
|
+
this.logger.warning("Parent window handle is not specified for the broker. This may cause unexpected behavior. Please provide the parentWindowHandle.");
|
|
2082
|
+
}
|
|
2083
|
+
if (this.enableMsaPassthrough) {
|
|
2084
|
+
silentRequest.tokenQueryParameters["msal_request_type"] = "consumer_passthrough";
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
try {
|
|
2088
|
+
this.logger.info("Attempting to acquire token silently");
|
|
2089
|
+
/**
|
|
2090
|
+
* The following code to retrieve all accounts is done as a workaround in an attempt to force the
|
|
2091
|
+
* refresh of the token cache with the token and the account passed in through the
|
|
2092
|
+
* `authenticationRecord` parameter. See issue - https://github.com/Azure/azure-sdk-for-js/issues/24349#issuecomment-1496715651
|
|
2093
|
+
* This workaround serves as a workaround for silent authentication not happening when authenticationRecord is passed.
|
|
2094
|
+
*/
|
|
2095
|
+
await ((_a = this.getApp("publicFirst", options === null || options === void 0 ? void 0 : options.enableCae)) === null || _a === void 0 ? void 0 : _a.getTokenCache().getAllAccounts());
|
|
2096
|
+
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));
|
|
2097
|
+
return this.handleResult(scopes, response || undefined);
|
|
2098
|
+
}
|
|
2099
|
+
catch (err) {
|
|
2100
|
+
throw handleMsalError(scopes, err, options);
|
|
2101
|
+
}
|
|
1893
2102
|
}
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
2103
|
+
/**
|
|
2104
|
+
* Wrapper around each MSAL flow get token operation: doGetToken.
|
|
2105
|
+
* If disableAutomaticAuthentication is sent through the constructor, it will prevent MSAL from requesting the user input.
|
|
2106
|
+
*/
|
|
2107
|
+
async getToken(scopes, options = {}) {
|
|
2108
|
+
const tenantId = processMultiTenantRequest(this.tenantId, options, this.additionallyAllowedTenantIds) ||
|
|
2109
|
+
this.tenantId;
|
|
2110
|
+
options.authority = getAuthority(tenantId, this.authorityHost);
|
|
2111
|
+
options.correlationId = (options === null || options === void 0 ? void 0 : options.correlationId) || randomUUID();
|
|
2112
|
+
await this.init(options);
|
|
2113
|
+
try {
|
|
2114
|
+
// MSAL now caches tokens based on their claims,
|
|
2115
|
+
// so now one has to keep track fo claims in order to retrieve the newer tokens from acquireTokenSilent
|
|
2116
|
+
// This update happened on PR: https://github.com/AzureAD/microsoft-authentication-library-for-js/pull/4533
|
|
2117
|
+
const optionsClaims = options.claims;
|
|
2118
|
+
if (optionsClaims) {
|
|
2119
|
+
this.cachedClaims = optionsClaims;
|
|
2120
|
+
}
|
|
2121
|
+
if (this.cachedClaims && !optionsClaims) {
|
|
2122
|
+
options.claims = this.cachedClaims;
|
|
2123
|
+
}
|
|
2124
|
+
// We don't return the promise since we want to catch errors right here.
|
|
2125
|
+
return await this.getTokenSilent(scopes, options);
|
|
1913
2126
|
}
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
2127
|
+
catch (err) {
|
|
2128
|
+
if (err.name !== "AuthenticationRequiredError") {
|
|
2129
|
+
throw err;
|
|
2130
|
+
}
|
|
2131
|
+
if (options === null || options === void 0 ? void 0 : options.disableAutomaticAuthentication) {
|
|
2132
|
+
throw new AuthenticationRequiredError({
|
|
2133
|
+
scopes,
|
|
2134
|
+
getTokenOptions: options,
|
|
2135
|
+
message: "Automatic authentication has been disabled. You may call the authentication() method.",
|
|
2136
|
+
});
|
|
2137
|
+
}
|
|
2138
|
+
this.logger.info(`Silent authentication failed, falling back to interactive method.`);
|
|
2139
|
+
return this.doGetToken(scopes, options);
|
|
1926
2140
|
}
|
|
1927
|
-
throw new AuthenticationError(response.status, `${msiName$3}: To authenticate with Azure Arc MSI, status code 401 is expected on the first request. ${message}`);
|
|
1928
|
-
}
|
|
1929
|
-
const authHeader = response.headers.get("www-authenticate") || "";
|
|
1930
|
-
try {
|
|
1931
|
-
return authHeader.split("=").slice(1)[0];
|
|
1932
2141
|
}
|
|
1933
|
-
|
|
1934
|
-
|
|
2142
|
+
/**
|
|
2143
|
+
* Handles the MSAL authentication result.
|
|
2144
|
+
* If the result has an account, we update the local account reference.
|
|
2145
|
+
* If the token received is invalid, an error will be thrown depending on what's missing.
|
|
2146
|
+
*/
|
|
2147
|
+
handleResult(scopes, result, getTokenOptions) {
|
|
2148
|
+
if (result === null || result === void 0 ? void 0 : result.account) {
|
|
2149
|
+
this.account = msalToPublic(this.clientId, result.account);
|
|
2150
|
+
}
|
|
2151
|
+
ensureValidMsalToken(scopes, result, getTokenOptions);
|
|
2152
|
+
this.logger.getToken.info(formatSuccess(scopes));
|
|
2153
|
+
return {
|
|
2154
|
+
token: result.accessToken,
|
|
2155
|
+
expiresOnTimestamp: result.expiresOn.getTime(),
|
|
2156
|
+
};
|
|
1935
2157
|
}
|
|
1936
2158
|
}
|
|
1937
|
-
/**
|
|
1938
|
-
* Defines how to determine whether the Azure Arc MSI is available, and also how to retrieve a token from the Azure Arc MSI.
|
|
1939
|
-
*/
|
|
1940
|
-
const arcMsi = {
|
|
1941
|
-
name: "arc",
|
|
1942
|
-
async isAvailable({ scopes }) {
|
|
1943
|
-
const resource = mapScopesToResource(scopes);
|
|
1944
|
-
if (!resource) {
|
|
1945
|
-
logger$j.info(`${msiName$3}: Unavailable. Multiple scopes are not supported.`);
|
|
1946
|
-
return false;
|
|
1947
|
-
}
|
|
1948
|
-
const result = Boolean(process.env.IMDS_ENDPOINT && process.env.IDENTITY_ENDPOINT);
|
|
1949
|
-
if (!result) {
|
|
1950
|
-
logger$j.info(`${msiName$3}: The environment variables needed are: IMDS_ENDPOINT and IDENTITY_ENDPOINT`);
|
|
1951
|
-
}
|
|
1952
|
-
return result;
|
|
1953
|
-
},
|
|
1954
|
-
async getToken(configuration, getTokenOptions = {}) {
|
|
1955
|
-
var _a;
|
|
1956
|
-
const { identityClient, scopes, clientId, resourceId } = configuration;
|
|
1957
|
-
if (clientId) {
|
|
1958
|
-
logger$j.warning(`${msiName$3}: user-assigned identities not supported. The argument clientId might be ignored by the service.`);
|
|
1959
|
-
}
|
|
1960
|
-
if (resourceId) {
|
|
1961
|
-
logger$j.warning(`${msiName$3}: user defined managed Identity by resource Id is not supported. Argument resourceId will be ignored.`);
|
|
1962
|
-
}
|
|
1963
|
-
logger$j.info(`${msiName$3}: Authenticating.`);
|
|
1964
|
-
const requestOptions = Object.assign(Object.assign({ disableJsonStringifyOnBody: true, deserializationMapper: undefined, abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$2(scopes, clientId, resourceId)), { allowInsecureConnection: true });
|
|
1965
|
-
const filePath = await filePathRequest(identityClient, requestOptions);
|
|
1966
|
-
if (!filePath) {
|
|
1967
|
-
throw new Error(`${msiName$3}: Failed to find the token file.`);
|
|
1968
|
-
}
|
|
1969
|
-
const key = await readFileAsync$1(filePath, { encoding: "utf-8" });
|
|
1970
|
-
(_a = requestOptions.headers) === null || _a === void 0 ? void 0 : _a.set("Authorization", `Basic ${key}`);
|
|
1971
|
-
const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({}, requestOptions), {
|
|
1972
|
-
// Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS).
|
|
1973
|
-
allowInsecureConnection: true }));
|
|
1974
|
-
const tokenResponse = await identityClient.sendTokenRequest(request);
|
|
1975
|
-
return (tokenResponse && tokenResponse.accessToken) || null;
|
|
1976
|
-
},
|
|
1977
|
-
};
|
|
1978
2159
|
|
|
1979
2160
|
// Copyright (c) Microsoft Corporation.
|
|
1980
2161
|
// Licensed under the MIT license.
|
|
@@ -2018,7 +2199,7 @@ class MsalClientAssertion extends MsalNode {
|
|
|
2018
2199
|
|
|
2019
2200
|
// Copyright (c) Microsoft Corporation.
|
|
2020
2201
|
// Licensed under the MIT license.
|
|
2021
|
-
const logger$
|
|
2202
|
+
const logger$g = credentialLogger("ClientAssertionCredential");
|
|
2022
2203
|
/**
|
|
2023
2204
|
* Authenticates a service principal with a JWT assertion.
|
|
2024
2205
|
*/
|
|
@@ -2041,7 +2222,7 @@ class ClientAssertionCredential {
|
|
|
2041
2222
|
this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants);
|
|
2042
2223
|
this.clientId = clientId;
|
|
2043
2224
|
this.options = options;
|
|
2044
|
-
this.msalFlow = new MsalClientAssertion(Object.assign(Object.assign({}, options), { logger: logger$
|
|
2225
|
+
this.msalFlow = new MsalClientAssertion(Object.assign(Object.assign({}, options), { logger: logger$g, clientId: this.clientId, tenantId: this.tenantId, tokenCredentialOptions: this.options, getAssertion }));
|
|
2045
2226
|
}
|
|
2046
2227
|
/**
|
|
2047
2228
|
* Authenticates with Microsoft Entra ID and returns an access token if successful.
|
|
@@ -2053,7 +2234,7 @@ class ClientAssertionCredential {
|
|
|
2053
2234
|
*/
|
|
2054
2235
|
async getToken(scopes, options = {}) {
|
|
2055
2236
|
return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async (newOptions) => {
|
|
2056
|
-
newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger$
|
|
2237
|
+
newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger$g);
|
|
2057
2238
|
const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];
|
|
2058
2239
|
return this.msalFlow.getToken(arrayScopes, newOptions);
|
|
2059
2240
|
});
|
|
@@ -2075,7 +2256,7 @@ const SupportedWorkloadEnvironmentVariables = [
|
|
|
2075
2256
|
"AZURE_CLIENT_ID",
|
|
2076
2257
|
"AZURE_FEDERATED_TOKEN_FILE",
|
|
2077
2258
|
];
|
|
2078
|
-
const logger$
|
|
2259
|
+
const logger$f = credentialLogger(credentialName$3);
|
|
2079
2260
|
/**
|
|
2080
2261
|
* Workload Identity authentication is a feature in Azure that allows applications running on virtual machines (VMs)
|
|
2081
2262
|
* to access other Azure resources without the need for a service principal or managed identity. With Workload Identity
|
|
@@ -2101,17 +2282,17 @@ class WorkloadIdentityCredential {
|
|
|
2101
2282
|
this.cacheDate = undefined;
|
|
2102
2283
|
// Logging environment variables for error details
|
|
2103
2284
|
const assignedEnv = processEnvVars(SupportedWorkloadEnvironmentVariables).assigned.join(", ");
|
|
2104
|
-
logger$
|
|
2285
|
+
logger$f.info(`Found the following environment variables: ${assignedEnv}`);
|
|
2105
2286
|
const workloadIdentityCredentialOptions = options !== null && options !== void 0 ? options : {};
|
|
2106
2287
|
const tenantId = workloadIdentityCredentialOptions.tenantId || process.env.AZURE_TENANT_ID;
|
|
2107
2288
|
const clientId = workloadIdentityCredentialOptions.clientId || process.env.AZURE_CLIENT_ID;
|
|
2108
2289
|
this.federatedTokenFilePath =
|
|
2109
2290
|
workloadIdentityCredentialOptions.tokenFilePath || process.env.AZURE_FEDERATED_TOKEN_FILE;
|
|
2110
2291
|
if (tenantId) {
|
|
2111
|
-
checkTenantId(logger$
|
|
2292
|
+
checkTenantId(logger$f, tenantId);
|
|
2112
2293
|
}
|
|
2113
2294
|
if (clientId && tenantId && this.federatedTokenFilePath) {
|
|
2114
|
-
logger$
|
|
2295
|
+
logger$f.info(`Invoking ClientAssertionCredential with tenant ID: ${tenantId}, clientId: ${workloadIdentityCredentialOptions.clientId} and federated token path: [REDACTED]`);
|
|
2115
2296
|
this.client = new ClientAssertionCredential(tenantId, clientId, this.readFileContents.bind(this), options);
|
|
2116
2297
|
}
|
|
2117
2298
|
}
|
|
@@ -2130,10 +2311,10 @@ class WorkloadIdentityCredential {
|
|
|
2130
2311
|
"AZURE_TENANT_ID",
|
|
2131
2312
|
"AZURE_CLIENT_ID",
|
|
2132
2313
|
"AZURE_FEDERATED_TOKEN_FILE". See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot `;
|
|
2133
|
-
logger$
|
|
2314
|
+
logger$f.info(errorMessage);
|
|
2134
2315
|
throw new CredentialUnavailableError(errorMessage);
|
|
2135
2316
|
}
|
|
2136
|
-
logger$
|
|
2317
|
+
logger$f.info("Invoking getToken() of Client Assertion Credential");
|
|
2137
2318
|
return this.client.getToken(scopes, options);
|
|
2138
2319
|
}
|
|
2139
2320
|
async readFileContents() {
|
|
@@ -2161,8 +2342,8 @@ class WorkloadIdentityCredential {
|
|
|
2161
2342
|
|
|
2162
2343
|
// Copyright (c) Microsoft Corporation.
|
|
2163
2344
|
// Licensed under the MIT license.
|
|
2164
|
-
const msiName
|
|
2165
|
-
const logger$
|
|
2345
|
+
const msiName = "ManagedIdentityCredential - Token Exchange";
|
|
2346
|
+
const logger$e = credentialLogger(msiName);
|
|
2166
2347
|
/**
|
|
2167
2348
|
* Defines how to determine whether the token exchange MSI is available, and also how to retrieve a token from the token exchange MSI.
|
|
2168
2349
|
*/
|
|
@@ -2175,7 +2356,7 @@ function tokenExchangeMsi() {
|
|
|
2175
2356
|
env.AZURE_TENANT_ID &&
|
|
2176
2357
|
process.env.AZURE_FEDERATED_TOKEN_FILE);
|
|
2177
2358
|
if (!result) {
|
|
2178
|
-
logger$
|
|
2359
|
+
logger$e.info(`${msiName}: Unavailable. The environment variables needed are: AZURE_CLIENT_ID (or the client ID sent through the parameters), AZURE_TENANT_ID and AZURE_FEDERATED_TOKEN_FILE`);
|
|
2179
2360
|
}
|
|
2180
2361
|
return result;
|
|
2181
2362
|
},
|
|
@@ -2189,164 +2370,6 @@ function tokenExchangeMsi() {
|
|
|
2189
2370
|
};
|
|
2190
2371
|
}
|
|
2191
2372
|
|
|
2192
|
-
// Copyright (c) Microsoft Corporation.
|
|
2193
|
-
// Licensed under the MIT license.
|
|
2194
|
-
// This MSI can be easily tested by deploying a container to Azure Service Fabric with the Dockerfile:
|
|
2195
|
-
//
|
|
2196
|
-
// FROM node:12
|
|
2197
|
-
// RUN wget https://host.any/path/bash.sh
|
|
2198
|
-
// CMD ["bash", "bash.sh"]
|
|
2199
|
-
//
|
|
2200
|
-
// Where the bash script contains:
|
|
2201
|
-
//
|
|
2202
|
-
// curl --insecure $IDENTITY_ENDPOINT'?api-version=2019-07-01-preview&resource=https://vault.azure.net/' -H "Secret: $IDENTITY_HEADER"
|
|
2203
|
-
//
|
|
2204
|
-
const msiName$1 = "ManagedIdentityCredential - Fabric MSI";
|
|
2205
|
-
const logger$f = credentialLogger(msiName$1);
|
|
2206
|
-
/**
|
|
2207
|
-
* Generates the options used on the request for an access token.
|
|
2208
|
-
*/
|
|
2209
|
-
function prepareRequestOptions$1(scopes, clientId, resourceId) {
|
|
2210
|
-
const resource = mapScopesToResource(scopes);
|
|
2211
|
-
if (!resource) {
|
|
2212
|
-
throw new Error(`${msiName$1}: Multiple scopes are not supported.`);
|
|
2213
|
-
}
|
|
2214
|
-
const queryParameters = {
|
|
2215
|
-
resource,
|
|
2216
|
-
"api-version": azureFabricVersion,
|
|
2217
|
-
};
|
|
2218
|
-
if (clientId) {
|
|
2219
|
-
queryParameters.client_id = clientId;
|
|
2220
|
-
}
|
|
2221
|
-
if (resourceId) {
|
|
2222
|
-
queryParameters.msi_res_id = resourceId;
|
|
2223
|
-
}
|
|
2224
|
-
const query = new URLSearchParams(queryParameters);
|
|
2225
|
-
// This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
|
|
2226
|
-
if (!process.env.IDENTITY_ENDPOINT) {
|
|
2227
|
-
throw new Error("Missing environment variable: IDENTITY_ENDPOINT");
|
|
2228
|
-
}
|
|
2229
|
-
if (!process.env.IDENTITY_HEADER) {
|
|
2230
|
-
throw new Error("Missing environment variable: IDENTITY_HEADER");
|
|
2231
|
-
}
|
|
2232
|
-
return {
|
|
2233
|
-
url: `${process.env.IDENTITY_ENDPOINT}?${query.toString()}`,
|
|
2234
|
-
method: "GET",
|
|
2235
|
-
headers: coreRestPipeline.createHttpHeaders({
|
|
2236
|
-
Accept: "application/json",
|
|
2237
|
-
secret: process.env.IDENTITY_HEADER,
|
|
2238
|
-
}),
|
|
2239
|
-
};
|
|
2240
|
-
}
|
|
2241
|
-
/**
|
|
2242
|
-
* Defines how to determine whether the Azure Service Fabric MSI is available, and also how to retrieve a token from the Azure Service Fabric MSI.
|
|
2243
|
-
*/
|
|
2244
|
-
const fabricMsi = {
|
|
2245
|
-
name: "fabricMsi",
|
|
2246
|
-
async isAvailable({ scopes }) {
|
|
2247
|
-
const resource = mapScopesToResource(scopes);
|
|
2248
|
-
if (!resource) {
|
|
2249
|
-
logger$f.info(`${msiName$1}: Unavailable. Multiple scopes are not supported.`);
|
|
2250
|
-
return false;
|
|
2251
|
-
}
|
|
2252
|
-
const env = process.env;
|
|
2253
|
-
const result = Boolean(env.IDENTITY_ENDPOINT && env.IDENTITY_HEADER && env.IDENTITY_SERVER_THUMBPRINT);
|
|
2254
|
-
if (!result) {
|
|
2255
|
-
logger$f.info(`${msiName$1}: Unavailable. The environment variables needed are: IDENTITY_ENDPOINT, IDENTITY_HEADER and IDENTITY_SERVER_THUMBPRINT`);
|
|
2256
|
-
}
|
|
2257
|
-
return result;
|
|
2258
|
-
},
|
|
2259
|
-
async getToken(configuration, getTokenOptions = {}) {
|
|
2260
|
-
const { scopes, identityClient, clientId, resourceId } = configuration;
|
|
2261
|
-
if (resourceId) {
|
|
2262
|
-
logger$f.warning(`${msiName$1}: user defined managed Identity by resource Id is not supported. Argument resourceId might be ignored by the service.`);
|
|
2263
|
-
}
|
|
2264
|
-
logger$f.info([
|
|
2265
|
-
`${msiName$1}:`,
|
|
2266
|
-
"Using the endpoint and the secret coming from the environment variables:",
|
|
2267
|
-
`IDENTITY_ENDPOINT=${process.env.IDENTITY_ENDPOINT},`,
|
|
2268
|
-
"IDENTITY_HEADER=[REDACTED] and",
|
|
2269
|
-
"IDENTITY_SERVER_THUMBPRINT=[REDACTED].",
|
|
2270
|
-
].join(" "));
|
|
2271
|
-
const request = coreRestPipeline.createPipelineRequest(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$1(scopes, clientId, resourceId)));
|
|
2272
|
-
request.agent = new https.Agent({
|
|
2273
|
-
// This is necessary because Service Fabric provides a self-signed certificate.
|
|
2274
|
-
// The alternative path is to verify the certificate using the IDENTITY_SERVER_THUMBPRINT env variable.
|
|
2275
|
-
rejectUnauthorized: false,
|
|
2276
|
-
});
|
|
2277
|
-
const tokenResponse = await identityClient.sendTokenRequest(request);
|
|
2278
|
-
return (tokenResponse && tokenResponse.accessToken) || null;
|
|
2279
|
-
},
|
|
2280
|
-
};
|
|
2281
|
-
|
|
2282
|
-
// Copyright (c) Microsoft Corporation.
|
|
2283
|
-
// Licensed under the MIT license.
|
|
2284
|
-
const msiName = "ManagedIdentityCredential - AppServiceMSI 2019";
|
|
2285
|
-
const logger$e = credentialLogger(msiName);
|
|
2286
|
-
/**
|
|
2287
|
-
* Generates the options used on the request for an access token.
|
|
2288
|
-
*/
|
|
2289
|
-
function prepareRequestOptions(scopes, clientId, resourceId) {
|
|
2290
|
-
const resource = mapScopesToResource(scopes);
|
|
2291
|
-
if (!resource) {
|
|
2292
|
-
throw new Error(`${msiName}: Multiple scopes are not supported.`);
|
|
2293
|
-
}
|
|
2294
|
-
const queryParameters = {
|
|
2295
|
-
resource,
|
|
2296
|
-
"api-version": "2019-08-01",
|
|
2297
|
-
};
|
|
2298
|
-
if (clientId) {
|
|
2299
|
-
queryParameters.client_id = clientId;
|
|
2300
|
-
}
|
|
2301
|
-
if (resourceId) {
|
|
2302
|
-
queryParameters.mi_res_id = resourceId;
|
|
2303
|
-
}
|
|
2304
|
-
const query = new URLSearchParams(queryParameters);
|
|
2305
|
-
// This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
|
|
2306
|
-
if (!process.env.IDENTITY_ENDPOINT) {
|
|
2307
|
-
throw new Error(`${msiName}: Missing environment variable: IDENTITY_ENDPOINT`);
|
|
2308
|
-
}
|
|
2309
|
-
if (!process.env.IDENTITY_HEADER) {
|
|
2310
|
-
throw new Error(`${msiName}: Missing environment variable: IDENTITY_HEADER`);
|
|
2311
|
-
}
|
|
2312
|
-
return {
|
|
2313
|
-
url: `${process.env.IDENTITY_ENDPOINT}?${query.toString()}`,
|
|
2314
|
-
method: "GET",
|
|
2315
|
-
headers: coreRestPipeline.createHttpHeaders({
|
|
2316
|
-
Accept: "application/json",
|
|
2317
|
-
"X-IDENTITY-HEADER": process.env.IDENTITY_HEADER,
|
|
2318
|
-
}),
|
|
2319
|
-
};
|
|
2320
|
-
}
|
|
2321
|
-
/**
|
|
2322
|
-
* 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.
|
|
2323
|
-
*/
|
|
2324
|
-
const appServiceMsi2019 = {
|
|
2325
|
-
name: "appServiceMsi2019",
|
|
2326
|
-
async isAvailable({ scopes }) {
|
|
2327
|
-
const resource = mapScopesToResource(scopes);
|
|
2328
|
-
if (!resource) {
|
|
2329
|
-
logger$e.info(`${msiName}: Unavailable. Multiple scopes are not supported.`);
|
|
2330
|
-
return false;
|
|
2331
|
-
}
|
|
2332
|
-
const env = process.env;
|
|
2333
|
-
const result = Boolean(env.IDENTITY_ENDPOINT && env.IDENTITY_HEADER);
|
|
2334
|
-
if (!result) {
|
|
2335
|
-
logger$e.info(`${msiName}: Unavailable. The environment variables needed are: IDENTITY_ENDPOINT and IDENTITY_HEADER.`);
|
|
2336
|
-
}
|
|
2337
|
-
return result;
|
|
2338
|
-
},
|
|
2339
|
-
async getToken(configuration, getTokenOptions = {}) {
|
|
2340
|
-
const { identityClient, scopes, clientId, resourceId } = configuration;
|
|
2341
|
-
logger$e.info(`${msiName}: Using the endpoint and the secret coming form the environment variables: IDENTITY_ENDPOINT=${process.env.IDENTITY_ENDPOINT} and IDENTITY_HEADER=[REDACTED].`);
|
|
2342
|
-
const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions(scopes, clientId, resourceId)), {
|
|
2343
|
-
// Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS).
|
|
2344
|
-
allowInsecureConnection: true }));
|
|
2345
|
-
const tokenResponse = await identityClient.sendTokenRequest(request);
|
|
2346
|
-
return (tokenResponse && tokenResponse.accessToken) || null;
|
|
2347
|
-
},
|
|
2348
|
-
};
|
|
2349
|
-
|
|
2350
2373
|
// Copyright (c) Microsoft Corporation.
|
|
2351
2374
|
// Licensed under the MIT license.
|
|
2352
2375
|
const logger$d = credentialLogger("ManagedIdentityCredential");
|
|
@@ -2364,9 +2387,14 @@ class ManagedIdentityCredential {
|
|
|
2364
2387
|
* @hidden
|
|
2365
2388
|
*/
|
|
2366
2389
|
constructor(clientIdOrOptions, options) {
|
|
2367
|
-
var _a;
|
|
2390
|
+
var _a, _b;
|
|
2368
2391
|
this.isEndpointUnavailable = null;
|
|
2369
2392
|
this.isAppTokenProviderInitialized = false;
|
|
2393
|
+
this.msiRetryConfig = {
|
|
2394
|
+
maxRetries: 5,
|
|
2395
|
+
startDelayInMs: 800,
|
|
2396
|
+
intervalIncrement: 2,
|
|
2397
|
+
};
|
|
2370
2398
|
let _options;
|
|
2371
2399
|
if (typeof clientIdOrOptions === "string") {
|
|
2372
2400
|
this.clientId = clientIdOrOptions;
|
|
@@ -2381,6 +2409,9 @@ class ManagedIdentityCredential {
|
|
|
2381
2409
|
if (this.clientId && this.resourceId) {
|
|
2382
2410
|
throw new Error(`${ManagedIdentityCredential.name} - Client Id and Resource Id can't be provided at the same time.`);
|
|
2383
2411
|
}
|
|
2412
|
+
if (((_a = _options === null || _options === void 0 ? void 0 : _options.retryOptions) === null || _a === void 0 ? void 0 : _a.maxRetries) !== undefined) {
|
|
2413
|
+
this.msiRetryConfig.maxRetries = _options.retryOptions.maxRetries;
|
|
2414
|
+
}
|
|
2384
2415
|
this.identityClient = new IdentityClient(_options);
|
|
2385
2416
|
this.isAvailableIdentityClient = new IdentityClient(Object.assign(Object.assign({}, _options), { retryOptions: {
|
|
2386
2417
|
maxRetries: 0,
|
|
@@ -2391,7 +2422,7 @@ class ManagedIdentityCredential {
|
|
|
2391
2422
|
this.confidentialApp = new msalCommon.ConfidentialClientApplication({
|
|
2392
2423
|
auth: {
|
|
2393
2424
|
authority: "https://login.microsoftonline.com/managed_identity",
|
|
2394
|
-
clientId: (
|
|
2425
|
+
clientId: (_b = this.clientId) !== null && _b !== void 0 ? _b : DeveloperSignOnClientId,
|
|
2395
2426
|
clientSecret: "dummy-secret",
|
|
2396
2427
|
cloudDiscoveryMetadata: '{"tenant_discovery_endpoint":"https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration","api-version":"1.1","metadata":[{"preferred_network":"login.microsoftonline.com","preferred_cache":"login.windows.net","aliases":["login.microsoftonline.com","login.windows.net","login.microsoft.com","sts.windows.net"]},{"preferred_network":"login.partner.microsoftonline.cn","preferred_cache":"login.partner.microsoftonline.cn","aliases":["login.partner.microsoftonline.cn","login.chinacloudapi.cn"]},{"preferred_network":"login.microsoftonline.de","preferred_cache":"login.microsoftonline.de","aliases":["login.microsoftonline.de"]},{"preferred_network":"login.microsoftonline.us","preferred_cache":"login.microsoftonline.us","aliases":["login.microsoftonline.us","login.usgovcloudapi.net"]},{"preferred_network":"login-us.microsoftonline.com","preferred_cache":"login-us.microsoftonline.com","aliases":["login-us.microsoftonline.com"]}]}',
|
|
2397
2428
|
authorityMetadata: '{"token_endpoint":"https://login.microsoftonline.com/common/oauth2/v2.0/token","token_endpoint_auth_methods_supported":["client_secret_post","private_key_jwt","client_secret_basic"],"jwks_uri":"https://login.microsoftonline.com/common/discovery/v2.0/keys","response_modes_supported":["query","fragment","form_post"],"subject_types_supported":["pairwise"],"id_token_signing_alg_values_supported":["RS256"],"response_types_supported":["code","id_token","code id_token","id_token token"],"scopes_supported":["openid","profile","email","offline_access"],"issuer":"https://login.microsoftonline.com/{tenantid}/v2.0","request_uri_parameter_supported":false,"userinfo_endpoint":"https://graph.microsoft.com/oidc/userinfo","authorization_endpoint":"https://login.microsoftonline.com/common/oauth2/v2.0/authorize","device_authorization_endpoint":"https://login.microsoftonline.com/common/oauth2/v2.0/devicecode","http_logout_supported":true,"frontchannel_logout_supported":true,"end_session_endpoint":"https://login.microsoftonline.com/common/oauth2/v2.0/logout","claims_supported":["sub","iss","cloud_instance_name","cloud_instance_host_name","cloud_graph_host_name","msgraph_host","aud","exp","iat","auth_time","acr","nonce","preferred_username","name","tid","ver","at_hash","c_hash","email"],"kerberos_endpoint":"https://login.microsoftonline.com/common/kerberos","tenant_region_scope":null,"cloud_instance_name":"microsoftonline.com","cloud_graph_host_name":"graph.windows.net","msgraph_host":"graph.microsoft.com","rbac_url":"https://pas.windows.net"}',
|
|
@@ -2441,6 +2472,7 @@ class ManagedIdentityCredential {
|
|
|
2441
2472
|
scopes,
|
|
2442
2473
|
clientId: this.clientId,
|
|
2443
2474
|
resourceId: this.resourceId,
|
|
2475
|
+
retryConfig: this.msiRetryConfig,
|
|
2444
2476
|
}, updatedOptions);
|
|
2445
2477
|
}
|
|
2446
2478
|
catch (err) {
|
|
@@ -2547,10 +2579,10 @@ class ManagedIdentityCredential {
|
|
|
2547
2579
|
if (err.statusCode === 400) {
|
|
2548
2580
|
throw new CredentialUnavailableError(`${ManagedIdentityCredential.name}: The managed identity endpoint is indicating there's no available identity. Message: ${err.message}`);
|
|
2549
2581
|
}
|
|
2550
|
-
// 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"
|
|
2582
|
+
// 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" or "A socket operation was attempted to an unreachable host"
|
|
2551
2583
|
// rather than just timing out, as expected.
|
|
2552
2584
|
if (err.statusCode === 403 || err.code === 403) {
|
|
2553
|
-
if (err.message.includes("
|
|
2585
|
+
if (err.message.includes("unreachable")) {
|
|
2554
2586
|
const error = new CredentialUnavailableError(`${ManagedIdentityCredential.name}: Unavailable. Network unreachable. Message: ${err.message}`);
|
|
2555
2587
|
logger$d.getToken.info(formatError(scopes, error));
|
|
2556
2588
|
throw error;
|
|
@@ -2587,7 +2619,6 @@ class ManagedIdentityCredential {
|
|
|
2587
2619
|
}
|
|
2588
2620
|
/**
|
|
2589
2621
|
* Ensures the validity of the MSAL token
|
|
2590
|
-
* @internal
|
|
2591
2622
|
*/
|
|
2592
2623
|
ensureValidMsalToken(scopes, msalToken, getTokenOptions) {
|
|
2593
2624
|
const error = (message) => {
|
|
@@ -2891,7 +2922,7 @@ const logger$b = credentialLogger("AzureDeveloperCliCredential");
|
|
|
2891
2922
|
* Azure Developer CLI is a command-line interface tool that allows developers to create, manage, and deploy
|
|
2892
2923
|
* resources in Azure. It's built on top of the Azure CLI and provides additional functionality specific
|
|
2893
2924
|
* to Azure developers. It allows users to authenticate as a user and/or a service principal against
|
|
2894
|
-
* <a href="https://learn.microsoft.com/
|
|
2925
|
+
* <a href="https://learn.microsoft.com/entra/fundamentals/">Microsoft Entra ID</a>. The
|
|
2895
2926
|
* AzureDeveloperCliCredential authenticates in a development environment and acquires a token on behalf of
|
|
2896
2927
|
* the logged-in user or service principal in the Azure Developer CLI. It acts as the Azure Developer CLI logged in user or
|
|
2897
2928
|
* service principal and executes an Azure CLI command underneath to authenticate the application against
|
|
@@ -3485,7 +3516,7 @@ const logger$7 = credentialLogger("ClientSecretCredential");
|
|
|
3485
3516
|
* that was generated for an App Registration. More information on how
|
|
3486
3517
|
* to configure a client secret can be found here:
|
|
3487
3518
|
*
|
|
3488
|
-
* https://learn.microsoft.com/
|
|
3519
|
+
* https://learn.microsoft.com/entra/identity-platform/quickstart-configure-app-access-web-apis#add-credentials-to-your-web-application
|
|
3489
3520
|
*
|
|
3490
3521
|
*/
|
|
3491
3522
|
class ClientSecretCredential {
|
|
@@ -3734,13 +3765,17 @@ const logger$4 = credentialLogger("DefaultAzureCredential");
|
|
|
3734
3765
|
*
|
|
3735
3766
|
* @internal
|
|
3736
3767
|
*/
|
|
3737
|
-
function createDefaultManagedIdentityCredential(options) {
|
|
3738
|
-
var _a, _b, _c;
|
|
3739
|
-
|
|
3740
|
-
|
|
3768
|
+
function createDefaultManagedIdentityCredential(options = {}) {
|
|
3769
|
+
var _a, _b, _c, _d;
|
|
3770
|
+
(_a = options.retryOptions) !== null && _a !== void 0 ? _a : (options.retryOptions = {
|
|
3771
|
+
maxRetries: 5,
|
|
3772
|
+
retryDelayInMs: 800,
|
|
3773
|
+
});
|
|
3774
|
+
const managedIdentityClientId = (_b = options === null || options === void 0 ? void 0 : options.managedIdentityClientId) !== null && _b !== void 0 ? _b : process.env.AZURE_CLIENT_ID;
|
|
3775
|
+
const workloadIdentityClientId = (_c = options === null || options === void 0 ? void 0 : options.workloadIdentityClientId) !== null && _c !== void 0 ? _c : managedIdentityClientId;
|
|
3741
3776
|
const managedResourceId = options === null || options === void 0 ? void 0 : options.managedIdentityResourceId;
|
|
3742
3777
|
const workloadFile = process.env.AZURE_FEDERATED_TOKEN_FILE;
|
|
3743
|
-
const tenantId = (
|
|
3778
|
+
const tenantId = (_d = options === null || options === void 0 ? void 0 : options.tenantId) !== null && _d !== void 0 ? _d : process.env.AZURE_TENANT_ID;
|
|
3744
3779
|
if (managedResourceId) {
|
|
3745
3780
|
const managedIdentityResourceIdOptions = Object.assign(Object.assign({}, options), { resourceId: managedResourceId });
|
|
3746
3781
|
return new ManagedIdentityCredential(managedIdentityResourceIdOptions);
|
|
@@ -3880,15 +3915,16 @@ const interactiveBrowserMockable = {
|
|
|
3880
3915
|
*/
|
|
3881
3916
|
class MsalOpenBrowser extends MsalNode {
|
|
3882
3917
|
constructor(options) {
|
|
3883
|
-
var _a, _b;
|
|
3918
|
+
var _a, _b, _c, _d;
|
|
3884
3919
|
super(options);
|
|
3885
3920
|
this.loginHint = options.loginHint;
|
|
3886
3921
|
this.errorTemplate = (_a = options.browserCustomizationOptions) === null || _a === void 0 ? void 0 : _a.errorMessage;
|
|
3887
3922
|
this.successTemplate = (_b = options.browserCustomizationOptions) === null || _b === void 0 ? void 0 : _b.successMessage;
|
|
3888
3923
|
this.logger = credentialLogger("Node.js MSAL Open Browser");
|
|
3924
|
+
this.useDefaultBrokerAccount =
|
|
3925
|
+
((_c = options.brokerOptions) === null || _c === void 0 ? void 0 : _c.enabled) && ((_d = options.brokerOptions) === null || _d === void 0 ? void 0 : _d.useDefaultBrokerAccount);
|
|
3889
3926
|
}
|
|
3890
|
-
async doGetToken(scopes, options) {
|
|
3891
|
-
var _a;
|
|
3927
|
+
async doGetToken(scopes, options = {}) {
|
|
3892
3928
|
try {
|
|
3893
3929
|
const interactiveRequest = {
|
|
3894
3930
|
openBrowser: async (url) => {
|
|
@@ -3903,30 +3939,70 @@ class MsalOpenBrowser extends MsalNode {
|
|
|
3903
3939
|
successTemplate: this.successTemplate,
|
|
3904
3940
|
};
|
|
3905
3941
|
if (hasNativeBroker() && this.enableBroker) {
|
|
3906
|
-
this.
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
}
|
|
3910
|
-
else {
|
|
3911
|
-
// error should have been thrown from within the constructor of InteractiveBrowserCredential
|
|
3912
|
-
this.logger.warning("Parent window handle is not specified for the broker. This may cause unexpected behavior. Please provide the parentWindowHandle.");
|
|
3913
|
-
}
|
|
3914
|
-
if (this.enableMsaPassthrough) {
|
|
3915
|
-
((_a = interactiveRequest.tokenQueryParameters) !== null && _a !== void 0 ? _a : (interactiveRequest.tokenQueryParameters = {}))["msal_request_type"] =
|
|
3916
|
-
"consumer_passthrough";
|
|
3917
|
-
}
|
|
3942
|
+
return this.doGetBrokeredToken(scopes, interactiveRequest, {
|
|
3943
|
+
enableCae: options.enableCae,
|
|
3944
|
+
useDefaultBrokerAccount: this.useDefaultBrokerAccount,
|
|
3945
|
+
});
|
|
3918
3946
|
}
|
|
3947
|
+
// If the broker is not enabled, we will fall back to interactive authentication
|
|
3919
3948
|
if (hasNativeBroker() && !this.enableBroker) {
|
|
3920
3949
|
this.logger.verbose("Authentication will resume normally without the broker, since it's not enabled");
|
|
3921
3950
|
}
|
|
3951
|
+
const result = await this.getApp("public", options === null || options === void 0 ? void 0 : options.enableCae).acquireTokenInteractive(interactiveRequest);
|
|
3952
|
+
return this.handleResult(scopes, result || undefined);
|
|
3953
|
+
}
|
|
3954
|
+
catch (err) {
|
|
3955
|
+
throw handleMsalError(scopes, err, options);
|
|
3956
|
+
}
|
|
3957
|
+
}
|
|
3958
|
+
/**
|
|
3959
|
+
* A helper function that supports brokered authentication through the MSAL's public application.
|
|
3960
|
+
*
|
|
3961
|
+
* When options.useDefaultBrokerAccount is true, the method will attempt to authenticate using the default broker account.
|
|
3962
|
+
* If the default broker account is not available, the method will fall back to interactive authentication.
|
|
3963
|
+
*/
|
|
3964
|
+
async doGetBrokeredToken(scopes, interactiveRequest, options) {
|
|
3965
|
+
var _a;
|
|
3966
|
+
this.logger.verbose("Authentication will resume through the broker");
|
|
3967
|
+
if (this.parentWindowHandle) {
|
|
3968
|
+
interactiveRequest.windowHandle = Buffer.from(this.parentWindowHandle);
|
|
3969
|
+
}
|
|
3970
|
+
else {
|
|
3971
|
+
// error should have been thrown from within the constructor of InteractiveBrowserCredential
|
|
3972
|
+
this.logger.warning("Parent window handle is not specified for the broker. This may cause unexpected behavior. Please provide the parentWindowHandle.");
|
|
3973
|
+
}
|
|
3974
|
+
if (this.enableMsaPassthrough) {
|
|
3975
|
+
((_a = interactiveRequest.tokenQueryParameters) !== null && _a !== void 0 ? _a : (interactiveRequest.tokenQueryParameters = {}))["msal_request_type"] =
|
|
3976
|
+
"consumer_passthrough";
|
|
3977
|
+
}
|
|
3978
|
+
if (options.useDefaultBrokerAccount) {
|
|
3979
|
+
interactiveRequest.prompt = "none";
|
|
3980
|
+
this.logger.verbose("Attempting broker authentication using the default broker account");
|
|
3981
|
+
}
|
|
3982
|
+
else {
|
|
3983
|
+
interactiveRequest.prompt = undefined;
|
|
3984
|
+
this.logger.verbose("Attempting broker authentication without the default broker account");
|
|
3985
|
+
}
|
|
3986
|
+
try {
|
|
3922
3987
|
const result = await this.getApp("public", options === null || options === void 0 ? void 0 : options.enableCae).acquireTokenInteractive(interactiveRequest);
|
|
3923
3988
|
if (result.fromNativeBroker) {
|
|
3924
3989
|
this.logger.verbose(`This result is returned from native broker`);
|
|
3925
3990
|
}
|
|
3926
3991
|
return this.handleResult(scopes, result || undefined);
|
|
3927
3992
|
}
|
|
3928
|
-
catch (
|
|
3929
|
-
|
|
3993
|
+
catch (e) {
|
|
3994
|
+
this.logger.verbose(`Failed to authenticate through the broker: ${e.message}`);
|
|
3995
|
+
// If we tried to use the default broker account and failed, fall back to interactive authentication
|
|
3996
|
+
if (options.useDefaultBrokerAccount) {
|
|
3997
|
+
return this.doGetBrokeredToken(scopes, interactiveRequest, {
|
|
3998
|
+
enableCae: options.enableCae,
|
|
3999
|
+
useDefaultBrokerAccount: false,
|
|
4000
|
+
});
|
|
4001
|
+
}
|
|
4002
|
+
else {
|
|
4003
|
+
// If we're not using the default broker account, throw the error
|
|
4004
|
+
throw handleMsalError(scopes, e);
|
|
4005
|
+
}
|
|
3930
4006
|
}
|
|
3931
4007
|
}
|
|
3932
4008
|
}
|
|
@@ -3942,17 +4018,17 @@ class InteractiveBrowserCredential {
|
|
|
3942
4018
|
/**
|
|
3943
4019
|
* Creates an instance of InteractiveBrowserCredential with the details needed.
|
|
3944
4020
|
*
|
|
3945
|
-
* This credential uses the [Authorization Code Flow](https://learn.microsoft.com/
|
|
4021
|
+
* This credential uses the [Authorization Code Flow](https://learn.microsoft.com/entra/identity-platform/v2-oauth2-auth-code-flow).
|
|
3946
4022
|
* On Node.js, it will open a browser window while it listens for a redirect response from the authentication service.
|
|
3947
4023
|
* On browsers, it authenticates via popups. The `loginStyle` optional parameter can be set to `redirect` to authenticate by redirecting the user to an Azure secure login page, which then will redirect the user back to the web application where the authentication started.
|
|
3948
4024
|
*
|
|
3949
4025
|
* For Node.js, if a `clientId` is provided, the Microsoft Entra application will need to be configured to have a "Mobile and desktop applications" redirect endpoint.
|
|
3950
|
-
* Follow our guide on [setting up Redirect URIs for Desktop apps that calls to web APIs](https://learn.microsoft.com/
|
|
4026
|
+
* Follow our guide on [setting up Redirect URIs for Desktop apps that calls to web APIs](https://learn.microsoft.com/entra/identity-platform/scenario-desktop-app-registration#redirect-uris).
|
|
3951
4027
|
*
|
|
3952
4028
|
* @param options - Options for configuring the client which makes the authentication requests.
|
|
3953
4029
|
*/
|
|
3954
4030
|
constructor(options) {
|
|
3955
|
-
var _a, _b, _c;
|
|
4031
|
+
var _a, _b, _c, _d;
|
|
3956
4032
|
const redirectUri = typeof options.redirectUri === "function"
|
|
3957
4033
|
? options.redirectUri()
|
|
3958
4034
|
: options.redirectUri || "http://localhost";
|
|
@@ -3969,6 +4045,7 @@ class InteractiveBrowserCredential {
|
|
|
3969
4045
|
enabled: true,
|
|
3970
4046
|
parentWindowHandle: ibcNodeOptions.brokerOptions.parentWindowHandle,
|
|
3971
4047
|
legacyEnableMsaPassthrough: (_c = ibcNodeOptions.brokerOptions) === null || _c === void 0 ? void 0 : _c.legacyEnableMsaPassthrough,
|
|
4048
|
+
useDefaultBrokerAccount: (_d = ibcNodeOptions.brokerOptions) === null || _d === void 0 ? void 0 : _d.useDefaultBrokerAccount,
|
|
3972
4049
|
} }));
|
|
3973
4050
|
}
|
|
3974
4051
|
}
|
|
@@ -4183,7 +4260,7 @@ const logger$1 = credentialLogger("AuthorizationCodeCredential");
|
|
|
4183
4260
|
* that was obtained through the authorization code flow, described in more detail
|
|
4184
4261
|
* in the Microsoft Entra ID documentation:
|
|
4185
4262
|
*
|
|
4186
|
-
* https://learn.microsoft.com/
|
|
4263
|
+
* https://learn.microsoft.com/entra/identity-platform/v2-oauth2-auth-code-flow
|
|
4187
4264
|
*/
|
|
4188
4265
|
class AuthorizationCodeCredential {
|
|
4189
4266
|
/**
|
|
@@ -4290,7 +4367,7 @@ class MsalOnBehalfOf extends MsalNode {
|
|
|
4290
4367
|
const credentialName = "OnBehalfOfCredential";
|
|
4291
4368
|
const logger = credentialLogger(credentialName);
|
|
4292
4369
|
/**
|
|
4293
|
-
* Enables authentication to Microsoft Entra ID using the [On Behalf Of flow](https://learn.microsoft.com/
|
|
4370
|
+
* Enables authentication to Microsoft Entra ID using the [On Behalf Of flow](https://learn.microsoft.com/entra/identity-platform/v2-oauth2-on-behalf-of-flow).
|
|
4294
4371
|
*/
|
|
4295
4372
|
class OnBehalfOfCredential {
|
|
4296
4373
|
constructor(options) {
|