@azure/identity 4.3.0 → 4.3.1-alpha.20240619.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -14,11 +14,12 @@ var path = require('path');
14
14
  var msalCommon = require('@azure/msal-node');
15
15
  var fs$1 = require('node:fs');
16
16
  var https = require('https');
17
+ var open = require('open');
17
18
  var promises = require('fs/promises');
18
19
  var child_process = require('child_process');
19
20
  var crypto = require('crypto');
20
- var open = require('open');
21
- var util = require('util');
21
+ var promises$1 = require('node:fs/promises');
22
+ var node_crypto = require('node:crypto');
22
23
 
23
24
  function _interopNamespaceDefault(e) {
24
25
  var n = Object.create(null);
@@ -45,7 +46,7 @@ var child_process__namespace = /*#__PURE__*/_interopNamespaceDefault(child_proce
45
46
  /**
46
47
  * Current version of the `@azure/identity` package.
47
48
  */
48
- const SDK_VERSION = `4.3.0-beta.3`;
49
+ const SDK_VERSION = `4.3.1`;
49
50
  /**
50
51
  * The default client ID for authentication
51
52
  * @internal
@@ -128,9 +129,6 @@ const msalNodeFlowCacheControl = {
128
129
  * @internal
129
130
  */
130
131
  let nativeBrokerInfo = undefined;
131
- function hasNativeBroker() {
132
- return nativeBrokerInfo !== undefined;
133
- }
134
132
  /**
135
133
  * An object that allows setting the native broker provider.
136
134
  * @internal
@@ -1009,16 +1007,88 @@ function useIdentityPlugin(plugin) {
1009
1007
 
1010
1008
  // Copyright (c) Microsoft Corporation.
1011
1009
  // Licensed under the MIT license.
1012
- const msiName$6 = "ManagedIdentityCredential - AppServiceMSI 2017";
1010
+ const msiName$6 = "ManagedIdentityCredential - CloudShellMSI";
1013
1011
  const logger$o = credentialLogger(msiName$6);
1014
1012
  /**
1015
1013
  * Generates the options used on the request for an access token.
1016
1014
  */
1017
- function prepareRequestOptions$5(scopes, clientId) {
1015
+ function prepareRequestOptions$5(scopes, clientId, resourceId) {
1018
1016
  const resource = mapScopesToResource(scopes);
1019
1017
  if (!resource) {
1020
1018
  throw new Error(`${msiName$6}: Multiple scopes are not supported.`);
1021
1019
  }
1020
+ const body = {
1021
+ resource,
1022
+ };
1023
+ if (clientId) {
1024
+ body.client_id = clientId;
1025
+ }
1026
+ if (resourceId) {
1027
+ body.msi_res_id = resourceId;
1028
+ }
1029
+ // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
1030
+ if (!process.env.MSI_ENDPOINT) {
1031
+ throw new Error(`${msiName$6}: Missing environment variable: MSI_ENDPOINT`);
1032
+ }
1033
+ const params = new URLSearchParams(body);
1034
+ return {
1035
+ url: process.env.MSI_ENDPOINT,
1036
+ method: "POST",
1037
+ body: params.toString(),
1038
+ headers: coreRestPipeline.createHttpHeaders({
1039
+ Accept: "application/json",
1040
+ Metadata: "true",
1041
+ "Content-Type": "application/x-www-form-urlencoded",
1042
+ }),
1043
+ };
1044
+ }
1045
+ /**
1046
+ * 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.
1047
+ * 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.
1048
+ */
1049
+ const cloudShellMsi = {
1050
+ name: "cloudShellMsi",
1051
+ async isAvailable({ scopes }) {
1052
+ const resource = mapScopesToResource(scopes);
1053
+ if (!resource) {
1054
+ logger$o.info(`${msiName$6}: Unavailable. Multiple scopes are not supported.`);
1055
+ return false;
1056
+ }
1057
+ const result = Boolean(process.env.MSI_ENDPOINT);
1058
+ if (!result) {
1059
+ logger$o.info(`${msiName$6}: Unavailable. The environment variable MSI_ENDPOINT is needed.`);
1060
+ }
1061
+ return result;
1062
+ },
1063
+ async getToken(configuration, getTokenOptions = {}) {
1064
+ const { identityClient, scopes, clientId, resourceId } = configuration;
1065
+ if (clientId) {
1066
+ logger$o.warning(`${msiName$6}: user-assigned identities not supported. The argument clientId might be ignored by the service.`);
1067
+ }
1068
+ if (resourceId) {
1069
+ logger$o.warning(`${msiName$6}: user defined managed Identity by resource Id not supported. The argument resourceId might be ignored by the service.`);
1070
+ }
1071
+ logger$o.info(`${msiName$6}: Using the endpoint coming form the environment variable MSI_ENDPOINT = ${process.env.MSI_ENDPOINT}.`);
1072
+ const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$5(scopes, clientId, resourceId)), {
1073
+ // Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS).
1074
+ allowInsecureConnection: true }));
1075
+ const tokenResponse = await identityClient.sendTokenRequest(request);
1076
+ return (tokenResponse && tokenResponse.accessToken) || null;
1077
+ },
1078
+ };
1079
+
1080
+ // Copyright (c) Microsoft Corporation.
1081
+ // Licensed under the MIT license.
1082
+ const msiName$5 = "ManagedIdentityCredential - AppServiceMSI 2017";
1083
+ const logger$n = credentialLogger(msiName$5);
1084
+ /**
1085
+ * Generates the options used on the request for an access token.
1086
+ */
1087
+ function prepareRequestOptions$4(scopes, clientId) {
1088
+ const resource = mapScopesToResource(scopes);
1089
+ if (!resource) {
1090
+ throw new Error(`${msiName$5}: Multiple scopes are not supported.`);
1091
+ }
1022
1092
  const queryParameters = {
1023
1093
  resource,
1024
1094
  "api-version": "2017-09-01",
@@ -1029,10 +1099,10 @@ function prepareRequestOptions$5(scopes, clientId) {
1029
1099
  const query = new URLSearchParams(queryParameters);
1030
1100
  // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
1031
1101
  if (!process.env.MSI_ENDPOINT) {
1032
- throw new Error(`${msiName$6}: Missing environment variable: MSI_ENDPOINT`);
1102
+ throw new Error(`${msiName$5}: Missing environment variable: MSI_ENDPOINT`);
1033
1103
  }
1034
1104
  if (!process.env.MSI_SECRET) {
1035
- throw new Error(`${msiName$6}: Missing environment variable: MSI_SECRET`);
1105
+ throw new Error(`${msiName$5}: Missing environment variable: MSI_SECRET`);
1036
1106
  }
1037
1107
  return {
1038
1108
  url: `${process.env.MSI_ENDPOINT}?${query.toString()}`,
@@ -1051,23 +1121,23 @@ const appServiceMsi2017 = {
1051
1121
  async isAvailable({ scopes }) {
1052
1122
  const resource = mapScopesToResource(scopes);
1053
1123
  if (!resource) {
1054
- logger$o.info(`${msiName$6}: Unavailable. Multiple scopes are not supported.`);
1124
+ logger$n.info(`${msiName$5}: Unavailable. Multiple scopes are not supported.`);
1055
1125
  return false;
1056
1126
  }
1057
1127
  const env = process.env;
1058
1128
  const result = Boolean(env.MSI_ENDPOINT && env.MSI_SECRET);
1059
1129
  if (!result) {
1060
- logger$o.info(`${msiName$6}: Unavailable. The environment variables needed are: MSI_ENDPOINT and MSI_SECRET.`);
1130
+ logger$n.info(`${msiName$5}: Unavailable. The environment variables needed are: MSI_ENDPOINT and MSI_SECRET.`);
1061
1131
  }
1062
1132
  return result;
1063
1133
  },
1064
1134
  async getToken(configuration, getTokenOptions = {}) {
1065
1135
  const { identityClient, scopes, clientId, resourceId } = configuration;
1066
1136
  if (resourceId) {
1067
- logger$o.warning(`${msiName$6}: managed Identity by resource Id is not supported. Argument resourceId might be ignored by the service.`);
1137
+ logger$n.warning(`${msiName$5}: managed Identity by resource Id is not supported. Argument resourceId might be ignored by the service.`);
1068
1138
  }
1069
- logger$o.info(`${msiName$6}: Using the endpoint and the secret coming form the environment variables: MSI_ENDPOINT=${process.env.MSI_ENDPOINT} and MSI_SECRET=[REDACTED].`);
1070
- const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$5(scopes, clientId)), {
1139
+ logger$n.info(`${msiName$5}: Using the endpoint and the secret coming form the environment variables: MSI_ENDPOINT=${process.env.MSI_ENDPOINT} and MSI_SECRET=[REDACTED].`);
1140
+ const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$4(scopes, clientId)), {
1071
1141
  // Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS).
1072
1142
  allowInsecureConnection: true }));
1073
1143
  const tokenResponse = await identityClient.sendTokenRequest(request);
@@ -1077,15 +1147,15 @@ const appServiceMsi2017 = {
1077
1147
 
1078
1148
  // Copyright (c) Microsoft Corporation.
1079
1149
  // Licensed under the MIT license.
1080
- const msiName$5 = "ManagedIdentityCredential - AppServiceMSI 2019";
1081
- const logger$n = credentialLogger(msiName$5);
1150
+ const msiName$4 = "ManagedIdentityCredential - AppServiceMSI 2019";
1151
+ const logger$m = credentialLogger(msiName$4);
1082
1152
  /**
1083
1153
  * Generates the options used on the request for an access token.
1084
1154
  */
1085
- function prepareRequestOptions$4(scopes, clientId, resourceId) {
1155
+ function prepareRequestOptions$3(scopes, clientId, resourceId) {
1086
1156
  const resource = mapScopesToResource(scopes);
1087
1157
  if (!resource) {
1088
- throw new Error(`${msiName$5}: Multiple scopes are not supported.`);
1158
+ throw new Error(`${msiName$4}: Multiple scopes are not supported.`);
1089
1159
  }
1090
1160
  const queryParameters = {
1091
1161
  resource,
@@ -1100,10 +1170,10 @@ function prepareRequestOptions$4(scopes, clientId, resourceId) {
1100
1170
  const query = new URLSearchParams(queryParameters);
1101
1171
  // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
1102
1172
  if (!process.env.IDENTITY_ENDPOINT) {
1103
- throw new Error(`${msiName$5}: Missing environment variable: IDENTITY_ENDPOINT`);
1173
+ throw new Error(`${msiName$4}: Missing environment variable: IDENTITY_ENDPOINT`);
1104
1174
  }
1105
1175
  if (!process.env.IDENTITY_HEADER) {
1106
- throw new Error(`${msiName$5}: Missing environment variable: IDENTITY_HEADER`);
1176
+ throw new Error(`${msiName$4}: Missing environment variable: IDENTITY_HEADER`);
1107
1177
  }
1108
1178
  return {
1109
1179
  url: `${process.env.IDENTITY_ENDPOINT}?${query.toString()}`,
@@ -1122,20 +1192,20 @@ const appServiceMsi2019 = {
1122
1192
  async isAvailable({ scopes }) {
1123
1193
  const resource = mapScopesToResource(scopes);
1124
1194
  if (!resource) {
1125
- logger$n.info(`${msiName$5}: Unavailable. Multiple scopes are not supported.`);
1195
+ logger$m.info(`${msiName$4}: Unavailable. Multiple scopes are not supported.`);
1126
1196
  return false;
1127
1197
  }
1128
1198
  const env = process.env;
1129
1199
  const result = Boolean(env.IDENTITY_ENDPOINT && env.IDENTITY_HEADER);
1130
1200
  if (!result) {
1131
- logger$n.info(`${msiName$5}: Unavailable. The environment variables needed are: IDENTITY_ENDPOINT and IDENTITY_HEADER.`);
1201
+ logger$m.info(`${msiName$4}: Unavailable. The environment variables needed are: IDENTITY_ENDPOINT and IDENTITY_HEADER.`);
1132
1202
  }
1133
1203
  return result;
1134
1204
  },
1135
1205
  async getToken(configuration, getTokenOptions = {}) {
1136
1206
  const { identityClient, scopes, clientId, resourceId } = configuration;
1137
- logger$n.info(`${msiName$5}: Using the endpoint and the secret coming form the environment variables: IDENTITY_ENDPOINT=${process.env.IDENTITY_ENDPOINT} and IDENTITY_HEADER=[REDACTED].`);
1138
- const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$4(scopes, clientId, resourceId)), {
1207
+ logger$m.info(`${msiName$4}: Using the endpoint and the secret coming form the environment variables: IDENTITY_ENDPOINT=${process.env.IDENTITY_ENDPOINT} and IDENTITY_HEADER=[REDACTED].`);
1208
+ const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$3(scopes, clientId, resourceId)), {
1139
1209
  // Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS).
1140
1210
  allowInsecureConnection: true }));
1141
1211
  const tokenResponse = await identityClient.sendTokenRequest(request);
@@ -1145,15 +1215,15 @@ const appServiceMsi2019 = {
1145
1215
 
1146
1216
  // Copyright (c) Microsoft Corporation.
1147
1217
  // Licensed under the MIT license.
1148
- const msiName$4 = "ManagedIdentityCredential - Azure Arc MSI";
1149
- const logger$m = credentialLogger(msiName$4);
1218
+ const msiName$3 = "ManagedIdentityCredential - Azure Arc MSI";
1219
+ const logger$l = credentialLogger(msiName$3);
1150
1220
  /**
1151
1221
  * Generates the options used on the request for an access token.
1152
1222
  */
1153
- function prepareRequestOptions$3(scopes, clientId, resourceId) {
1223
+ function prepareRequestOptions$2(scopes, clientId, resourceId) {
1154
1224
  const resource = mapScopesToResource(scopes);
1155
1225
  if (!resource) {
1156
- throw new Error(`${msiName$4}: Multiple scopes are not supported.`);
1226
+ throw new Error(`${msiName$3}: Multiple scopes are not supported.`);
1157
1227
  }
1158
1228
  const queryParameters = {
1159
1229
  resource,
@@ -1167,7 +1237,7 @@ function prepareRequestOptions$3(scopes, clientId, resourceId) {
1167
1237
  }
1168
1238
  // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
1169
1239
  if (!process.env.IDENTITY_ENDPOINT) {
1170
- throw new Error(`${msiName$4}: Missing environment variable: IDENTITY_ENDPOINT`);
1240
+ throw new Error(`${msiName$3}: Missing environment variable: IDENTITY_ENDPOINT`);
1171
1241
  }
1172
1242
  const query = new URLSearchParams(queryParameters);
1173
1243
  return coreRestPipeline.createPipelineRequest({
@@ -1190,7 +1260,7 @@ async function filePathRequest(identityClient, requestPrepareOptions) {
1190
1260
  if (response.bodyAsText) {
1191
1261
  message = ` Response: ${response.bodyAsText}`;
1192
1262
  }
1193
- throw new AuthenticationError(response.status, `${msiName$4}: To authenticate with Azure Arc MSI, status code 401 is expected on the first request. ${message}`);
1263
+ throw new AuthenticationError(response.status, `${msiName$3}: To authenticate with Azure Arc MSI, status code 401 is expected on the first request. ${message}`);
1194
1264
  }
1195
1265
  const authHeader = response.headers.get("www-authenticate") || "";
1196
1266
  try {
@@ -1204,13 +1274,13 @@ function platformToFilePath() {
1204
1274
  switch (process.platform) {
1205
1275
  case "win32":
1206
1276
  if (!process.env.PROGRAMDATA) {
1207
- throw new Error(`${msiName$4}: PROGRAMDATA environment variable has no value.`);
1277
+ throw new Error(`${msiName$3}: PROGRAMDATA environment variable has no value.`);
1208
1278
  }
1209
1279
  return `${process.env.PROGRAMDATA}\\AzureConnectedMachineAgent\\Tokens`;
1210
1280
  case "linux":
1211
1281
  return "/var/opt/azcmagent/tokens";
1212
1282
  default:
1213
- throw new Error(`${msiName$4}: Unsupported platform ${process.platform}.`);
1283
+ throw new Error(`${msiName$3}: Unsupported platform ${process.platform}.`);
1214
1284
  }
1215
1285
  }
1216
1286
  /**
@@ -1223,18 +1293,18 @@ function platformToFilePath() {
1223
1293
  */
1224
1294
  function validateKeyFile(filePath) {
1225
1295
  if (!filePath) {
1226
- throw new Error(`${msiName$4}: Failed to find the token file.`);
1296
+ throw new Error(`${msiName$3}: Failed to find the token file.`);
1227
1297
  }
1228
1298
  if (!filePath.endsWith(".key")) {
1229
- throw new Error(`${msiName$4}: unexpected file path from HIMDS service: ${filePath}.`);
1299
+ throw new Error(`${msiName$3}: unexpected file path from HIMDS service: ${filePath}.`);
1230
1300
  }
1231
1301
  const expectedPath = platformToFilePath();
1232
1302
  if (!filePath.startsWith(expectedPath)) {
1233
- throw new Error(`${msiName$4}: unexpected file path from HIMDS service: ${filePath}.`);
1303
+ throw new Error(`${msiName$3}: unexpected file path from HIMDS service: ${filePath}.`);
1234
1304
  }
1235
1305
  const stats = fs$1.statSync(filePath);
1236
1306
  if (stats.size > 4096) {
1237
- throw new Error(`${msiName$4}: The file at ${filePath} is larger than expected at ${stats.size} bytes.`);
1307
+ throw new Error(`${msiName$3}: The file at ${filePath} is larger than expected at ${stats.size} bytes.`);
1238
1308
  }
1239
1309
  }
1240
1310
  /**
@@ -1245,12 +1315,12 @@ const arcMsi = {
1245
1315
  async isAvailable({ scopes }) {
1246
1316
  const resource = mapScopesToResource(scopes);
1247
1317
  if (!resource) {
1248
- logger$m.info(`${msiName$4}: Unavailable. Multiple scopes are not supported.`);
1318
+ logger$l.info(`${msiName$3}: Unavailable. Multiple scopes are not supported.`);
1249
1319
  return false;
1250
1320
  }
1251
1321
  const result = Boolean(process.env.IMDS_ENDPOINT && process.env.IDENTITY_ENDPOINT);
1252
1322
  if (!result) {
1253
- logger$m.info(`${msiName$4}: The environment variables needed are: IMDS_ENDPOINT and IDENTITY_ENDPOINT`);
1323
+ logger$l.info(`${msiName$3}: The environment variables needed are: IMDS_ENDPOINT and IDENTITY_ENDPOINT`);
1254
1324
  }
1255
1325
  return result;
1256
1326
  },
@@ -1258,13 +1328,13 @@ const arcMsi = {
1258
1328
  var _a;
1259
1329
  const { identityClient, scopes, clientId, resourceId } = configuration;
1260
1330
  if (clientId) {
1261
- logger$m.warning(`${msiName$4}: user-assigned identities not supported. The argument clientId might be ignored by the service.`);
1331
+ logger$l.warning(`${msiName$3}: user-assigned identities not supported. The argument clientId might be ignored by the service.`);
1262
1332
  }
1263
1333
  if (resourceId) {
1264
- logger$m.warning(`${msiName$4}: user defined managed Identity by resource Id is not supported. Argument resourceId will be ignored.`);
1334
+ logger$l.warning(`${msiName$3}: user defined managed Identity by resource Id is not supported. Argument resourceId will be ignored.`);
1265
1335
  }
1266
- logger$m.info(`${msiName$4}: Authenticating.`);
1267
- const requestOptions = Object.assign(Object.assign({ disableJsonStringifyOnBody: true, deserializationMapper: undefined, abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$3(scopes, clientId, resourceId)), { allowInsecureConnection: true });
1336
+ logger$l.info(`${msiName$3}: Authenticating.`);
1337
+ const requestOptions = Object.assign(Object.assign({ disableJsonStringifyOnBody: true, deserializationMapper: undefined, abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$2(scopes, clientId, resourceId)), { allowInsecureConnection: true });
1268
1338
  const filePath = await filePathRequest(identityClient, requestOptions);
1269
1339
  validateKeyFile(filePath);
1270
1340
  const key = await fs$1.promises.readFile(filePath, { encoding: "utf-8" });
@@ -1277,78 +1347,6 @@ const arcMsi = {
1277
1347
  },
1278
1348
  };
1279
1349
 
1280
- // Copyright (c) Microsoft Corporation.
1281
- // Licensed under the MIT license.
1282
- const msiName$3 = "ManagedIdentityCredential - CloudShellMSI";
1283
- const logger$l = credentialLogger(msiName$3);
1284
- /**
1285
- * Generates the options used on the request for an access token.
1286
- */
1287
- function prepareRequestOptions$2(scopes, clientId, resourceId) {
1288
- const resource = mapScopesToResource(scopes);
1289
- if (!resource) {
1290
- throw new Error(`${msiName$3}: Multiple scopes are not supported.`);
1291
- }
1292
- const body = {
1293
- resource,
1294
- };
1295
- if (clientId) {
1296
- body.client_id = clientId;
1297
- }
1298
- if (resourceId) {
1299
- body.msi_res_id = resourceId;
1300
- }
1301
- // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
1302
- if (!process.env.MSI_ENDPOINT) {
1303
- throw new Error(`${msiName$3}: Missing environment variable: MSI_ENDPOINT`);
1304
- }
1305
- const params = new URLSearchParams(body);
1306
- return {
1307
- url: process.env.MSI_ENDPOINT,
1308
- method: "POST",
1309
- body: params.toString(),
1310
- headers: coreRestPipeline.createHttpHeaders({
1311
- Accept: "application/json",
1312
- Metadata: "true",
1313
- "Content-Type": "application/x-www-form-urlencoded",
1314
- }),
1315
- };
1316
- }
1317
- /**
1318
- * 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.
1319
- * 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.
1320
- */
1321
- const cloudShellMsi = {
1322
- name: "cloudShellMsi",
1323
- async isAvailable({ scopes }) {
1324
- const resource = mapScopesToResource(scopes);
1325
- if (!resource) {
1326
- logger$l.info(`${msiName$3}: Unavailable. Multiple scopes are not supported.`);
1327
- return false;
1328
- }
1329
- const result = Boolean(process.env.MSI_ENDPOINT);
1330
- if (!result) {
1331
- logger$l.info(`${msiName$3}: Unavailable. The environment variable MSI_ENDPOINT is needed.`);
1332
- }
1333
- return result;
1334
- },
1335
- async getToken(configuration, getTokenOptions = {}) {
1336
- const { identityClient, scopes, clientId, resourceId } = configuration;
1337
- if (clientId) {
1338
- logger$l.warning(`${msiName$3}: user-assigned identities not supported. The argument clientId might be ignored by the service.`);
1339
- }
1340
- if (resourceId) {
1341
- logger$l.warning(`${msiName$3}: user defined managed Identity by resource Id not supported. The argument resourceId might be ignored by the service.`);
1342
- }
1343
- logger$l.info(`${msiName$3}: Using the endpoint coming form the environment variable MSI_ENDPOINT = ${process.env.MSI_ENDPOINT}.`);
1344
- const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$2(scopes, clientId, resourceId)), {
1345
- // Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS).
1346
- allowInsecureConnection: true }));
1347
- const tokenResponse = await identityClient.sendTokenRequest(request);
1348
- return (tokenResponse && tokenResponse.accessToken) || null;
1349
- },
1350
- };
1351
-
1352
1350
  // Copyright (c) Microsoft Corporation.
1353
1351
  // Licensed under the MIT license.
1354
1352
  // This MSI can be easily tested by deploying a container to Azure Service Fabric with the Dockerfile:
@@ -1546,16 +1544,6 @@ function getMSALLogLevel(logLevel) {
1546
1544
  return msalCommon__namespace.LogLevel.Info;
1547
1545
  }
1548
1546
  }
1549
- /**
1550
- * Wraps core-util's randomUUID in order to allow for mocking in tests.
1551
- * This prepares the library for the upcoming core-util update to ESM.
1552
- *
1553
- * @internal
1554
- * @returns A string containing a random UUID
1555
- */
1556
- function randomUUID() {
1557
- return coreUtil.randomUUID();
1558
- }
1559
1547
  /**
1560
1548
  * Handles MSAL errors.
1561
1549
  */
@@ -1928,6 +1916,16 @@ function calculateRegionalAuthority(regionalAuthority) {
1928
1916
  return azureRegion;
1929
1917
  }
1930
1918
 
1919
+ // Copyright (c) Microsoft Corporation.
1920
+ // Licensed under the MIT license.
1921
+ /**
1922
+ * A call to open(), but mockable
1923
+ * @internal
1924
+ */
1925
+ const interactiveBrowserMockable = {
1926
+ open,
1927
+ };
1928
+
1931
1929
  // Copyright (c) Microsoft Corporation.
1932
1930
  // Licensed under the MIT license.
1933
1931
  /**
@@ -2234,6 +2232,105 @@ To work with multiple accounts for the same Client ID and Tenant ID, please prov
2234
2232
  });
2235
2233
  });
2236
2234
  }
2235
+ async function getTokenOnBehalfOf(scopes, userAssertionToken, clientSecretOrCertificate, options = {}) {
2236
+ msalLogger.getToken.info(`Attempting to acquire token on behalf of another user`);
2237
+ if (typeof clientSecretOrCertificate === "string") {
2238
+ // Client secret
2239
+ msalLogger.getToken.info(`Using client secret for on behalf of flow`);
2240
+ state.msalConfig.auth.clientSecret = clientSecretOrCertificate;
2241
+ }
2242
+ else {
2243
+ // Client certificate
2244
+ msalLogger.getToken.info(`Using client certificate for on behalf of flow`);
2245
+ state.msalConfig.auth.clientCertificate = clientSecretOrCertificate;
2246
+ }
2247
+ const msalApp = await getConfidentialApp(options);
2248
+ try {
2249
+ const response = await msalApp.acquireTokenOnBehalfOf({
2250
+ scopes,
2251
+ authority: state.msalConfig.auth.authority,
2252
+ claims: options.claims,
2253
+ oboAssertion: userAssertionToken,
2254
+ });
2255
+ ensureValidMsalToken(scopes, response, options);
2256
+ msalLogger.getToken.info(formatSuccess(scopes));
2257
+ return {
2258
+ token: response.accessToken,
2259
+ expiresOnTimestamp: response.expiresOn.getTime(),
2260
+ };
2261
+ }
2262
+ catch (err) {
2263
+ throw handleMsalError(scopes, err, options);
2264
+ }
2265
+ }
2266
+ async function getTokenByInteractiveRequest(scopes, options = {}) {
2267
+ msalLogger.getToken.info(`Attempting to acquire token interactively`);
2268
+ const app = await getPublicApp(options);
2269
+ /**
2270
+ * A helper function that supports brokered authentication through the MSAL's public application.
2271
+ *
2272
+ * When options.useDefaultBrokerAccount is true, the method will attempt to authenticate using the default broker account.
2273
+ * If the default broker account is not available, the method will fall back to interactive authentication.
2274
+ */
2275
+ async function getBrokeredToken(useDefaultBrokerAccount) {
2276
+ var _a;
2277
+ msalLogger.verbose("Authentication will resume through the broker");
2278
+ const interactiveRequest = createBaseInteractiveRequest();
2279
+ if (state.pluginConfiguration.broker.parentWindowHandle) {
2280
+ interactiveRequest.windowHandle = Buffer.from(state.pluginConfiguration.broker.parentWindowHandle);
2281
+ }
2282
+ else {
2283
+ // this is a bug, as the pluginConfiguration handler should validate this case.
2284
+ msalLogger.warning("Parent window handle is not specified for the broker. This may cause unexpected behavior. Please provide the parentWindowHandle.");
2285
+ }
2286
+ if (state.pluginConfiguration.broker.enableMsaPassthrough) {
2287
+ ((_a = interactiveRequest.tokenQueryParameters) !== null && _a !== void 0 ? _a : (interactiveRequest.tokenQueryParameters = {}))["msal_request_type"] =
2288
+ "consumer_passthrough";
2289
+ }
2290
+ if (useDefaultBrokerAccount) {
2291
+ interactiveRequest.prompt = "none";
2292
+ msalLogger.verbose("Attempting broker authentication using the default broker account");
2293
+ }
2294
+ else {
2295
+ msalLogger.verbose("Attempting broker authentication without the default broker account");
2296
+ }
2297
+ try {
2298
+ return await app.acquireTokenInteractive(interactiveRequest);
2299
+ }
2300
+ catch (e) {
2301
+ msalLogger.verbose(`Failed to authenticate through the broker: ${e.message}`);
2302
+ // If we tried to use the default broker account and failed, fall back to interactive authentication
2303
+ if (useDefaultBrokerAccount) {
2304
+ return getBrokeredToken(/* useDefaultBrokerAccount: */ false);
2305
+ }
2306
+ else {
2307
+ throw e;
2308
+ }
2309
+ }
2310
+ }
2311
+ function createBaseInteractiveRequest() {
2312
+ var _a, _b;
2313
+ return {
2314
+ openBrowser: async (url) => {
2315
+ await interactiveBrowserMockable.open(url, { wait: true, newInstance: true });
2316
+ },
2317
+ scopes,
2318
+ authority: state.msalConfig.auth.authority,
2319
+ claims: options === null || options === void 0 ? void 0 : options.claims,
2320
+ loginHint: options === null || options === void 0 ? void 0 : options.loginHint,
2321
+ errorTemplate: (_a = options === null || options === void 0 ? void 0 : options.browserCustomizationOptions) === null || _a === void 0 ? void 0 : _a.errorMessage,
2322
+ successTemplate: (_b = options === null || options === void 0 ? void 0 : options.browserCustomizationOptions) === null || _b === void 0 ? void 0 : _b.successMessage,
2323
+ };
2324
+ }
2325
+ return withSilentAuthentication(app, scopes, options, async () => {
2326
+ var _a;
2327
+ const interactiveRequest = createBaseInteractiveRequest();
2328
+ if (state.pluginConfiguration.broker.isEnabled) {
2329
+ return getBrokeredToken((_a = state.pluginConfiguration.broker.useDefaultBrokerAccount) !== null && _a !== void 0 ? _a : false);
2330
+ }
2331
+ return app.acquireTokenInteractive(interactiveRequest);
2332
+ });
2333
+ }
2237
2334
  return {
2238
2335
  getActiveAccount,
2239
2336
  getTokenByClientSecret,
@@ -2242,6 +2339,8 @@ To work with multiple accounts for the same Client ID and Tenant ID, please prov
2242
2339
  getTokenByDeviceCode,
2243
2340
  getTokenByUsernamePassword,
2244
2341
  getTokenByAuthorizationCode,
2342
+ getTokenOnBehalfOf,
2343
+ getTokenByInteractiveRequest,
2245
2344
  };
2246
2345
  }
2247
2346
 
@@ -2422,19 +2521,7 @@ function tokenExchangeMsi() {
2422
2521
  // Copyright (c) Microsoft Corporation.
2423
2522
  // Licensed under the MIT license.
2424
2523
  const logger$e = credentialLogger("ManagedIdentityCredential");
2425
- /**
2426
- * Attempts authentication using a managed identity available at the deployment environment.
2427
- * This authentication type works in Azure VMs, App Service instances, Azure Functions applications,
2428
- * Azure Kubernetes Services, Azure Service Fabric instances and inside of the Azure Cloud Shell.
2429
- *
2430
- * More information about configuring managed identities can be found here:
2431
- * https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview
2432
- */
2433
- class ManagedIdentityCredential {
2434
- /**
2435
- * @internal
2436
- * @hidden
2437
- */
2524
+ class LegacyMsiProvider {
2438
2525
  constructor(clientIdOrOptions, options) {
2439
2526
  var _a, _b;
2440
2527
  this.isEndpointUnavailable = null;
@@ -2456,7 +2543,7 @@ class ManagedIdentityCredential {
2456
2543
  this.resourceId = _options === null || _options === void 0 ? void 0 : _options.resourceId;
2457
2544
  // For JavaScript users.
2458
2545
  if (this.clientId && this.resourceId) {
2459
- throw new Error(`${ManagedIdentityCredential.name} - Client Id and Resource Id can't be provided at the same time.`);
2546
+ throw new Error(`ManagedIdentityCredential - Client Id and Resource Id can't be provided at the same time.`);
2460
2547
  }
2461
2548
  if (((_a = _options === null || _options === void 0 ? void 0 : _options.retryOptions) === null || _a === void 0 ? void 0 : _a.maxRetries) !== undefined) {
2462
2549
  this.msiRetryConfig.maxRetries = _options.retryOptions.maxRetries;
@@ -2509,10 +2596,10 @@ class ManagedIdentityCredential {
2509
2596
  return msi;
2510
2597
  }
2511
2598
  }
2512
- throw new CredentialUnavailableError(`${ManagedIdentityCredential.name} - No MSI credential available`);
2599
+ throw new CredentialUnavailableError(`ManagedIdentityCredential - No MSI credential available`);
2513
2600
  }
2514
2601
  async authenticateManagedIdentity(scopes, getTokenOptions) {
2515
- const { span, updatedOptions } = tracingClient.startSpan(`${ManagedIdentityCredential.name}.authenticateManagedIdentity`, getTokenOptions);
2602
+ const { span, updatedOptions } = tracingClient.startSpan(`ManagedIdentityCredential.authenticateManagedIdentity`, getTokenOptions);
2516
2603
  try {
2517
2604
  // Determining the available MSI, and avoiding checking for other MSIs while the program is running.
2518
2605
  const availableMSI = await this.cachedAvailableMSI(scopes, updatedOptions);
@@ -2546,7 +2633,7 @@ class ManagedIdentityCredential {
2546
2633
  */
2547
2634
  async getToken(scopes, options) {
2548
2635
  let result = null;
2549
- const { span, updatedOptions } = tracingClient.startSpan(`${ManagedIdentityCredential.name}.getToken`, options);
2636
+ const { span, updatedOptions } = tracingClient.startSpan(`ManagedIdentityCredential.getToken`, options);
2550
2637
  try {
2551
2638
  // isEndpointAvailable can be true, false, or null,
2552
2639
  // If it's null, it means we don't yet know whether
@@ -2612,27 +2699,27 @@ class ManagedIdentityCredential {
2612
2699
  // If either the network is unreachable,
2613
2700
  // we can safely assume the credential is unavailable.
2614
2701
  if (err.code === "ENETUNREACH") {
2615
- const error = new CredentialUnavailableError(`${ManagedIdentityCredential.name}: Unavailable. Network unreachable. Message: ${err.message}`);
2702
+ const error = new CredentialUnavailableError(`ManagedIdentityCredential: Unavailable. Network unreachable. Message: ${err.message}`);
2616
2703
  logger$e.getToken.info(formatError(scopes, error));
2617
2704
  throw error;
2618
2705
  }
2619
2706
  // If either the host was unreachable,
2620
2707
  // we can safely assume the credential is unavailable.
2621
2708
  if (err.code === "EHOSTUNREACH") {
2622
- const error = new CredentialUnavailableError(`${ManagedIdentityCredential.name}: Unavailable. No managed identity endpoint found. Message: ${err.message}`);
2709
+ const error = new CredentialUnavailableError(`ManagedIdentityCredential: Unavailable. No managed identity endpoint found. Message: ${err.message}`);
2623
2710
  logger$e.getToken.info(formatError(scopes, error));
2624
2711
  throw error;
2625
2712
  }
2626
2713
  // If err.statusCode has a value of 400, it comes from sendTokenRequest,
2627
2714
  // and it means that the endpoint is working, but that no identity is available.
2628
2715
  if (err.statusCode === 400) {
2629
- throw new CredentialUnavailableError(`${ManagedIdentityCredential.name}: The managed identity endpoint is indicating there's no available identity. Message: ${err.message}`);
2716
+ throw new CredentialUnavailableError(`ManagedIdentityCredential: The managed identity endpoint is indicating there's no available identity. Message: ${err.message}`);
2630
2717
  }
2631
2718
  // 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"
2632
2719
  // rather than just timing out, as expected.
2633
2720
  if (err.statusCode === 403 || err.code === 403) {
2634
2721
  if (err.message.includes("unreachable")) {
2635
- const error = new CredentialUnavailableError(`${ManagedIdentityCredential.name}: Unavailable. Network unreachable. Message: ${err.message}`);
2722
+ const error = new CredentialUnavailableError(`ManagedIdentityCredential: Unavailable. Network unreachable. Message: ${err.message}`);
2636
2723
  logger$e.getToken.info(formatError(scopes, error));
2637
2724
  throw error;
2638
2725
  }
@@ -2640,11 +2727,11 @@ class ManagedIdentityCredential {
2640
2727
  // If the error has no status code, we can assume there was no available identity.
2641
2728
  // This will throw silently during any ChainedTokenCredential.
2642
2729
  if (err.statusCode === undefined) {
2643
- throw new CredentialUnavailableError(`${ManagedIdentityCredential.name}: Authentication failed. Message ${err.message}`);
2730
+ throw new CredentialUnavailableError(`ManagedIdentityCredential: Authentication failed. Message ${err.message}`);
2644
2731
  }
2645
2732
  // Any other error should break the chain.
2646
2733
  throw new AuthenticationError(err.statusCode, {
2647
- error: `${ManagedIdentityCredential.name} authentication failed.`,
2734
+ error: `ManagedIdentityCredential authentication failed.`,
2648
2735
  error_description: err.message,
2649
2736
  });
2650
2737
  }
@@ -2721,24 +2808,56 @@ class ManagedIdentityCredential {
2721
2808
  // Copyright (c) Microsoft Corporation.
2722
2809
  // Licensed under the MIT license.
2723
2810
  /**
2724
- * Ensures the scopes value is an array.
2725
- * @internal
2726
- */
2727
- function ensureScopes(scopes) {
2728
- return Array.isArray(scopes) ? scopes : [scopes];
2729
- }
2730
- /**
2731
- * Throws if the received scope is not valid.
2732
- * @internal
2811
+ * Attempts authentication using a managed identity available at the deployment environment.
2812
+ * This authentication type works in Azure VMs, App Service instances, Azure Functions applications,
2813
+ * Azure Kubernetes Services, Azure Service Fabric instances and inside of the Azure Cloud Shell.
2814
+ *
2815
+ * More information about configuring managed identities can be found here:
2816
+ * https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview
2733
2817
  */
2734
- function ensureValidScopeForDevTimeCreds(scope, logger) {
2735
- if (!scope.match(/^[0-9a-zA-Z-_.:/]+$/)) {
2736
- const error = new Error("Invalid scope was specified by the user or calling client");
2737
- logger.getToken.info(formatError(scope, error));
2738
- throw error;
2739
- }
2740
- }
2741
- /**
2818
+ class ManagedIdentityCredential {
2819
+ /**
2820
+ * @internal
2821
+ * @hidden
2822
+ */
2823
+ constructor(clientIdOrOptions, options) {
2824
+ this.implProvider = new LegacyMsiProvider(clientIdOrOptions, options);
2825
+ }
2826
+ /**
2827
+ * Authenticates with Microsoft Entra ID and returns an access token if successful.
2828
+ * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.
2829
+ * If an unexpected error occurs, an {@link AuthenticationError} will be thrown with the details of the failure.
2830
+ *
2831
+ * @param scopes - The list of scopes for which the token will have access.
2832
+ * @param options - The options used to configure any requests this
2833
+ * TokenCredential implementation might make.
2834
+ */
2835
+ async getToken(scopes, options) {
2836
+ return this.implProvider.getToken(scopes, options);
2837
+ }
2838
+ }
2839
+
2840
+ // Copyright (c) Microsoft Corporation.
2841
+ // Licensed under the MIT license.
2842
+ /**
2843
+ * Ensures the scopes value is an array.
2844
+ * @internal
2845
+ */
2846
+ function ensureScopes(scopes) {
2847
+ return Array.isArray(scopes) ? scopes : [scopes];
2848
+ }
2849
+ /**
2850
+ * Throws if the received scope is not valid.
2851
+ * @internal
2852
+ */
2853
+ function ensureValidScopeForDevTimeCreds(scope, logger) {
2854
+ if (!scope.match(/^[0-9a-zA-Z-_.:/]+$/)) {
2855
+ const error = new Error("Invalid scope was specified by the user or calling client");
2856
+ logger.getToken.info(formatError(scope, error));
2857
+ throw error;
2858
+ }
2859
+ }
2860
+ /**
2742
2861
  * Returns the resource out of a scope.
2743
2862
  * @internal
2744
2863
  */
@@ -3826,425 +3945,6 @@ class DefaultAzureCredential extends ChainedTokenCredential {
3826
3945
  }
3827
3946
  }
3828
3947
 
3829
- // Copyright (c) Microsoft Corporation.
3830
- // Licensed under the MIT license.
3831
- /**
3832
- * MSAL partial base client for Node.js.
3833
- *
3834
- * It completes the input configuration with some default values.
3835
- * It also provides with utility protected methods that can be used from any of the clients,
3836
- * which includes handlers for successful responses and errors.
3837
- *
3838
- * @internal
3839
- */
3840
- class MsalNode {
3841
- constructor(options) {
3842
- var _a, _b, _c, _d, _e, _f;
3843
- this.app = {};
3844
- this.caeApp = {};
3845
- this.requiresConfidential = false;
3846
- this.logger = options.logger;
3847
- this.msalConfig = this.defaultNodeMsalConfig(options);
3848
- this.tenantId = resolveTenantId(options.logger, options.tenantId, options.clientId);
3849
- this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds((_a = options === null || options === void 0 ? void 0 : options.tokenCredentialOptions) === null || _a === void 0 ? void 0 : _a.additionallyAllowedTenants);
3850
- this.clientId = this.msalConfig.auth.clientId;
3851
- if (options === null || options === void 0 ? void 0 : options.getAssertion) {
3852
- this.getAssertion = options.getAssertion;
3853
- }
3854
- this.enableBroker = (_b = options === null || options === void 0 ? void 0 : options.brokerOptions) === null || _b === void 0 ? void 0 : _b.enabled;
3855
- this.enableMsaPassthrough = (_c = options === null || options === void 0 ? void 0 : options.brokerOptions) === null || _c === void 0 ? void 0 : _c.legacyEnableMsaPassthrough;
3856
- this.parentWindowHandle = (_d = options.brokerOptions) === null || _d === void 0 ? void 0 : _d.parentWindowHandle;
3857
- // If persistence has been configured
3858
- if (persistenceProvider !== undefined && ((_e = options.tokenCachePersistenceOptions) === null || _e === void 0 ? void 0 : _e.enabled)) {
3859
- const cacheBaseName = options.tokenCachePersistenceOptions.name || DEFAULT_TOKEN_CACHE_NAME;
3860
- const nonCaeOptions = Object.assign({ name: `${cacheBaseName}.${CACHE_NON_CAE_SUFFIX}` }, options.tokenCachePersistenceOptions);
3861
- const caeOptions = Object.assign({ name: `${cacheBaseName}.${CACHE_CAE_SUFFIX}` }, options.tokenCachePersistenceOptions);
3862
- this.createCachePlugin = () => persistenceProvider(nonCaeOptions);
3863
- this.createCachePluginCae = () => persistenceProvider(caeOptions);
3864
- }
3865
- else if ((_f = options.tokenCachePersistenceOptions) === null || _f === void 0 ? void 0 : _f.enabled) {
3866
- throw new Error([
3867
- "Persistent token caching was requested, but no persistence provider was configured.",
3868
- "You must install the identity-cache-persistence plugin package (`npm install --save @azure/identity-cache-persistence`)",
3869
- "and enable it by importing `useIdentityPlugin` from `@azure/identity` and calling",
3870
- "`useIdentityPlugin(cachePersistencePlugin)` before using `tokenCachePersistenceOptions`.",
3871
- ].join(" "));
3872
- }
3873
- // If broker has not been configured
3874
- if (!hasNativeBroker() && this.enableBroker) {
3875
- throw new Error([
3876
- "Broker for WAM was requested to be enabled, but no native broker was configured.",
3877
- "You must install the identity-broker plugin package (`npm install --save @azure/identity-broker`)",
3878
- "and enable it by importing `useIdentityPlugin` from `@azure/identity` and calling",
3879
- "`useIdentityPlugin(createNativeBrokerPlugin())` before using `enableBroker`.",
3880
- ].join(" "));
3881
- }
3882
- this.azureRegion = calculateRegionalAuthority(options.regionalAuthority);
3883
- }
3884
- /**
3885
- * Generates a MSAL configuration that generally works for Node.js
3886
- */
3887
- defaultNodeMsalConfig(options) {
3888
- var _a;
3889
- const clientId = options.clientId || DeveloperSignOnClientId;
3890
- const tenantId = resolveTenantId(options.logger, options.tenantId, options.clientId);
3891
- this.authorityHost = options.authorityHost || process.env.AZURE_AUTHORITY_HOST;
3892
- const authority = getAuthority(tenantId, this.authorityHost);
3893
- this.identityClient = new IdentityClient(Object.assign(Object.assign({}, options.tokenCredentialOptions), { authorityHost: authority, loggingOptions: options.loggingOptions }));
3894
- const clientCapabilities = [];
3895
- return {
3896
- auth: {
3897
- clientId,
3898
- authority,
3899
- knownAuthorities: getKnownAuthorities(tenantId, authority, options.disableInstanceDiscovery),
3900
- clientCapabilities,
3901
- },
3902
- // Cache is defined in this.prepare();
3903
- system: {
3904
- networkClient: this.identityClient,
3905
- loggerOptions: {
3906
- loggerCallback: defaultLoggerCallback(options.logger),
3907
- logLevel: getMSALLogLevel(logger$r.getLogLevel()),
3908
- piiLoggingEnabled: (_a = options.loggingOptions) === null || _a === void 0 ? void 0 : _a.enableUnsafeSupportLogging,
3909
- },
3910
- },
3911
- };
3912
- }
3913
- getApp(appType, enableCae) {
3914
- const app = enableCae ? this.caeApp : this.app;
3915
- if (appType === "publicFirst") {
3916
- return (app.public || app.confidential);
3917
- }
3918
- else if (appType === "confidentialFirst") {
3919
- return (app.confidential || app.public);
3920
- }
3921
- else if (appType === "confidential") {
3922
- return app.confidential;
3923
- }
3924
- else {
3925
- return app.public;
3926
- }
3927
- }
3928
- /**
3929
- * Prepares the MSAL applications.
3930
- */
3931
- async init(options) {
3932
- if (options === null || options === void 0 ? void 0 : options.abortSignal) {
3933
- options.abortSignal.addEventListener("abort", () => {
3934
- // This will abort any pending request in the IdentityClient,
3935
- // based on the received or generated correlationId
3936
- this.identityClient.abortRequests(options.correlationId);
3937
- });
3938
- }
3939
- const app = (options === null || options === void 0 ? void 0 : options.enableCae) ? this.caeApp : this.app;
3940
- if (options === null || options === void 0 ? void 0 : options.enableCae) {
3941
- this.msalConfig.auth.clientCapabilities = ["cp1"];
3942
- }
3943
- if (app.public || app.confidential) {
3944
- return;
3945
- }
3946
- if ((options === null || options === void 0 ? void 0 : options.enableCae) && this.createCachePluginCae !== undefined) {
3947
- this.msalConfig.cache = {
3948
- cachePlugin: await this.createCachePluginCae(),
3949
- };
3950
- }
3951
- if (this.createCachePlugin !== undefined) {
3952
- this.msalConfig.cache = {
3953
- cachePlugin: await this.createCachePlugin(),
3954
- };
3955
- }
3956
- if (hasNativeBroker() && this.enableBroker) {
3957
- this.msalConfig.broker = {
3958
- nativeBrokerPlugin: nativeBrokerInfo.broker,
3959
- };
3960
- if (!this.parentWindowHandle) {
3961
- // error should have been thrown from within the constructor of InteractiveBrowserCredential
3962
- this.logger.warning("Parent window handle is not specified for the broker. This may cause unexpected behavior. Please provide the parentWindowHandle.");
3963
- }
3964
- }
3965
- if (options === null || options === void 0 ? void 0 : options.enableCae) {
3966
- this.caeApp.public = new msalCommon__namespace.PublicClientApplication(this.msalConfig);
3967
- }
3968
- else {
3969
- this.app.public = new msalCommon__namespace.PublicClientApplication(this.msalConfig);
3970
- }
3971
- if (this.getAssertion) {
3972
- this.msalConfig.auth.clientAssertion = await this.getAssertion();
3973
- }
3974
- // The confidential client requires either a secret, assertion or certificate.
3975
- if (this.msalConfig.auth.clientSecret ||
3976
- this.msalConfig.auth.clientAssertion ||
3977
- this.msalConfig.auth.clientCertificate) {
3978
- if (options === null || options === void 0 ? void 0 : options.enableCae) {
3979
- this.caeApp.confidential = new msalCommon__namespace.ConfidentialClientApplication(this.msalConfig);
3980
- }
3981
- else {
3982
- this.app.confidential = new msalCommon__namespace.ConfidentialClientApplication(this.msalConfig);
3983
- }
3984
- }
3985
- else {
3986
- if (this.requiresConfidential) {
3987
- throw new Error("Unable to generate the MSAL confidential client. Missing either the client's secret, certificate or assertion.");
3988
- }
3989
- }
3990
- }
3991
- /**
3992
- * Allows the cancellation of a MSAL request.
3993
- */
3994
- withCancellation(promise, abortSignal, onCancel) {
3995
- return new Promise((resolve, reject) => {
3996
- promise
3997
- .then((msalToken) => {
3998
- return resolve(msalToken);
3999
- })
4000
- .catch(reject);
4001
- if (abortSignal) {
4002
- abortSignal.addEventListener("abort", () => {
4003
- onCancel === null || onCancel === void 0 ? void 0 : onCancel();
4004
- });
4005
- }
4006
- });
4007
- }
4008
- /**
4009
- * Returns the existing account, attempts to load the account from MSAL.
4010
- */
4011
- async getActiveAccount(enableCae = false) {
4012
- if (this.account) {
4013
- return this.account;
4014
- }
4015
- const cache = this.getApp("confidentialFirst", enableCae).getTokenCache();
4016
- const accountsByTenant = await (cache === null || cache === void 0 ? void 0 : cache.getAllAccounts());
4017
- if (!accountsByTenant) {
4018
- return;
4019
- }
4020
- if (accountsByTenant.length === 1) {
4021
- this.account = msalToPublic(this.clientId, accountsByTenant[0]);
4022
- }
4023
- else {
4024
- this.logger
4025
- .info(`More than one account was found authenticated for this Client ID and Tenant ID.
4026
- However, no "authenticationRecord" has been provided for this credential,
4027
- therefore we're unable to pick between these accounts.
4028
- A new login attempt will be requested, to ensure the correct account is picked.
4029
- 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.`);
4030
- return;
4031
- }
4032
- return this.account;
4033
- }
4034
- /**
4035
- * Attempts to retrieve a token from cache.
4036
- */
4037
- async getTokenSilent(scopes, options) {
4038
- var _a, _b, _c;
4039
- await this.getActiveAccount(options === null || options === void 0 ? void 0 : options.enableCae);
4040
- if (!this.account) {
4041
- throw new AuthenticationRequiredError({
4042
- scopes,
4043
- getTokenOptions: options,
4044
- message: "Silent authentication failed. We couldn't retrieve an active account from the cache.",
4045
- });
4046
- }
4047
- const silentRequest = {
4048
- // To be able to re-use the account, the Token Cache must also have been provided.
4049
- account: publicToMsal(this.account),
4050
- correlationId: options === null || options === void 0 ? void 0 : options.correlationId,
4051
- scopes,
4052
- authority: options === null || options === void 0 ? void 0 : options.authority,
4053
- claims: options === null || options === void 0 ? void 0 : options.claims,
4054
- };
4055
- if (hasNativeBroker() && this.enableBroker) {
4056
- if (!silentRequest.tokenQueryParameters) {
4057
- silentRequest.tokenQueryParameters = {};
4058
- }
4059
- if (!this.parentWindowHandle) {
4060
- // error should have been thrown from within the constructor of InteractiveBrowserCredential
4061
- this.logger.warning("Parent window handle is not specified for the broker. This may cause unexpected behavior. Please provide the parentWindowHandle.");
4062
- }
4063
- if (this.enableMsaPassthrough) {
4064
- silentRequest.tokenQueryParameters["msal_request_type"] = "consumer_passthrough";
4065
- }
4066
- }
4067
- try {
4068
- this.logger.info("Attempting to acquire token silently");
4069
- /**
4070
- * The following code to retrieve all accounts is done as a workaround in an attempt to force the
4071
- * refresh of the token cache with the token and the account passed in through the
4072
- * `authenticationRecord` parameter. See issue - https://github.com/Azure/azure-sdk-for-js/issues/24349#issuecomment-1496715651
4073
- * This workaround serves as a workaround for silent authentication not happening when authenticationRecord is passed.
4074
- */
4075
- await ((_a = this.getApp("publicFirst", options === null || options === void 0 ? void 0 : options.enableCae)) === null || _a === void 0 ? void 0 : _a.getTokenCache().getAllAccounts());
4076
- 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));
4077
- return this.handleResult(scopes, response || undefined);
4078
- }
4079
- catch (err) {
4080
- throw handleMsalError(scopes, err, options);
4081
- }
4082
- }
4083
- /**
4084
- * Wrapper around each MSAL flow get token operation: doGetToken.
4085
- * If disableAutomaticAuthentication is sent through the constructor, it will prevent MSAL from requesting the user input.
4086
- */
4087
- async getToken(scopes, options = {}) {
4088
- const tenantId = processMultiTenantRequest(this.tenantId, options, this.additionallyAllowedTenantIds) ||
4089
- this.tenantId;
4090
- options.authority = getAuthority(tenantId, this.authorityHost);
4091
- options.correlationId = (options === null || options === void 0 ? void 0 : options.correlationId) || randomUUID();
4092
- await this.init(options);
4093
- try {
4094
- // MSAL now caches tokens based on their claims,
4095
- // so now one has to keep track fo claims in order to retrieve the newer tokens from acquireTokenSilent
4096
- // This update happened on PR: https://github.com/AzureAD/microsoft-authentication-library-for-js/pull/4533
4097
- const optionsClaims = options.claims;
4098
- if (optionsClaims) {
4099
- this.cachedClaims = optionsClaims;
4100
- }
4101
- if (this.cachedClaims && !optionsClaims) {
4102
- options.claims = this.cachedClaims;
4103
- }
4104
- // We don't return the promise since we want to catch errors right here.
4105
- return await this.getTokenSilent(scopes, options);
4106
- }
4107
- catch (err) {
4108
- if (err.name !== "AuthenticationRequiredError") {
4109
- throw err;
4110
- }
4111
- if (options === null || options === void 0 ? void 0 : options.disableAutomaticAuthentication) {
4112
- throw new AuthenticationRequiredError({
4113
- scopes,
4114
- getTokenOptions: options,
4115
- message: "Automatic authentication has been disabled. You may call the authentication() method.",
4116
- });
4117
- }
4118
- this.logger.info(`Silent authentication failed, falling back to interactive method.`);
4119
- return this.doGetToken(scopes, options);
4120
- }
4121
- }
4122
- /**
4123
- * Handles the MSAL authentication result.
4124
- * If the result has an account, we update the local account reference.
4125
- * If the token received is invalid, an error will be thrown depending on what's missing.
4126
- */
4127
- handleResult(scopes, result, getTokenOptions) {
4128
- if (result === null || result === void 0 ? void 0 : result.account) {
4129
- this.account = msalToPublic(this.clientId, result.account);
4130
- }
4131
- ensureValidMsalToken(scopes, result, getTokenOptions);
4132
- this.logger.getToken.info(formatSuccess(scopes));
4133
- return {
4134
- token: result.accessToken,
4135
- expiresOnTimestamp: result.expiresOn.getTime(),
4136
- };
4137
- }
4138
- }
4139
-
4140
- // Copyright (c) Microsoft Corporation.
4141
- // Licensed under the MIT license.
4142
- /**
4143
- * A call to open(), but mockable
4144
- * @internal
4145
- */
4146
- const interactiveBrowserMockable = {
4147
- open,
4148
- };
4149
- /**
4150
- * This MSAL client sets up a web server to listen for redirect callbacks, then calls to the MSAL's public application's `acquireTokenByDeviceCode` during `doGetToken`
4151
- * to trigger the authentication flow, and then respond based on the values obtained from the redirect callback
4152
- * @internal
4153
- */
4154
- class MsalOpenBrowser extends MsalNode {
4155
- constructor(options) {
4156
- var _a, _b, _c, _d;
4157
- super(options);
4158
- this.loginHint = options.loginHint;
4159
- this.errorTemplate = (_a = options.browserCustomizationOptions) === null || _a === void 0 ? void 0 : _a.errorMessage;
4160
- this.successTemplate = (_b = options.browserCustomizationOptions) === null || _b === void 0 ? void 0 : _b.successMessage;
4161
- this.logger = credentialLogger("Node.js MSAL Open Browser");
4162
- this.useDefaultBrokerAccount =
4163
- ((_c = options.brokerOptions) === null || _c === void 0 ? void 0 : _c.enabled) && ((_d = options.brokerOptions) === null || _d === void 0 ? void 0 : _d.useDefaultBrokerAccount);
4164
- }
4165
- async doGetToken(scopes, options = {}) {
4166
- try {
4167
- const interactiveRequest = {
4168
- openBrowser: async (url) => {
4169
- await interactiveBrowserMockable.open(url, { wait: true, newInstance: true });
4170
- },
4171
- scopes,
4172
- authority: options === null || options === void 0 ? void 0 : options.authority,
4173
- claims: options === null || options === void 0 ? void 0 : options.claims,
4174
- correlationId: options === null || options === void 0 ? void 0 : options.correlationId,
4175
- loginHint: this.loginHint,
4176
- errorTemplate: this.errorTemplate,
4177
- successTemplate: this.successTemplate,
4178
- };
4179
- if (hasNativeBroker() && this.enableBroker) {
4180
- return this.doGetBrokeredToken(scopes, interactiveRequest, {
4181
- enableCae: options.enableCae,
4182
- useDefaultBrokerAccount: this.useDefaultBrokerAccount,
4183
- });
4184
- }
4185
- // If the broker is not enabled, we will fall back to interactive authentication
4186
- if (hasNativeBroker() && !this.enableBroker) {
4187
- this.logger.verbose("Authentication will resume normally without the broker, since it's not enabled");
4188
- }
4189
- const result = await this.getApp("public", options === null || options === void 0 ? void 0 : options.enableCae).acquireTokenInteractive(interactiveRequest);
4190
- return this.handleResult(scopes, result || undefined);
4191
- }
4192
- catch (err) {
4193
- throw handleMsalError(scopes, err, options);
4194
- }
4195
- }
4196
- /**
4197
- * A helper function that supports brokered authentication through the MSAL's public application.
4198
- *
4199
- * When options.useDefaultBrokerAccount is true, the method will attempt to authenticate using the default broker account.
4200
- * If the default broker account is not available, the method will fall back to interactive authentication.
4201
- */
4202
- async doGetBrokeredToken(scopes, interactiveRequest, options) {
4203
- var _a;
4204
- this.logger.verbose("Authentication will resume through the broker");
4205
- if (this.parentWindowHandle) {
4206
- interactiveRequest.windowHandle = Buffer.from(this.parentWindowHandle);
4207
- }
4208
- else {
4209
- // error should have been thrown from within the constructor of InteractiveBrowserCredential
4210
- this.logger.warning("Parent window handle is not specified for the broker. This may cause unexpected behavior. Please provide the parentWindowHandle.");
4211
- }
4212
- if (this.enableMsaPassthrough) {
4213
- ((_a = interactiveRequest.tokenQueryParameters) !== null && _a !== void 0 ? _a : (interactiveRequest.tokenQueryParameters = {}))["msal_request_type"] =
4214
- "consumer_passthrough";
4215
- }
4216
- if (options.useDefaultBrokerAccount) {
4217
- interactiveRequest.prompt = "none";
4218
- this.logger.verbose("Attempting broker authentication using the default broker account");
4219
- }
4220
- else {
4221
- interactiveRequest.prompt = undefined;
4222
- this.logger.verbose("Attempting broker authentication without the default broker account");
4223
- }
4224
- try {
4225
- const result = await this.getApp("public", options === null || options === void 0 ? void 0 : options.enableCae).acquireTokenInteractive(interactiveRequest);
4226
- if (result.fromNativeBroker) {
4227
- this.logger.verbose(`This result is returned from native broker`);
4228
- }
4229
- return this.handleResult(scopes, result || undefined);
4230
- }
4231
- catch (e) {
4232
- this.logger.verbose(`Failed to authenticate through the broker: ${e.message}`);
4233
- // If we tried to use the default broker account and failed, fall back to interactive authentication
4234
- if (options.useDefaultBrokerAccount) {
4235
- return this.doGetBrokeredToken(scopes, interactiveRequest, {
4236
- enableCae: options.enableCae,
4237
- useDefaultBrokerAccount: false,
4238
- });
4239
- }
4240
- else {
4241
- // If we're not using the default broker account, throw the error
4242
- throw handleMsalError(scopes, e);
4243
- }
4244
- }
4245
- }
4246
- }
4247
-
4248
3948
  // Copyright (c) Microsoft Corporation.
4249
3949
  // Licensed under the MIT license.
4250
3950
  const logger$4 = credentialLogger("InteractiveBrowserCredential");
@@ -4266,31 +3966,27 @@ class InteractiveBrowserCredential {
4266
3966
  * @param options - Options for configuring the client which makes the authentication requests.
4267
3967
  */
4268
3968
  constructor(options) {
4269
- var _a, _b, _c, _d;
4270
- const redirectUri = typeof options.redirectUri === "function"
4271
- ? options.redirectUri()
4272
- : options.redirectUri || "http://localhost";
4273
- this.tenantId = options === null || options === void 0 ? void 0 : options.tenantId;
3969
+ var _a, _b, _c, _d, _e;
3970
+ this.tenantId = resolveTenantId(logger$4, options.tenantId, options.clientId);
4274
3971
  this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants);
3972
+ const msalClientOptions = Object.assign(Object.assign({}, options), { tokenCredentialOptions: options, logger: logger$4 });
4275
3973
  const ibcNodeOptions = options;
3974
+ this.browserCustomizationOptions = ibcNodeOptions.browserCustomizationOptions;
3975
+ this.loginHint = ibcNodeOptions.loginHint;
4276
3976
  if ((_a = ibcNodeOptions === null || ibcNodeOptions === void 0 ? void 0 : ibcNodeOptions.brokerOptions) === null || _a === void 0 ? void 0 : _a.enabled) {
4277
3977
  if (!((_b = ibcNodeOptions === null || ibcNodeOptions === void 0 ? void 0 : ibcNodeOptions.brokerOptions) === null || _b === void 0 ? void 0 : _b.parentWindowHandle)) {
4278
3978
  throw new Error("In order to do WAM authentication, `parentWindowHandle` under `brokerOptions` is a required parameter");
4279
3979
  }
4280
3980
  else {
4281
- this.msalFlow = new MsalOpenBrowser(Object.assign(Object.assign({}, options), { tokenCredentialOptions: options, logger: logger$4,
4282
- redirectUri, browserCustomizationOptions: ibcNodeOptions === null || ibcNodeOptions === void 0 ? void 0 : ibcNodeOptions.browserCustomizationOptions, brokerOptions: {
4283
- enabled: true,
4284
- parentWindowHandle: ibcNodeOptions.brokerOptions.parentWindowHandle,
4285
- legacyEnableMsaPassthrough: (_c = ibcNodeOptions.brokerOptions) === null || _c === void 0 ? void 0 : _c.legacyEnableMsaPassthrough,
4286
- useDefaultBrokerAccount: (_d = ibcNodeOptions.brokerOptions) === null || _d === void 0 ? void 0 : _d.useDefaultBrokerAccount,
4287
- } }));
3981
+ msalClientOptions.brokerOptions = {
3982
+ enabled: true,
3983
+ parentWindowHandle: ibcNodeOptions.brokerOptions.parentWindowHandle,
3984
+ legacyEnableMsaPassthrough: (_c = ibcNodeOptions.brokerOptions) === null || _c === void 0 ? void 0 : _c.legacyEnableMsaPassthrough,
3985
+ useDefaultBrokerAccount: (_d = ibcNodeOptions.brokerOptions) === null || _d === void 0 ? void 0 : _d.useDefaultBrokerAccount,
3986
+ };
4288
3987
  }
4289
3988
  }
4290
- else {
4291
- this.msalFlow = new MsalOpenBrowser(Object.assign(Object.assign({}, options), { tokenCredentialOptions: options, logger: logger$4,
4292
- redirectUri, browserCustomizationOptions: ibcNodeOptions === null || ibcNodeOptions === void 0 ? void 0 : ibcNodeOptions.browserCustomizationOptions }));
4293
- }
3989
+ this.msalClient = createMsalClient((_e = options.clientId) !== null && _e !== void 0 ? _e : DeveloperSignOnClientId, this.tenantId, msalClientOptions);
4294
3990
  this.disableAutomaticAuthentication = options === null || options === void 0 ? void 0 : options.disableAutomaticAuthentication;
4295
3991
  }
4296
3992
  /**
@@ -4309,7 +4005,7 @@ class InteractiveBrowserCredential {
4309
4005
  return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async (newOptions) => {
4310
4006
  newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger$4);
4311
4007
  const arrayScopes = ensureScopes(scopes);
4312
- return this.msalFlow.getToken(arrayScopes, Object.assign(Object.assign({}, newOptions), { disableAutomaticAuthentication: this.disableAutomaticAuthentication }));
4008
+ return this.msalClient.getTokenByInteractiveRequest(arrayScopes, Object.assign(Object.assign({}, newOptions), { disableAutomaticAuthentication: this.disableAutomaticAuthentication, browserCustomizationOptions: this.browserCustomizationOptions, loginHint: this.loginHint }));
4313
4009
  });
4314
4010
  }
4315
4011
  /**
@@ -4328,8 +4024,8 @@ class InteractiveBrowserCredential {
4328
4024
  async authenticate(scopes, options = {}) {
4329
4025
  return tracingClient.withSpan(`${this.constructor.name}.authenticate`, options, async (newOptions) => {
4330
4026
  const arrayScopes = ensureScopes(scopes);
4331
- await this.msalFlow.getToken(arrayScopes, newOptions);
4332
- return this.msalFlow.getActiveAccount();
4027
+ await this.msalClient.getTokenByInteractiveRequest(arrayScopes, Object.assign(Object.assign({}, newOptions), { disableAutomaticAuthentication: false, browserCustomizationOptions: this.browserCustomizationOptions, loginHint: this.loginHint }));
4028
+ return this.msalClient.getActiveAccount();
4333
4029
  });
4334
4030
  }
4335
4031
  }
@@ -4571,102 +4267,6 @@ class AuthorizationCodeCredential {
4571
4267
  }
4572
4268
  }
4573
4269
 
4574
- // Copyright (c) Microsoft Corporation.
4575
- // Licensed under the MIT license.
4576
- const readFileAsync = util.promisify(fs.readFile);
4577
- /**
4578
- * Tries to asynchronously load a certificate from the given path.
4579
- *
4580
- * @param configuration - Either the PEM value or the path to the certificate.
4581
- * @param sendCertificateChain - Option to include x5c header for SubjectName and Issuer name authorization.
4582
- * @returns - The certificate parts, or `undefined` if the certificate could not be loaded.
4583
- * @internal
4584
- */
4585
- async function parseCertificate(configuration, sendCertificateChain) {
4586
- const certificateParts = {};
4587
- const certificate = configuration
4588
- .certificate;
4589
- const certificatePath = configuration
4590
- .certificatePath;
4591
- certificateParts.certificateContents =
4592
- certificate || (await readFileAsync(certificatePath, "utf8"));
4593
- if (sendCertificateChain) {
4594
- certificateParts.x5c = certificateParts.certificateContents;
4595
- }
4596
- const certificatePattern = /(-+BEGIN CERTIFICATE-+)(\n\r?|\r\n?)([A-Za-z0-9+/\n\r]+=*)(\n\r?|\r\n?)(-+END CERTIFICATE-+)/g;
4597
- const publicKeys = [];
4598
- // Match all possible certificates, in the order they are in the file. These will form the chain that is used for x5c
4599
- let match;
4600
- do {
4601
- match = certificatePattern.exec(certificateParts.certificateContents);
4602
- if (match) {
4603
- publicKeys.push(match[3]);
4604
- }
4605
- } while (match);
4606
- if (publicKeys.length === 0) {
4607
- throw new Error("The file at the specified path does not contain a PEM-encoded certificate.");
4608
- }
4609
- certificateParts.thumbprint = crypto.createHash("sha1")
4610
- .update(Buffer.from(publicKeys[0], "base64"))
4611
- .digest("hex")
4612
- .toUpperCase();
4613
- return certificateParts;
4614
- }
4615
-
4616
- // Copyright (c) Microsoft Corporation.
4617
- // Licensed under the MIT license.
4618
- /**
4619
- * MSAL on behalf of flow. Calls to MSAL's confidential application's `acquireTokenOnBehalfOf` during `doGetToken`.
4620
- * @internal
4621
- */
4622
- class MsalOnBehalfOf extends MsalNode {
4623
- constructor(options) {
4624
- super(options);
4625
- this.logger.info("Initialized MSAL's On-Behalf-Of flow");
4626
- this.requiresConfidential = true;
4627
- this.userAssertionToken = options.userAssertionToken;
4628
- this.certificatePath = options.certificatePath;
4629
- this.sendCertificateChain = options.sendCertificateChain;
4630
- this.clientSecret = options.clientSecret;
4631
- }
4632
- // Changing the MSAL configuration asynchronously
4633
- async init(options) {
4634
- if (this.certificatePath) {
4635
- try {
4636
- const parts = await parseCertificate({ certificatePath: this.certificatePath }, this.sendCertificateChain);
4637
- this.msalConfig.auth.clientCertificate = {
4638
- thumbprint: parts.thumbprint,
4639
- privateKey: parts.certificateContents,
4640
- x5c: parts.x5c,
4641
- };
4642
- }
4643
- catch (error) {
4644
- this.logger.info(formatError("", error));
4645
- throw error;
4646
- }
4647
- }
4648
- else {
4649
- this.msalConfig.auth.clientSecret = this.clientSecret;
4650
- }
4651
- return super.init(options);
4652
- }
4653
- async doGetToken(scopes, options = {}) {
4654
- try {
4655
- const result = await this.getApp("confidential", options.enableCae).acquireTokenOnBehalfOf({
4656
- scopes,
4657
- correlationId: options.correlationId,
4658
- authority: options.authority,
4659
- claims: options.claims,
4660
- oboAssertion: this.userAssertionToken,
4661
- });
4662
- return this.handleResult(scopes, result || undefined);
4663
- }
4664
- catch (err) {
4665
- throw handleMsalError(scopes, err, options);
4666
- }
4667
- }
4668
- }
4669
-
4670
4270
  // Copyright (c) Microsoft Corporation.
4671
4271
  // Licensed under the MIT license.
4672
4272
  const credentialName = "OnBehalfOfCredential";
@@ -4676,16 +4276,19 @@ const logger = credentialLogger(credentialName);
4676
4276
  */
4677
4277
  class OnBehalfOfCredential {
4678
4278
  constructor(options) {
4679
- this.options = options;
4680
4279
  const { clientSecret } = options;
4681
- const { certificatePath } = options;
4280
+ const { certificatePath, sendCertificateChain } = options;
4682
4281
  const { tenantId, clientId, userAssertionToken, additionallyAllowedTenants: additionallyAllowedTenantIds, } = options;
4683
4282
  if (!tenantId || !clientId || !(clientSecret || certificatePath) || !userAssertionToken) {
4684
4283
  throw new Error(`${credentialName}: tenantId, clientId, clientSecret (or certificatePath) and userAssertionToken are required parameters.`);
4685
4284
  }
4285
+ this.certificatePath = certificatePath;
4286
+ this.clientSecret = clientSecret;
4287
+ this.userAssertionToken = userAssertionToken;
4288
+ this.sendCertificateChain = sendCertificateChain;
4686
4289
  this.tenantId = tenantId;
4687
4290
  this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(additionallyAllowedTenantIds);
4688
- this.msalFlow = new MsalOnBehalfOf(Object.assign(Object.assign({}, this.options), { logger, tokenCredentialOptions: this.options }));
4291
+ this.msalClient = createMsalClient(clientId, this.tenantId, Object.assign(Object.assign({}, options), { logger, tokenCredentialOptions: options }));
4689
4292
  }
4690
4293
  /**
4691
4294
  * Authenticates with Microsoft Entra ID and returns an access token if successful.
@@ -4698,9 +4301,60 @@ class OnBehalfOfCredential {
4698
4301
  return tracingClient.withSpan(`${credentialName}.getToken`, options, async (newOptions) => {
4699
4302
  newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger);
4700
4303
  const arrayScopes = ensureScopes(scopes);
4701
- return this.msalFlow.getToken(arrayScopes, newOptions);
4304
+ if (this.certificatePath) {
4305
+ const clientCertificate = await this.buildClientCertificate(this.certificatePath);
4306
+ return this.msalClient.getTokenOnBehalfOf(arrayScopes, this.userAssertionToken, clientCertificate, newOptions);
4307
+ }
4308
+ else if (this.clientSecret) {
4309
+ return this.msalClient.getTokenOnBehalfOf(arrayScopes, this.userAssertionToken, this.clientSecret, options);
4310
+ }
4311
+ else {
4312
+ // this is a bug, as the constructor should have thrown an error if neither clientSecret nor certificatePath were provided
4313
+ throw new Error("Expected either clientSecret or certificatePath to be defined.");
4314
+ }
4702
4315
  });
4703
4316
  }
4317
+ async buildClientCertificate(certificatePath) {
4318
+ try {
4319
+ const parts = await this.parseCertificate({ certificatePath }, this.sendCertificateChain);
4320
+ return {
4321
+ thumbprint: parts.thumbprint,
4322
+ privateKey: parts.certificateContents,
4323
+ x5c: parts.x5c,
4324
+ };
4325
+ }
4326
+ catch (error) {
4327
+ logger.info(formatError("", error));
4328
+ throw error;
4329
+ }
4330
+ }
4331
+ async parseCertificate(configuration, sendCertificateChain) {
4332
+ const certificatePath = configuration.certificatePath;
4333
+ const certificateContents = await promises$1.readFile(certificatePath, "utf8");
4334
+ const x5c = sendCertificateChain ? certificateContents : undefined;
4335
+ const certificatePattern = /(-+BEGIN CERTIFICATE-+)(\n\r?|\r\n?)([A-Za-z0-9+/\n\r]+=*)(\n\r?|\r\n?)(-+END CERTIFICATE-+)/g;
4336
+ const publicKeys = [];
4337
+ // Match all possible certificates, in the order they are in the file. These will form the chain that is used for x5c
4338
+ let match;
4339
+ do {
4340
+ match = certificatePattern.exec(certificateContents);
4341
+ if (match) {
4342
+ publicKeys.push(match[3]);
4343
+ }
4344
+ } while (match);
4345
+ if (publicKeys.length === 0) {
4346
+ throw new Error("The file at the specified path does not contain a PEM-encoded certificate.");
4347
+ }
4348
+ const thumbprint = node_crypto.createHash("sha1")
4349
+ .update(Buffer.from(publicKeys[0], "base64"))
4350
+ .digest("hex")
4351
+ .toUpperCase();
4352
+ return {
4353
+ certificateContents,
4354
+ thumbprint,
4355
+ x5c,
4356
+ };
4357
+ }
4704
4358
  }
4705
4359
 
4706
4360
  // Copyright (c) Microsoft Corporation.