@azure/identity 1.0.0-preview.1 → 1.0.0-preview.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of @azure/identity might be problematic. Click here for more details.

Files changed (88) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +50 -23
  3. package/browser/identity.js +9828 -0
  4. package/browser/identity.js.map +1 -0
  5. package/browser/identity.min.js +2 -0
  6. package/browser/identity.min.js.map +1 -0
  7. package/dist/index.js +475 -205
  8. package/dist/index.js.map +1 -1
  9. package/dist-esm/src/client/errors.d.ts +1 -1
  10. package/dist-esm/src/client/errors.d.ts.map +1 -1
  11. package/dist-esm/src/client/errors.js +9 -1
  12. package/dist-esm/src/client/errors.js.map +1 -1
  13. package/dist-esm/src/client/identityClient.d.ts +20 -17
  14. package/dist-esm/src/client/identityClient.d.ts.map +1 -1
  15. package/dist-esm/src/client/identityClient.js +42 -206
  16. package/dist-esm/src/client/identityClient.js.map +1 -1
  17. package/dist-esm/src/credentials/clientCertificateCredential.browser.d.ts +7 -0
  18. package/dist-esm/src/credentials/clientCertificateCredential.browser.d.ts.map +1 -0
  19. package/dist-esm/src/credentials/clientCertificateCredential.browser.js +12 -0
  20. package/dist-esm/src/credentials/clientCertificateCredential.browser.js.map +1 -0
  21. package/dist-esm/src/credentials/clientCertificateCredential.d.ts +5 -5
  22. package/dist-esm/src/credentials/clientCertificateCredential.d.ts.map +1 -1
  23. package/dist-esm/src/credentials/clientCertificateCredential.js +59 -5
  24. package/dist-esm/src/credentials/clientCertificateCredential.js.map +1 -1
  25. package/dist-esm/src/credentials/clientSecretCredential.d.ts +3 -3
  26. package/dist-esm/src/credentials/clientSecretCredential.d.ts.map +1 -1
  27. package/dist-esm/src/credentials/clientSecretCredential.js +27 -4
  28. package/dist-esm/src/credentials/clientSecretCredential.js.map +1 -1
  29. package/dist-esm/src/credentials/deviceCodeCredential.browser.d.ts +7 -0
  30. package/dist-esm/src/credentials/deviceCodeCredential.browser.d.ts.map +1 -0
  31. package/dist-esm/src/credentials/deviceCodeCredential.browser.js +12 -0
  32. package/dist-esm/src/credentials/deviceCodeCredential.browser.js.map +1 -0
  33. package/dist-esm/src/credentials/deviceCodeCredential.d.ts +67 -0
  34. package/dist-esm/src/credentials/deviceCodeCredential.d.ts.map +1 -0
  35. package/dist-esm/src/credentials/deviceCodeCredential.js +139 -0
  36. package/dist-esm/src/credentials/deviceCodeCredential.js.map +1 -0
  37. package/dist-esm/src/credentials/environmentCredential.browser.d.ts +7 -0
  38. package/dist-esm/src/credentials/environmentCredential.browser.d.ts.map +1 -0
  39. package/dist-esm/src/credentials/environmentCredential.browser.js +12 -0
  40. package/dist-esm/src/credentials/environmentCredential.browser.js.map +1 -0
  41. package/dist-esm/src/credentials/environmentCredential.d.ts.map +1 -1
  42. package/dist-esm/src/credentials/environmentCredential.js +0 -4
  43. package/dist-esm/src/credentials/environmentCredential.js.map +1 -1
  44. package/dist-esm/src/credentials/interactiveBrowserCredential.browser.d.ts +32 -0
  45. package/dist-esm/src/credentials/interactiveBrowserCredential.browser.d.ts.map +1 -0
  46. package/dist-esm/src/credentials/interactiveBrowserCredential.browser.js +112 -0
  47. package/dist-esm/src/credentials/interactiveBrowserCredential.browser.js.map +1 -0
  48. package/dist-esm/src/credentials/interactiveBrowserCredential.d.ts +12 -0
  49. package/dist-esm/src/credentials/interactiveBrowserCredential.d.ts.map +1 -0
  50. package/dist-esm/src/credentials/interactiveBrowserCredential.js +17 -0
  51. package/dist-esm/src/credentials/interactiveBrowserCredential.js.map +1 -0
  52. package/dist-esm/src/credentials/interactiveBrowserCredentialOptions.d.ts +24 -0
  53. package/dist-esm/src/credentials/interactiveBrowserCredentialOptions.d.ts.map +1 -0
  54. package/dist-esm/src/credentials/interactiveBrowserCredentialOptions.js +3 -0
  55. package/dist-esm/src/credentials/interactiveBrowserCredentialOptions.js.map +1 -0
  56. package/dist-esm/src/credentials/managedIdentityCredential.browser.d.ts +7 -0
  57. package/dist-esm/src/credentials/managedIdentityCredential.browser.d.ts.map +1 -0
  58. package/dist-esm/src/credentials/managedIdentityCredential.browser.js +15 -0
  59. package/dist-esm/src/credentials/managedIdentityCredential.browser.js.map +1 -0
  60. package/dist-esm/src/credentials/managedIdentityCredential.d.ts +10 -1
  61. package/dist-esm/src/credentials/managedIdentityCredential.d.ts.map +1 -1
  62. package/dist-esm/src/credentials/managedIdentityCredential.js +144 -2
  63. package/dist-esm/src/credentials/managedIdentityCredential.js.map +1 -1
  64. package/dist-esm/src/credentials/usernamePasswordCredential.d.ts +39 -0
  65. package/dist-esm/src/credentials/usernamePasswordCredential.d.ts.map +1 -0
  66. package/dist-esm/src/credentials/usernamePasswordCredential.js +67 -0
  67. package/dist-esm/src/credentials/usernamePasswordCredential.js.map +1 -0
  68. package/dist-esm/src/index.d.ts +4 -0
  69. package/dist-esm/src/index.d.ts.map +1 -1
  70. package/dist-esm/src/index.js +3 -0
  71. package/dist-esm/src/index.js.map +1 -1
  72. package/package.json +32 -14
  73. package/src/client/errors.ts +11 -3
  74. package/src/client/identityClient.ts +64 -246
  75. package/src/credentials/clientCertificateCredential.browser.ts +27 -0
  76. package/src/credentials/clientCertificateCredential.ts +72 -22
  77. package/src/credentials/clientSecretCredential.ts +32 -17
  78. package/src/credentials/deviceCodeCredential.browser.ts +27 -0
  79. package/src/credentials/deviceCodeCredential.ts +203 -0
  80. package/src/credentials/environmentCredential.browser.ts +19 -0
  81. package/src/credentials/environmentCredential.ts +5 -9
  82. package/src/credentials/interactiveBrowserCredential.browser.ts +134 -0
  83. package/src/credentials/interactiveBrowserCredential.ts +31 -0
  84. package/src/credentials/interactiveBrowserCredentialOptions.ts +30 -0
  85. package/src/credentials/managedIdentityCredential.browser.ts +22 -0
  86. package/src/credentials/managedIdentityCredential.ts +179 -8
  87. package/src/credentials/usernamePasswordCredential.ts +83 -0
  88. package/src/index.ts +4 -0
package/dist/index.js CHANGED
@@ -5,8 +5,8 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
6
6
 
7
7
  var tslib_1 = require('tslib');
8
- var coreHttp = require('@azure/core-http');
9
8
  var qs = _interopDefault(require('qs'));
9
+ var coreHttp = require('@azure/core-http');
10
10
  var jws = _interopDefault(require('jws'));
11
11
  var uuid = _interopDefault(require('uuid'));
12
12
  var fs = require('fs');
@@ -14,6 +14,11 @@ var crypto = require('crypto');
14
14
 
15
15
  // Copyright (c) Microsoft Corporation.
16
16
  // Licensed under the MIT License.
17
+ function isErrorResponse(errorResponse) {
18
+ return errorResponse &&
19
+ typeof errorResponse.error === "string" &&
20
+ typeof errorResponse.error_description === "string";
21
+ }
17
22
  /**
18
23
  * Provides details about a failure to authenticate with Azure Active
19
24
  * Directory. The `errorResponse` field contains more details about
@@ -25,7 +30,10 @@ class AuthenticationError extends Error {
25
30
  error: "unknown",
26
31
  error_description: "An unknown error occurred and no additional details are available."
27
32
  };
28
- if (errorBody) {
33
+ if (isErrorResponse(errorBody)) {
34
+ errorResponse = errorBody;
35
+ }
36
+ else if (typeof errorBody === "string") {
29
37
  try {
30
38
  // Most error responses will contain JSON-formatted error details
31
39
  // in the response body
@@ -113,17 +121,15 @@ class ChainedTokenCredential {
113
121
  }
114
122
 
115
123
  // Copyright (c) Microsoft Corporation.
116
- const SelfSignedJwtLifetimeMins = 10;
117
124
  const DefaultAuthorityHost = "https://login.microsoftonline.com";
118
- const DefaultScopeSuffix = "/.default";
119
- const ImdsEndpoint = "http://169.254.169.254/metadata/identity/oauth2/token";
120
- const ImdsApiVersion = "2018-02-01";
121
- const AppServiceMsiApiVersion = "2017-09-01";
122
125
  class IdentityClient extends coreHttp.ServiceClient {
123
126
  constructor(options) {
124
127
  options = options || IdentityClient.getDefaultOptions();
125
128
  super(undefined, options);
126
- this.baseUri = options.authorityHost;
129
+ this.baseUri = this.authorityHost = options.authorityHost || DefaultAuthorityHost;
130
+ if (!this.baseUri.startsWith("https:")) {
131
+ throw new Error("The authorityHost address must use the 'https' protocol.");
132
+ }
127
133
  }
128
134
  createWebResource(requestOptions) {
129
135
  const webResource = new coreHttp.WebResource();
@@ -138,15 +144,196 @@ class IdentityClient extends coreHttp.ServiceClient {
138
144
  });
139
145
  if (response.status === 200 || response.status === 201) {
140
146
  return {
141
- token: response.parsedBody.access_token,
142
- expiresOnTimestamp: expiresOnParser(response.parsedBody)
147
+ accessToken: {
148
+ token: response.parsedBody.access_token,
149
+ expiresOnTimestamp: expiresOnParser(response.parsedBody)
150
+ },
151
+ refreshToken: response.parsedBody.refresh_token,
143
152
  };
144
153
  }
145
154
  else {
146
- throw new AuthenticationError(response.status, response.bodyAsText);
155
+ throw new AuthenticationError(response.status, response.parsedBody || response.bodyAsText);
147
156
  }
148
157
  });
149
158
  }
159
+ refreshAccessToken(tenantId, clientId, scopes, refreshToken, clientSecret, expiresOnParser, options) {
160
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
161
+ if (refreshToken === undefined) {
162
+ return null;
163
+ }
164
+ const refreshParams = {
165
+ grant_type: "refresh_token",
166
+ client_id: clientId,
167
+ refresh_token: refreshToken,
168
+ scope: scopes
169
+ };
170
+ if (clientSecret !== undefined) {
171
+ refreshParams.client_secret = clientSecret;
172
+ }
173
+ const webResource = this.createWebResource({
174
+ url: `${this.authorityHost}/${tenantId}/oauth2/v2.0/token`,
175
+ method: "POST",
176
+ disableJsonStringifyOnBody: true,
177
+ deserializationMapper: undefined,
178
+ body: qs.stringify(refreshParams),
179
+ headers: {
180
+ Accept: "application/json",
181
+ "Content-Type": "application/x-www-form-urlencoded"
182
+ },
183
+ abortSignal: options && options.abortSignal
184
+ });
185
+ try {
186
+ return yield this.sendTokenRequest(webResource, expiresOnParser);
187
+ }
188
+ catch (err) {
189
+ if (err instanceof AuthenticationError && err.errorResponse.error === "interaction_required") {
190
+ // It's likely that the refresh token has expired, so
191
+ // return null so that the credential implementation will
192
+ // initiate the authentication flow again.
193
+ return null;
194
+ }
195
+ else {
196
+ throw err;
197
+ }
198
+ }
199
+ });
200
+ }
201
+ static getDefaultOptions() {
202
+ return {
203
+ authorityHost: DefaultAuthorityHost
204
+ };
205
+ }
206
+ }
207
+
208
+ // Copyright (c) Microsoft Corporation.
209
+ /**
210
+ * Enables authentication to Azure Active Directory using a client secret
211
+ * that was generated for an App Registration. More information on how
212
+ * to configure a client secret can be found here:
213
+ *
214
+ * https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-access-web-apis#add-credentials-to-your-web-application
215
+ *
216
+ */
217
+ class ClientSecretCredential {
218
+ /**
219
+ * Creates an instance of the ClientSecretCredential with the details
220
+ * needed to authenticate against Azure Active Directory with a client
221
+ * secret.
222
+ *
223
+ * @param tenantId The Azure Active Directory tenant (directory) ID.
224
+ * @param clientId The client (application) ID of an App Registration in the tenant.
225
+ * @param clientSecret A client secret that was generated for the App Registration.
226
+ * @param options Options for configuring the client which makes the authentication request.
227
+ */
228
+ constructor(tenantId, clientId, clientSecret, options) {
229
+ this.identityClient = new IdentityClient(options);
230
+ this.tenantId = tenantId;
231
+ this.clientId = clientId;
232
+ this.clientSecret = clientSecret;
233
+ }
234
+ /**
235
+ * Authenticates with Azure Active Directory and returns an {@link AccessToken} if
236
+ * successful. If authentication cannot be performed at this time, this method may
237
+ * return null. If an error occurs during authentication, an {@link AuthenticationError}
238
+ * containing failure details will be thrown.
239
+ *
240
+ * @param scopes The list of scopes for which the token will have access.
241
+ * @param options The options used to configure any requests this
242
+ * TokenCredential implementation might make.
243
+ */
244
+ getToken(scopes, options) {
245
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
246
+ const webResource = this.identityClient.createWebResource({
247
+ url: `${this.identityClient.authorityHost}/${this.tenantId}/oauth2/v2.0/token`,
248
+ method: "POST",
249
+ disableJsonStringifyOnBody: true,
250
+ deserializationMapper: undefined,
251
+ body: qs.stringify({
252
+ response_type: "token",
253
+ grant_type: "client_credentials",
254
+ client_id: this.clientId,
255
+ client_secret: this.clientSecret,
256
+ scope: typeof scopes === "string" ? scopes : scopes.join(" ")
257
+ }),
258
+ headers: {
259
+ Accept: "application/json",
260
+ "Content-Type": "application/x-www-form-urlencoded"
261
+ },
262
+ abortSignal: options && options.abortSignal
263
+ });
264
+ const tokenResponse = yield this.identityClient.sendTokenRequest(webResource);
265
+ return (tokenResponse && tokenResponse.accessToken) || null;
266
+ });
267
+ }
268
+ }
269
+
270
+ // Copyright (c) Microsoft Corporation.
271
+ /**
272
+ * Enables authentication to Azure Active Directory using client secret
273
+ * details configured in the following environment variables:
274
+ *
275
+ * - AZURE_TENANT_ID: The Azure Active Directory tenant (directory) ID.
276
+ * - AZURE_CLIENT_ID: The client (application) ID of an App Registration in the tenant.
277
+ * - AZURE_CLIENT_SECRET: A client secret that was generated for the App Registration.
278
+ *
279
+ * This credential ultimately uses a {@link ClientSecretCredential} to
280
+ * perform the authentication using these details. Please consult the
281
+ * documentation of that class for more details.
282
+ */
283
+ class EnvironmentCredential {
284
+ /**
285
+ * Creates an instance of the EnvironmentCredential class and reads
286
+ * client secret details from environment variables. If the expected
287
+ * environment variables are not found at this time, the getToken method
288
+ * will return null when invoked.
289
+ *
290
+ * @param options Options for configuring the client which makes the authentication request.
291
+ */
292
+ constructor(options) {
293
+ this._credential = undefined;
294
+ const tenantId = process.env.AZURE_TENANT_ID, clientId = process.env.AZURE_CLIENT_ID, clientSecret = process.env.AZURE_CLIENT_SECRET;
295
+ if (tenantId && clientId && clientSecret) {
296
+ this._credential = new ClientSecretCredential(tenantId, clientId, clientSecret, options);
297
+ }
298
+ }
299
+ /**
300
+ * Authenticates with Azure Active Directory and returns an {@link AccessToken} if
301
+ * successful. If authentication cannot be performed at this time, this method may
302
+ * return null. If an error occurs during authentication, an {@link AuthenticationError}
303
+ * containing failure details will be thrown.
304
+ *
305
+ * @param scopes The list of scopes for which the token will have access.
306
+ * @param options The options used to configure any requests this
307
+ * TokenCredential implementation might make.
308
+ */
309
+ getToken(scopes, options) {
310
+ if (this._credential) {
311
+ return this._credential.getToken(scopes, options);
312
+ }
313
+ return Promise.resolve(null);
314
+ }
315
+ }
316
+
317
+ // Copyright (c) Microsoft Corporation.
318
+ const DefaultScopeSuffix = "/.default";
319
+ const ImdsEndpoint = "http://169.254.169.254/metadata/identity/oauth2/token";
320
+ const ImdsApiVersion = "2018-02-01";
321
+ const AppServiceMsiApiVersion = "2017-09-01";
322
+ /**
323
+ * Attempts authentication using a managed identity that has been assigned
324
+ * to the deployment environment. This authentication type works in Azure VMs,
325
+ * App Service and Azure Functions applications, and inside of Azure Cloud Shell.
326
+ *
327
+ * More information about configuring managed identities can be found here:
328
+ *
329
+ * https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview
330
+ */
331
+ class ManagedIdentityCredential {
332
+ constructor(clientId, options) {
333
+ this.isEndpointUnavailable = null;
334
+ this.identityClient = new IdentityClient(options);
335
+ this.clientId = clientId;
336
+ }
150
337
  mapScopesToResource(scopes) {
151
338
  let scope = "";
152
339
  if (Array.isArray(scopes)) {
@@ -163,13 +350,6 @@ class IdentityClient extends coreHttp.ServiceClient {
163
350
  }
164
351
  return scope.substr(0, scope.lastIndexOf(DefaultScopeSuffix));
165
352
  }
166
- dateInSeconds(date) {
167
- return Math.floor(date.getTime() / 1000);
168
- }
169
- addMinutes(date, minutes) {
170
- date.setMinutes(date.getMinutes() + minutes);
171
- return date;
172
- }
173
353
  createImdsAuthRequest(resource, clientId) {
174
354
  const queryParameters = {
175
355
  resource,
@@ -236,10 +416,10 @@ class IdentityClient extends coreHttp.ServiceClient {
236
416
  // Create a request with a 500 msec timeout since we expect that
237
417
  // not having a "Metadata" header should cause an error to be
238
418
  // returned quickly from the endpoint, proving its availability.
239
- const webResource = this.createWebResource(request);
419
+ const webResource = this.identityClient.createWebResource(request);
240
420
  webResource.timeout = 500;
241
421
  try {
242
- yield this.sendRequest(webResource);
422
+ yield this.identityClient.sendRequest(webResource);
243
423
  }
244
424
  catch (err) {
245
425
  if (err instanceof coreHttp.RestError && err.code === coreHttp.RestError.REQUEST_SEND_ERROR) {
@@ -251,27 +431,6 @@ class IdentityClient extends coreHttp.ServiceClient {
251
431
  return true;
252
432
  });
253
433
  }
254
- authenticateClientSecret(tenantId, clientId, clientSecret, scopes, getTokenOptions) {
255
- const webResource = this.createWebResource({
256
- url: `${this.baseUri}/${tenantId}/oauth2/v2.0/token`,
257
- method: "POST",
258
- disableJsonStringifyOnBody: true,
259
- deserializationMapper: undefined,
260
- body: qs.stringify({
261
- response_type: "token",
262
- grant_type: "client_credentials",
263
- client_id: clientId,
264
- client_secret: clientSecret,
265
- scope: typeof scopes === "string" ? scopes : scopes.join(" ")
266
- }),
267
- headers: {
268
- Accept: "application/json",
269
- "Content-Type": "application/x-www-form-urlencoded"
270
- },
271
- abortSignal: getTokenOptions && getTokenOptions.abortSignal
272
- });
273
- return this.sendTokenRequest(webResource);
274
- }
275
434
  authenticateManagedIdentity(scopes, checkIfImdsEndpointAvailable, clientId, getTokenOptions) {
276
435
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
277
436
  let authRequestOptions;
@@ -306,165 +465,10 @@ class IdentityClient extends coreHttp.ServiceClient {
306
465
  return null;
307
466
  }
308
467
  }
309
- const webResource = this.createWebResource(Object.assign({ disableJsonStringifyOnBody: true, deserializationMapper: undefined, abortSignal: getTokenOptions && getTokenOptions.abortSignal }, authRequestOptions));
310
- return this.sendTokenRequest(webResource, expiresInParser);
311
- });
312
- }
313
- authenticateClientCertificate(tenantId, clientId, certificateString, certificateX5t, scopes, getTokenOptions) {
314
- const tokenId = uuid.v4();
315
- const audienceUrl = `${this.baseUri}/${tenantId}/oauth2/v2.0/token`;
316
- const header = {
317
- typ: "JWT",
318
- alg: "RS256",
319
- x5t: certificateX5t
320
- };
321
- const payload = {
322
- iss: clientId,
323
- sub: clientId,
324
- aud: audienceUrl,
325
- jti: tokenId,
326
- nbf: this.dateInSeconds(new Date()),
327
- exp: this.dateInSeconds(this.addMinutes(new Date(), SelfSignedJwtLifetimeMins))
328
- };
329
- const clientAssertion = jws.sign({
330
- header,
331
- payload,
332
- secret: certificateString
333
- });
334
- const webResource = this.createWebResource({
335
- url: audienceUrl,
336
- method: "POST",
337
- disableJsonStringifyOnBody: true,
338
- deserializationMapper: undefined,
339
- body: qs.stringify({
340
- response_type: "token",
341
- grant_type: "client_credentials",
342
- client_id: clientId,
343
- client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
344
- client_assertion: clientAssertion,
345
- scope: typeof scopes === "string" ? scopes : scopes.join(" ")
346
- }),
347
- headers: {
348
- Accept: "application/json",
349
- "Content-Type": "application/x-www-form-urlencoded"
350
- },
351
- abortSignal: getTokenOptions && getTokenOptions.abortSignal
468
+ const webResource = this.identityClient.createWebResource(Object.assign({ disableJsonStringifyOnBody: true, deserializationMapper: undefined, abortSignal: getTokenOptions && getTokenOptions.abortSignal }, authRequestOptions));
469
+ const tokenResponse = yield this.identityClient.sendTokenRequest(webResource, expiresInParser);
470
+ return (tokenResponse && tokenResponse.accessToken) || null;
352
471
  });
353
- return this.sendTokenRequest(webResource);
354
- }
355
- static getDefaultOptions() {
356
- return {
357
- authorityHost: DefaultAuthorityHost
358
- };
359
- }
360
- }
361
-
362
- // Copyright (c) Microsoft Corporation.
363
- /**
364
- * Enables authentication to Azure Active Directory using a client secret
365
- * that was generated for an App Registration. More information on how
366
- * to configure a client secret can be found here:
367
- *
368
- * https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-access-web-apis#add-credentials-to-your-web-application
369
- *
370
- */
371
- class ClientSecretCredential {
372
- /**
373
- * Creates an instance of the ClientSecretCredential with the details
374
- * needed to authenticate against Azure Active Directory with a client
375
- * secret.
376
- *
377
- * @param tenantId The Azure Active Directory tenant (directory) ID.
378
- * @param clientId The client (application) ID of an App Registration in the tenant.
379
- * @param clientSecret A client secret that was generated for the App Registration.
380
- * @param options Options for configuring the client which makes the authentication request.
381
- */
382
- constructor(tenantId, clientId, clientSecret, options) {
383
- this.identityClient = new IdentityClient(options);
384
- this._tenantId = tenantId;
385
- this._clientId = clientId;
386
- this._clientSecret = clientSecret;
387
- }
388
- /**
389
- * Authenticates with Azure Active Directory and returns an {@link AccessToken} if
390
- * successful. If authentication cannot be performed at this time, this method may
391
- * return null. If an error occurs during authentication, an {@link AuthenticationError}
392
- * containing failure details will be thrown.
393
- *
394
- * @param scopes The list of scopes for which the token will have access.
395
- * @param options The options used to configure any requests this
396
- * TokenCredential implementation might make.
397
- */
398
- getToken(scopes, options) {
399
- return this.identityClient.authenticateClientSecret(this._tenantId, this._clientId, this._clientSecret, scopes, options);
400
- }
401
- }
402
-
403
- // Copyright (c) Microsoft Corporation.
404
- /**
405
- * Enables authentication to Azure Active Directory using client secret
406
- * details configured in the following environment variables:
407
- *
408
- * - AZURE_TENANT_ID: The Azure Active Directory tenant (directory) ID.
409
- * - AZURE_CLIENT_ID: The client (application) ID of an App Registration in the tenant.
410
- * - AZURE_CLIENT_SECRET: A client secret that was generated for the App Registration.
411
- *
412
- * This credential ultimately uses a {@link ClientSecretCredential} to
413
- * perform the authentication using these details. Please consult the
414
- * documentation of that class for more details.
415
- */
416
- class EnvironmentCredential {
417
- /**
418
- * Creates an instance of the EnvironmentCredential class and reads
419
- * client secret details from environment variables. If the expected
420
- * environment variables are not found at this time, the getToken method
421
- * will return null when invoked.
422
- *
423
- * @param options Options for configuring the client which makes the authentication request.
424
- */
425
- constructor(options) {
426
- this._credential = undefined;
427
- if (!coreHttp.isNode) {
428
- throw "EnvironmentCredential is only supported when running in Node.js.";
429
- }
430
- const tenantId = process.env.AZURE_TENANT_ID, clientId = process.env.AZURE_CLIENT_ID, clientSecret = process.env.AZURE_CLIENT_SECRET;
431
- if (tenantId && clientId && clientSecret) {
432
- this._credential = new ClientSecretCredential(tenantId, clientId, clientSecret, options);
433
- }
434
- }
435
- /**
436
- * Authenticates with Azure Active Directory and returns an {@link AccessToken} if
437
- * successful. If authentication cannot be performed at this time, this method may
438
- * return null. If an error occurs during authentication, an {@link AuthenticationError}
439
- * containing failure details will be thrown.
440
- *
441
- * @param scopes The list of scopes for which the token will have access.
442
- * @param options The options used to configure any requests this
443
- * TokenCredential implementation might make.
444
- */
445
- getToken(scopes, options) {
446
- if (this._credential) {
447
- return this._credential.getToken(scopes, options);
448
- }
449
- return Promise.resolve(null);
450
- }
451
- }
452
-
453
- // Copyright (c) Microsoft Corporation.
454
- /**
455
- * Attempts authentication using a managed identity that has been assigned
456
- * to the deployment environment. This authentication type works in Azure VMs,
457
- * App Service and Azure Functions applications, and inside of Azure Cloud Shell.
458
- *
459
- * More information about configuring managed identities can be found here:
460
- *
461
- * https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview
462
- */
463
- class ManagedIdentityCredential {
464
- constructor(clientId, options) {
465
- this.isEndpointUnavailable = null;
466
- this.identityClient = new IdentityClient(options);
467
- this._clientId = clientId;
468
472
  }
469
473
  /**
470
474
  * Authenticates with Azure Active Directory and returns an {@link AccessToken} if
@@ -484,7 +488,7 @@ class ManagedIdentityCredential {
484
488
  // the endpoint is available and need to check for it.
485
489
  if (this.isEndpointUnavailable !== true) {
486
490
  result =
487
- yield this.identityClient.authenticateManagedIdentity(scopes, this.isEndpointUnavailable === null, this._clientId, options);
491
+ yield this.authenticateManagedIdentity(scopes, this.isEndpointUnavailable === null, this.clientId, options);
488
492
  // If authenticateManagedIdentity returns null, it means no MSI
489
493
  // endpoints are available. In this case, don't try them in future
490
494
  // requests.
@@ -519,6 +523,14 @@ class DefaultAzureCredential extends ChainedTokenCredential {
519
523
  }
520
524
 
521
525
  // Copyright (c) Microsoft Corporation.
526
+ const SelfSignedJwtLifetimeMins = 10;
527
+ function timestampInSeconds(date) {
528
+ return Math.floor(date.getTime() / 1000);
529
+ }
530
+ function addMinutes(date, minutes) {
531
+ date.setMinutes(date.getMinutes() + minutes);
532
+ return date;
533
+ }
522
534
  /**
523
535
  * Enables authentication to Azure Active Directory using a PEM-encoded
524
536
  * certificate that is assigned to an App Registration. More information
@@ -539,11 +551,11 @@ class ClientCertificateCredential {
539
551
  */
540
552
  constructor(tenantId, clientId, certificatePath, options) {
541
553
  this.identityClient = new IdentityClient(options);
542
- this._tenantId = tenantId;
543
- this._clientId = clientId;
544
- this._certificateString = fs.readFileSync(certificatePath, "utf8");
554
+ this.tenantId = tenantId;
555
+ this.clientId = clientId;
556
+ this.certificateString = fs.readFileSync(certificatePath, "utf8");
545
557
  const certificatePattern = /(-+BEGIN CERTIFICATE-+)(\n\r?|\r\n?)([A-Za-z0-9+/\n\r]+=*)(\n\r?|\r\n?)(-+END CERTIFICATE-+)/;
546
- const matchCert = this._certificateString.match(certificatePattern);
558
+ const matchCert = this.certificateString.match(certificatePattern);
547
559
  const publicKey = matchCert ? matchCert[3] : "";
548
560
  if (!publicKey) {
549
561
  throw new Error("The file at the specified path does not contain a PEM-encoded certificate.");
@@ -565,7 +577,262 @@ class ClientCertificateCredential {
565
577
  * TokenCredential implementation might make.
566
578
  */
567
579
  getToken(scopes, options) {
568
- return this.identityClient.authenticateClientCertificate(this._tenantId, this._clientId, this._certificateString, this.certificateX5t, scopes, options);
580
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
581
+ const tokenId = uuid.v4();
582
+ const audienceUrl = `${this.identityClient.authorityHost}/${this.tenantId}/oauth2/v2.0/token`;
583
+ const header = {
584
+ typ: "JWT",
585
+ alg: "RS256",
586
+ x5t: this.certificateX5t
587
+ };
588
+ const payload = {
589
+ iss: this.clientId,
590
+ sub: this.clientId,
591
+ aud: audienceUrl,
592
+ jti: tokenId,
593
+ nbf: timestampInSeconds(new Date()),
594
+ exp: timestampInSeconds(addMinutes(new Date(), SelfSignedJwtLifetimeMins))
595
+ };
596
+ const clientAssertion = jws.sign({
597
+ header,
598
+ payload,
599
+ secret: this.certificateString
600
+ });
601
+ const webResource = this.identityClient.createWebResource({
602
+ url: audienceUrl,
603
+ method: "POST",
604
+ disableJsonStringifyOnBody: true,
605
+ deserializationMapper: undefined,
606
+ body: qs.stringify({
607
+ response_type: "token",
608
+ grant_type: "client_credentials",
609
+ client_id: this.clientId,
610
+ client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
611
+ client_assertion: clientAssertion,
612
+ scope: typeof scopes === "string" ? scopes : scopes.join(" ")
613
+ }),
614
+ headers: {
615
+ Accept: "application/json",
616
+ "Content-Type": "application/x-www-form-urlencoded"
617
+ },
618
+ abortSignal: options && options.abortSignal
619
+ });
620
+ const tokenResponse = yield this.identityClient.sendTokenRequest(webResource);
621
+ return (tokenResponse && tokenResponse.accessToken) || null;
622
+ });
623
+ }
624
+ }
625
+
626
+ // Copyright (c) Microsoft Corporation.
627
+ // Licensed under the MIT License.
628
+ const BrowserNotSupportedError = new Error("InteractiveBrowserCredential is not supported in Node.js.");
629
+ /**
630
+ * Enables authentication to Azure Active Directory inside of the web browser
631
+ * using the interactive login flow, either via browser redirects or a popup
632
+ * window. This credential is not currently supported in Node.js.
633
+ */
634
+ class InteractiveBrowserCredential {
635
+ constructor(tenantId, clientId, options) {
636
+ throw BrowserNotSupportedError;
637
+ }
638
+ getToken(scopes, options) {
639
+ throw BrowserNotSupportedError;
640
+ }
641
+ }
642
+
643
+ // Copyright (c) Microsoft Corporation.
644
+ /**
645
+ * Enables authentication to Azure Active Directory using a device code
646
+ * that the user can enter into https://microsoft.com/devicelogin.
647
+ */
648
+ class DeviceCodeCredential {
649
+ /**
650
+ * Creates an instance of DeviceCodeCredential with the details needed
651
+ * to initiate the device code authorization flow with Azure Active Directory.
652
+ *
653
+ * @param tenantId The Azure Active Directory tenant (directory) ID or name.
654
+ * @param clientId The client (application) ID of an App Registration in the tenant.
655
+ * @param userPromptCallback A callback function that will be invoked to show
656
+ {@link DeviceCodeDetails} to the user.
657
+ * @param options Options for configuring the client which makes the authentication request.
658
+ */
659
+ constructor(tenantId, clientId, userPromptCallback, options) {
660
+ this.lastTokenResponse = null;
661
+ this.identityClient = new IdentityClient(options);
662
+ this.tenantId = tenantId;
663
+ this.clientId = clientId;
664
+ this.userPromptCallback = userPromptCallback;
665
+ }
666
+ sendDeviceCodeRequest(scope, options) {
667
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
668
+ const webResource = this.identityClient.createWebResource({
669
+ url: `${this.identityClient.authorityHost}/${this.tenantId}/oauth2/v2.0/devicecode`,
670
+ method: "POST",
671
+ disableJsonStringifyOnBody: true,
672
+ deserializationMapper: undefined,
673
+ body: qs.stringify({
674
+ client_id: this.clientId,
675
+ scope
676
+ }),
677
+ headers: {
678
+ Accept: "application/json",
679
+ "Content-Type": "application/x-www-form-urlencoded"
680
+ },
681
+ abortSignal: options && options.abortSignal
682
+ });
683
+ const response = yield this.identityClient.sendRequest(webResource);
684
+ if (!(response.status === 200 || response.status === 201)) {
685
+ throw new AuthenticationError(response.status, response.bodyAsText);
686
+ }
687
+ return response.parsedBody;
688
+ });
689
+ }
690
+ pollForToken(deviceCodeResponse, options) {
691
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
692
+ let tokenResponse = null;
693
+ const webResource = this.identityClient.createWebResource({
694
+ url: `${this.identityClient.authorityHost}/${this.tenantId}/oauth2/v2.0/token`,
695
+ method: "POST",
696
+ disableJsonStringifyOnBody: true,
697
+ deserializationMapper: undefined,
698
+ body: qs.stringify({
699
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code",
700
+ client_id: this.clientId,
701
+ device_code: deviceCodeResponse.device_code
702
+ }),
703
+ headers: {
704
+ Accept: "application/json",
705
+ "Content-Type": "application/x-www-form-urlencoded"
706
+ },
707
+ abortSignal: options && options.abortSignal
708
+ });
709
+ while (tokenResponse === null) {
710
+ try {
711
+ yield coreHttp.delay(deviceCodeResponse.interval * 1000);
712
+ // Check the abort signal before sending the request
713
+ if (options && options.abortSignal && options.abortSignal.aborted) {
714
+ return null;
715
+ }
716
+ tokenResponse = yield this.identityClient.sendTokenRequest(webResource);
717
+ }
718
+ catch (err) {
719
+ if (err instanceof AuthenticationError) {
720
+ switch (err.errorResponse.error) {
721
+ case "authorization_pending":
722
+ break;
723
+ case "authorization_declined":
724
+ return null;
725
+ case "expired_token":
726
+ throw err;
727
+ case "bad_verification_code":
728
+ throw err;
729
+ }
730
+ }
731
+ else {
732
+ throw err;
733
+ }
734
+ }
735
+ }
736
+ return tokenResponse;
737
+ });
738
+ }
739
+ /**
740
+ * Authenticates with Azure Active Directory and returns an {@link AccessToken} if
741
+ * successful. If authentication cannot be performed at this time, this method may
742
+ * return null. If an error occurs during authentication, an {@link AuthenticationError}
743
+ * containing failure details will be thrown.
744
+ *
745
+ * @param scopes The list of scopes for which the token will have access.
746
+ * @param options The options used to configure any requests this
747
+ * TokenCredential implementation might make.
748
+ */
749
+ getToken(scopes, options) {
750
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
751
+ let tokenResponse = null;
752
+ let scopeString = typeof scopes === "string" ? scopes : scopes.join(" ");
753
+ if (scopeString.indexOf("offline_access") < 0) {
754
+ scopeString += " offline_access";
755
+ }
756
+ // Try to use the refresh token first
757
+ if (this.lastTokenResponse && this.lastTokenResponse.refreshToken) {
758
+ tokenResponse = yield this.identityClient.refreshAccessToken(this.tenantId, this.clientId, scopeString, this.lastTokenResponse.refreshToken, undefined, // clientSecret not needed for device code auth
759
+ undefined, options);
760
+ }
761
+ if (tokenResponse === null) {
762
+ const deviceCodeResponse = yield this.sendDeviceCodeRequest(scopeString, options);
763
+ this.userPromptCallback({
764
+ userCode: deviceCodeResponse.user_code,
765
+ verificationUri: deviceCodeResponse.verification_uri,
766
+ message: deviceCodeResponse.message
767
+ });
768
+ tokenResponse = yield this.pollForToken(deviceCodeResponse, options);
769
+ }
770
+ this.lastTokenResponse = tokenResponse;
771
+ return (tokenResponse && tokenResponse.accessToken) || null;
772
+ });
773
+ }
774
+ }
775
+
776
+ // Copyright (c) Microsoft Corporation.
777
+ /**
778
+ * Enables authentication to Azure Active Directory with a user's
779
+ * username and password. This credential requires a high degree of
780
+ * trust so you should only use it when other, more secure credential
781
+ * types can't be used.
782
+ */
783
+ class UsernamePasswordCredential {
784
+ /**
785
+ * Creates an instance of the UsernamePasswordCredential with the details
786
+ * needed to authenticate against Azure Active Directory with a username
787
+ * and password.
788
+ *
789
+ * @param tenantIdOrName The Azure Active Directory tenant (directory) ID or name.
790
+ * @param clientId The client (application) ID of an App Registration in the tenant.
791
+ * @param username The user account's e-mail address (user name).
792
+ * @param password The user account's account password
793
+ * @param options Options for configuring the client which makes the authentication request.
794
+ */
795
+ constructor(tenantIdOrName, clientId, username, password, options) {
796
+ this.identityClient = new IdentityClient(options);
797
+ this.tenantId = tenantIdOrName;
798
+ this.clientId = clientId;
799
+ this.username = username;
800
+ this.password = password;
801
+ }
802
+ /**
803
+ * Authenticates with Azure Active Directory and returns an {@link AccessToken} if
804
+ * successful. If authentication cannot be performed at this time, this method may
805
+ * return null. If an error occurs during authentication, an {@link AuthenticationError}
806
+ * containing failure details will be thrown.
807
+ *
808
+ * @param scopes The list of scopes for which the token will have access.
809
+ * @param options The options used to configure any requests this
810
+ * TokenCredential implementation might make.
811
+ */
812
+ getToken(scopes, options) {
813
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
814
+ const webResource = this.identityClient.createWebResource({
815
+ url: `${this.identityClient.authorityHost}/${this.tenantId}/oauth2/v2.0/token`,
816
+ method: "POST",
817
+ disableJsonStringifyOnBody: true,
818
+ deserializationMapper: undefined,
819
+ body: qs.stringify({
820
+ response_type: "token",
821
+ grant_type: "password",
822
+ client_id: this.clientId,
823
+ username: this.username,
824
+ password: this.password,
825
+ scope: typeof scopes === "string" ? scopes : scopes.join(" ")
826
+ }),
827
+ headers: {
828
+ Accept: "application/json",
829
+ "Content-Type": "application/x-www-form-urlencoded"
830
+ },
831
+ abortSignal: options && options.abortSignal
832
+ });
833
+ const tokenResponse = yield this.identityClient.sendTokenRequest(webResource);
834
+ return (tokenResponse && tokenResponse.accessToken) || null;
835
+ });
569
836
  }
570
837
  }
571
838
 
@@ -580,7 +847,10 @@ exports.ChainedTokenCredential = ChainedTokenCredential;
580
847
  exports.ClientCertificateCredential = ClientCertificateCredential;
581
848
  exports.ClientSecretCredential = ClientSecretCredential;
582
849
  exports.DefaultAzureCredential = DefaultAzureCredential;
850
+ exports.DeviceCodeCredential = DeviceCodeCredential;
583
851
  exports.EnvironmentCredential = EnvironmentCredential;
852
+ exports.InteractiveBrowserCredential = InteractiveBrowserCredential;
584
853
  exports.ManagedIdentityCredential = ManagedIdentityCredential;
854
+ exports.UsernamePasswordCredential = UsernamePasswordCredential;
585
855
  exports.getDefaultAzureCredential = getDefaultAzureCredential;
586
856
  //# sourceMappingURL=index.js.map