@azure/identity 2.0.0-beta.3 → 2.0.0

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

Potentially problematic release.


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

Files changed (149) hide show
  1. package/CHANGELOG.md +232 -6
  2. package/README.md +124 -39
  3. package/dist/index.js +2317 -1596
  4. package/dist/index.js.map +1 -1
  5. package/dist-esm/src/client/identityClient.js +147 -133
  6. package/dist-esm/src/client/identityClient.js.map +1 -1
  7. package/dist-esm/src/constants.js +1 -1
  8. package/dist-esm/src/constants.js.map +1 -1
  9. package/dist-esm/src/credentials/authorizationCodeCredential.browser.js +1 -1
  10. package/dist-esm/src/credentials/authorizationCodeCredential.browser.js.map +1 -1
  11. package/dist-esm/src/credentials/authorizationCodeCredential.js +13 -76
  12. package/dist-esm/src/credentials/authorizationCodeCredential.js.map +1 -1
  13. package/dist-esm/src/credentials/azureApplicationCredential.browser.js +34 -0
  14. package/dist-esm/src/credentials/azureApplicationCredential.browser.js.map +1 -0
  15. package/dist-esm/src/credentials/azureApplicationCredential.js +36 -0
  16. package/dist-esm/src/credentials/azureApplicationCredential.js.map +1 -0
  17. package/dist-esm/src/credentials/azureCliCredential.browser.js +7 -0
  18. package/dist-esm/src/credentials/azureCliCredential.browser.js.map +1 -1
  19. package/dist-esm/src/credentials/azureCliCredential.js +110 -83
  20. package/dist-esm/src/credentials/azureCliCredential.js.map +1 -1
  21. package/dist-esm/src/credentials/azureCliCredentialOptions.js +4 -0
  22. package/dist-esm/src/credentials/azureCliCredentialOptions.js.map +1 -0
  23. package/dist-esm/src/credentials/azurePowerShellCredential.browser.js +3 -1
  24. package/dist-esm/src/credentials/azurePowerShellCredential.browser.js.map +1 -1
  25. package/dist-esm/src/credentials/azurePowerShellCredential.js +93 -83
  26. package/dist-esm/src/credentials/azurePowerShellCredential.js.map +1 -1
  27. package/dist-esm/src/credentials/azurePowerShellCredentialOptions.js +4 -0
  28. package/dist-esm/src/credentials/azurePowerShellCredentialOptions.js.map +1 -0
  29. package/dist-esm/src/credentials/chainedTokenCredential.js +34 -37
  30. package/dist-esm/src/credentials/chainedTokenCredential.js.map +1 -1
  31. package/dist-esm/src/credentials/clientCertificateCredential.browser.js +7 -0
  32. package/dist-esm/src/credentials/clientCertificateCredential.browser.js.map +1 -1
  33. package/dist-esm/src/credentials/clientCertificateCredential.js +24 -23
  34. package/dist-esm/src/credentials/clientCertificateCredential.js.map +1 -1
  35. package/dist-esm/src/credentials/clientCertificateCredentialOptions.js.map +1 -1
  36. package/dist-esm/src/credentials/clientSecretCredential.browser.js +39 -44
  37. package/dist-esm/src/credentials/clientSecretCredential.browser.js.map +1 -1
  38. package/dist-esm/src/credentials/clientSecretCredential.js +9 -11
  39. package/dist-esm/src/credentials/clientSecretCredential.js.map +1 -1
  40. package/dist-esm/src/credentials/clientSecretCredentialOptions.js.map +1 -1
  41. package/dist-esm/src/credentials/credentialPersistenceOptions.js +4 -0
  42. package/dist-esm/src/credentials/credentialPersistenceOptions.js.map +1 -0
  43. package/dist-esm/src/credentials/defaultAzureCredential.browser.js +1 -1
  44. package/dist-esm/src/credentials/defaultAzureCredential.browser.js.map +1 -1
  45. package/dist-esm/src/credentials/defaultAzureCredential.js +50 -27
  46. package/dist-esm/src/credentials/defaultAzureCredential.js.map +1 -1
  47. package/dist-esm/src/credentials/deviceCodeCredential.browser.js +7 -0
  48. package/dist-esm/src/credentials/deviceCodeCredential.browser.js.map +1 -1
  49. package/dist-esm/src/credentials/deviceCodeCredential.js +27 -22
  50. package/dist-esm/src/credentials/deviceCodeCredential.js.map +1 -1
  51. package/dist-esm/src/credentials/deviceCodeCredentialOptions.js.map +1 -1
  52. package/dist-esm/src/credentials/environmentCredential.browser.js +7 -0
  53. package/dist-esm/src/credentials/environmentCredential.browser.js.map +1 -1
  54. package/dist-esm/src/credentials/environmentCredential.js +39 -38
  55. package/dist-esm/src/credentials/environmentCredential.js.map +1 -1
  56. package/dist-esm/src/credentials/interactiveBrowserCredential.browser.js +20 -29
  57. package/dist-esm/src/credentials/interactiveBrowserCredential.browser.js.map +1 -1
  58. package/dist-esm/src/credentials/interactiveBrowserCredential.js +23 -29
  59. package/dist-esm/src/credentials/interactiveBrowserCredential.js.map +1 -1
  60. package/dist-esm/src/credentials/interactiveBrowserCredentialOptions.js.map +1 -1
  61. package/dist-esm/src/credentials/managedIdentityCredential/appServiceMsi2017.js +36 -22
  62. package/dist-esm/src/credentials/managedIdentityCredential/appServiceMsi2017.js.map +1 -1
  63. package/dist-esm/src/credentials/managedIdentityCredential/arcMsi.js +62 -47
  64. package/dist-esm/src/credentials/managedIdentityCredential/arcMsi.js.map +1 -1
  65. package/dist-esm/src/credentials/managedIdentityCredential/cloudShellMsi.js +33 -22
  66. package/dist-esm/src/credentials/managedIdentityCredential/cloudShellMsi.js.map +1 -1
  67. package/dist-esm/src/credentials/managedIdentityCredential/constants.js +2 -1
  68. package/dist-esm/src/credentials/managedIdentityCredential/constants.js.map +1 -1
  69. package/dist-esm/src/credentials/managedIdentityCredential/fabricMsi.js +42 -27
  70. package/dist-esm/src/credentials/managedIdentityCredential/fabricMsi.js.map +1 -1
  71. package/dist-esm/src/credentials/managedIdentityCredential/imdsMsi.js +115 -91
  72. package/dist-esm/src/credentials/managedIdentityCredential/imdsMsi.js.map +1 -1
  73. package/dist-esm/src/credentials/managedIdentityCredential/index.browser.js +3 -6
  74. package/dist-esm/src/credentials/managedIdentityCredential/index.browser.js.map +1 -1
  75. package/dist-esm/src/credentials/managedIdentityCredential/index.js +120 -125
  76. package/dist-esm/src/credentials/managedIdentityCredential/index.js.map +1 -1
  77. package/dist-esm/src/credentials/managedIdentityCredential/models.js.map +1 -1
  78. package/dist-esm/src/credentials/managedIdentityCredential/tokenExchangeMsi.js +82 -0
  79. package/dist-esm/src/credentials/managedIdentityCredential/tokenExchangeMsi.js.map +1 -0
  80. package/dist-esm/src/credentials/managedIdentityCredential/utils.js +14 -8
  81. package/dist-esm/src/credentials/managedIdentityCredential/utils.js.map +1 -1
  82. package/dist-esm/src/credentials/onBehalfOfCredential.browser.js +23 -0
  83. package/dist-esm/src/credentials/onBehalfOfCredential.browser.js.map +1 -0
  84. package/dist-esm/src/credentials/onBehalfOfCredential.js +57 -0
  85. package/dist-esm/src/credentials/onBehalfOfCredential.js.map +1 -0
  86. package/dist-esm/src/credentials/onBehalfOfCredentialOptions.js +4 -0
  87. package/dist-esm/src/credentials/onBehalfOfCredentialOptions.js.map +1 -0
  88. package/dist-esm/src/credentials/usernamePasswordCredential.browser.js +41 -46
  89. package/dist-esm/src/credentials/usernamePasswordCredential.browser.js.map +1 -1
  90. package/dist-esm/src/credentials/usernamePasswordCredential.js +9 -13
  91. package/dist-esm/src/credentials/usernamePasswordCredential.js.map +1 -1
  92. package/dist-esm/src/credentials/usernamePasswordCredentialOptions.js.map +1 -1
  93. package/dist-esm/src/credentials/visualStudioCodeCredential.browser.js +27 -0
  94. package/dist-esm/src/credentials/visualStudioCodeCredential.browser.js.map +1 -0
  95. package/dist-esm/src/credentials/visualStudioCodeCredential.js +183 -0
  96. package/dist-esm/src/credentials/visualStudioCodeCredential.js.map +1 -0
  97. package/dist-esm/src/credentials/visualStudioCodeCredentialPlugin.js +4 -0
  98. package/dist-esm/src/credentials/visualStudioCodeCredentialPlugin.js.map +1 -0
  99. package/dist-esm/src/{client/errors.js → errors.js} +16 -1
  100. package/dist-esm/src/errors.js.map +1 -0
  101. package/dist-esm/src/index.js +4 -2
  102. package/dist-esm/src/index.js.map +1 -1
  103. package/dist-esm/src/msal/browserFlows/browserCommon.js +33 -31
  104. package/dist-esm/src/msal/browserFlows/browserCommon.js.map +1 -1
  105. package/dist-esm/src/msal/browserFlows/msalAuthCode.js +113 -115
  106. package/dist-esm/src/msal/browserFlows/msalAuthCode.js.map +1 -1
  107. package/dist-esm/src/msal/credentials.js.map +1 -1
  108. package/dist-esm/src/msal/flows.js.map +1 -1
  109. package/dist-esm/src/msal/nodeFlows/msalAuthorizationCode.js +41 -0
  110. package/dist-esm/src/msal/nodeFlows/msalAuthorizationCode.js.map +1 -0
  111. package/dist-esm/src/msal/nodeFlows/msalClientCertificate.js +65 -46
  112. package/dist-esm/src/msal/nodeFlows/msalClientCertificate.js.map +1 -1
  113. package/dist-esm/src/msal/nodeFlows/msalClientSecret.js +15 -16
  114. package/dist-esm/src/msal/nodeFlows/msalClientSecret.js.map +1 -1
  115. package/dist-esm/src/msal/nodeFlows/msalDeviceCode.js +20 -22
  116. package/dist-esm/src/msal/nodeFlows/msalDeviceCode.js.map +1 -1
  117. package/dist-esm/src/msal/nodeFlows/msalOnBehalfOf.js +56 -0
  118. package/dist-esm/src/msal/nodeFlows/msalOnBehalfOf.js.map +1 -0
  119. package/dist-esm/src/msal/nodeFlows/msalOpenBrowser.js +44 -33
  120. package/dist-esm/src/msal/nodeFlows/msalOpenBrowser.js.map +1 -1
  121. package/dist-esm/src/msal/nodeFlows/msalUsernamePassword.js +15 -17
  122. package/dist-esm/src/msal/nodeFlows/msalUsernamePassword.js.map +1 -1
  123. package/dist-esm/src/msal/nodeFlows/nodeCommon.js +141 -98
  124. package/dist-esm/src/msal/nodeFlows/nodeCommon.js.map +1 -1
  125. package/dist-esm/src/msal/nodeFlows/tokenCachePersistenceOptions.js +4 -0
  126. package/dist-esm/src/msal/nodeFlows/tokenCachePersistenceOptions.js.map +1 -0
  127. package/dist-esm/src/msal/utils.js +23 -15
  128. package/dist-esm/src/msal/utils.js.map +1 -1
  129. package/dist-esm/src/plugins/consumer.browser.js +7 -0
  130. package/dist-esm/src/plugins/consumer.browser.js.map +1 -0
  131. package/dist-esm/src/plugins/consumer.js +44 -0
  132. package/dist-esm/src/plugins/consumer.js.map +1 -0
  133. package/dist-esm/src/plugins/provider.js +4 -0
  134. package/dist-esm/src/plugins/provider.js.map +1 -0
  135. package/dist-esm/src/regionalAuthority.js +115 -0
  136. package/dist-esm/src/regionalAuthority.js.map +1 -0
  137. package/dist-esm/src/util/tracing.js +24 -27
  138. package/dist-esm/src/util/tracing.js.map +1 -1
  139. package/dist-esm/src/util/validateMultiTenant.browser.js +22 -0
  140. package/dist-esm/src/util/validateMultiTenant.browser.js.map +1 -0
  141. package/dist-esm/src/util/validateMultiTenant.js +29 -0
  142. package/dist-esm/src/util/validateMultiTenant.js.map +1 -0
  143. package/package.json +44 -28
  144. package/types/identity.d.ts +482 -126
  145. package/dist-esm/src/client/errors.js.map +0 -1
  146. package/dist-esm/src/msal/errors.js +0 -22
  147. package/dist-esm/src/msal/errors.js.map +0 -1
  148. package/dist-esm/src/util/authHostEnv.js +0 -13
  149. package/dist-esm/src/util/authHostEnv.js.map +0 -1
@@ -1,44 +1,64 @@
1
1
  // Copyright (c) Microsoft Corporation.
2
2
  // Licensed under the MIT license.
3
- import { __awaiter } from "tslib";
4
- import { delay, RestError } from "@azure/core-http";
3
+ import { delay } from "@azure/core-util";
4
+ import { createHttpHeaders, createPipelineRequest, RestError } from "@azure/core-rest-pipeline";
5
5
  import { SpanStatusCode } from "@azure/core-tracing";
6
- import { AuthenticationError } from "../../client/errors";
7
6
  import { credentialLogger } from "../../util/logging";
8
7
  import { createSpan } from "../../util/tracing";
9
- import { imdsApiVersion, imdsEndpoint } from "./constants";
10
- import { msiGenericGetToken } from "./utils";
11
- const logger = credentialLogger("ManagedIdentityCredential - IMDS");
8
+ import { imdsApiVersion, imdsEndpointPath, imdsHost } from "./constants";
9
+ import { mapScopesToResource, msiGenericGetToken } from "./utils";
10
+ import { AuthenticationError } from "../../errors";
11
+ const msiName = "ManagedIdentityCredential - IMDS";
12
+ const logger = credentialLogger(msiName);
12
13
  function expiresInParser(requestBody) {
13
14
  if (requestBody.expires_on) {
14
15
  // Use the expires_on timestamp if it's available
15
16
  const expires = +requestBody.expires_on * 1000;
16
- logger.info(`IMDS using expires_on: ${expires} (original value: ${requestBody.expires_on})`);
17
+ logger.info(`${msiName}: Using expires_on: ${expires} (original value: ${requestBody.expires_on})`);
17
18
  return expires;
18
19
  }
19
20
  else {
20
21
  // If these aren't possible, use expires_in and calculate a timestamp
21
22
  const expires = Date.now() + requestBody.expires_in * 1000;
22
- logger.info(`IMDS using expires_in: ${expires} (original value: ${requestBody.expires_in})`);
23
+ logger.info(`${msiName}: IMDS using expires_in: ${expires} (original value: ${requestBody.expires_in})`);
23
24
  return expires;
24
25
  }
25
26
  }
26
- function prepareRequestOptions(resource, clientId) {
27
- const queryParameters = {
28
- resource,
29
- "api-version": imdsApiVersion
27
+ function prepareRequestOptions(scopes, clientId, options) {
28
+ var _a;
29
+ const resource = mapScopesToResource(scopes);
30
+ if (!resource) {
31
+ throw new Error(`${msiName}: Multiple scopes are not supported.`);
32
+ }
33
+ const { skipQuery, skipMetadataHeader } = options || {};
34
+ let query = "";
35
+ // Pod Identity will try to process this request even if the Metadata header is missing.
36
+ // We can exclude the request query to ensure no IMDS endpoint tries to process the ping request.
37
+ if (!skipQuery) {
38
+ const queryParameters = {
39
+ resource,
40
+ "api-version": imdsApiVersion
41
+ };
42
+ if (clientId) {
43
+ queryParameters.client_id = clientId;
44
+ }
45
+ const params = new URLSearchParams(queryParameters);
46
+ query = `?${params.toString()}`;
47
+ }
48
+ const url = new URL(imdsEndpointPath, (_a = process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) !== null && _a !== void 0 ? _a : imdsHost);
49
+ const rawHeaders = {
50
+ Accept: "application/json",
51
+ Metadata: "true"
30
52
  };
31
- if (clientId) {
32
- queryParameters.client_id = clientId;
53
+ // Remove the Metadata header to invoke a request error from some IMDS endpoints.
54
+ if (skipMetadataHeader) {
55
+ delete rawHeaders.Metadata;
33
56
  }
34
57
  return {
35
- url: imdsEndpoint,
58
+ // In this case, the `?` should be added in the "query" variable `skipQuery` is not set.
59
+ url: `${url}${query}`,
36
60
  method: "GET",
37
- queryParameters,
38
- headers: {
39
- Accept: "application/json",
40
- Metadata: true
41
- }
61
+ headers: createHttpHeaders(rawHeaders)
42
62
  };
43
63
  }
44
64
  // 800ms -> 1600ms -> 3200ms
@@ -48,84 +68,88 @@ export const imdsMsiRetryConfig = {
48
68
  intervalIncrement: 2
49
69
  };
50
70
  export const imdsMsi = {
51
- isAvailable(identityClient, resource, clientId, getTokenOptions) {
52
- var _a, _b, _c;
53
- return __awaiter(this, void 0, void 0, function* () {
54
- const { span, updatedOptions } = createSpan("ManagedIdentityCredential-pingImdsEndpoint", getTokenOptions);
55
- const request = prepareRequestOptions(resource, clientId);
56
- // This will always be populated, but let's make TypeScript happy
57
- if (request.headers) {
58
- // Remove the Metadata header to invoke a request error from
59
- // IMDS endpoint
60
- delete request.headers.Metadata;
61
- }
62
- request.spanOptions = (_a = updatedOptions === null || updatedOptions === void 0 ? void 0 : updatedOptions.tracingOptions) === null || _a === void 0 ? void 0 : _a.spanOptions;
63
- request.tracingContext = (_b = updatedOptions === null || updatedOptions === void 0 ? void 0 : updatedOptions.tracingOptions) === null || _b === void 0 ? void 0 : _b.tracingContext;
71
+ async isAvailable(scopes, identityClient, clientId, getTokenOptions) {
72
+ var _a, _b;
73
+ const resource = mapScopesToResource(scopes);
74
+ if (!resource) {
75
+ logger.info(`${msiName}: Unavailable. Multiple scopes are not supported.`);
76
+ return false;
77
+ }
78
+ const { span, updatedOptions: options } = createSpan("ManagedIdentityCredential-pingImdsEndpoint", getTokenOptions);
79
+ // if the PodIdenityEndpoint environment variable was set no need to probe the endpoint, it can be assumed to exist
80
+ if (process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) {
81
+ return true;
82
+ }
83
+ const requestOptions = prepareRequestOptions(resource, clientId, {
84
+ skipMetadataHeader: true,
85
+ skipQuery: true
86
+ });
87
+ requestOptions.tracingOptions = options.tracingOptions;
88
+ try {
89
+ // Create a request with a timeout since we expect that
90
+ // not having a "Metadata" header should cause an error to be
91
+ // returned quickly from the endpoint, proving its availability.
92
+ const request = createPipelineRequest(requestOptions);
93
+ request.timeout = (_b = (_a = options.requestOptions) === null || _a === void 0 ? void 0 : _a.timeout) !== null && _b !== void 0 ? _b : 300;
94
+ // This MSI uses the imdsEndpoint to get the token, which only uses http://
95
+ request.allowInsecureConnection = true;
64
96
  try {
65
- // Create a request with a timeout since we expect that
66
- // not having a "Metadata" header should cause an error to be
67
- // returned quickly from the endpoint, proving its availability.
68
- const webResource = identityClient.createWebResource(request);
69
- webResource.timeout = ((_c = updatedOptions === null || updatedOptions === void 0 ? void 0 : updatedOptions.requestOptions) === null || _c === void 0 ? void 0 : _c.timeout) || 500;
70
- try {
71
- logger.info(`Pinging IMDS endpoint`);
72
- yield identityClient.sendRequest(webResource);
73
- }
74
- catch (err) {
75
- if ((err.name === "RestError" && err.code === RestError.REQUEST_SEND_ERROR) ||
76
- err.name === "AbortError" ||
77
- err.code === "ECONNREFUSED" || // connection refused
78
- err.code === "EHOSTDOWN" // host is down
79
- ) {
80
- // If the request failed, or NodeJS was unable to establish a connection,
81
- // or the host was down, we'll assume the IMDS endpoint isn't available.
82
- logger.info(`The Azure IMDS endpoint is unavailable`);
83
- span.setStatus({
84
- code: SpanStatusCode.ERROR,
85
- message: err.message
86
- });
87
- return false;
88
- }
89
- }
90
- // If we received any response, the endpoint is available
91
- logger.info(`The Azure IMDS endpoint is available`);
92
- // IMDS MSI available!
93
- return true;
97
+ logger.info(`${msiName}: Pinging the Azure IMDS endpoint`);
98
+ await identityClient.sendRequest(request);
94
99
  }
95
100
  catch (err) {
96
- // createWebResource failed.
97
- // This error should bubble up to the user.
98
- logger.info(`Error when creating the WebResource for the IMDS endpoint: ${err.message}`);
99
- span.setStatus({
100
- code: SpanStatusCode.ERROR,
101
- message: err.message
102
- });
103
- throw err;
104
- }
105
- finally {
106
- span.end();
101
+ if ((err.name === "RestError" && err.code === RestError.REQUEST_SEND_ERROR) ||
102
+ err.name === "AbortError" ||
103
+ err.code === "ENETUNREACH" || // Network unreachable
104
+ err.code === "ECONNREFUSED" || // connection refused
105
+ err.code === "EHOSTDOWN" // host is down
106
+ ) {
107
+ // If the request failed, or Node.js was unable to establish a connection,
108
+ // or the host was down, we'll assume the IMDS endpoint isn't available.
109
+ logger.info(`${msiName}: The Azure IMDS endpoint is unavailable`);
110
+ span.setStatus({
111
+ code: SpanStatusCode.ERROR,
112
+ message: err.message
113
+ });
114
+ return false;
115
+ }
107
116
  }
108
- });
117
+ // If we received any response, the endpoint is available
118
+ logger.info(`${msiName}: The Azure IMDS endpoint is available`);
119
+ return true;
120
+ }
121
+ catch (err) {
122
+ // createWebResource failed.
123
+ // This error should bubble up to the user.
124
+ logger.info(`${msiName}: Error when creating the WebResource for the Azure IMDS endpoint: ${err.message}`);
125
+ span.setStatus({
126
+ code: SpanStatusCode.ERROR,
127
+ message: err.message
128
+ });
129
+ throw err;
130
+ }
131
+ finally {
132
+ span.end();
133
+ }
109
134
  },
110
- getToken(identityClient, resource, clientId, getTokenOptions = {}) {
111
- return __awaiter(this, void 0, void 0, function* () {
112
- logger.info(`Using the IMDS endpoint coming form the environment variable MSI_ENDPOINT=${process.env.MSI_ENDPOINT}, and using the cloud shell to proceed with the authentication.`);
113
- let nextDelayInMs = imdsMsiRetryConfig.startDelayInMs;
114
- for (let retries = 0; retries < imdsMsiRetryConfig.maxRetries; retries++) {
115
- try {
116
- return yield msiGenericGetToken(identityClient, prepareRequestOptions(resource, clientId), expiresInParser, getTokenOptions);
117
- }
118
- catch (error) {
119
- if (error.statusCode === 404) {
120
- yield delay(nextDelayInMs);
121
- nextDelayInMs *= imdsMsiRetryConfig.intervalIncrement;
122
- continue;
123
- }
124
- throw error;
135
+ async getToken(configuration, getTokenOptions = {}) {
136
+ const { identityClient, scopes, clientId } = configuration;
137
+ logger.info(`${msiName}: Using the Azure IMDS endpoint coming from the environment variable MSI_ENDPOINT=${process.env.MSI_ENDPOINT}, and using the cloud shell to proceed with the authentication.`);
138
+ let nextDelayInMs = imdsMsiRetryConfig.startDelayInMs;
139
+ for (let retries = 0; retries < imdsMsiRetryConfig.maxRetries; retries++) {
140
+ try {
141
+ return await msiGenericGetToken(identityClient, prepareRequestOptions(scopes, clientId), expiresInParser, getTokenOptions);
142
+ }
143
+ catch (error) {
144
+ if (error.statusCode === 404) {
145
+ await delay(nextDelayInMs);
146
+ nextDelayInMs *= imdsMsiRetryConfig.intervalIncrement;
147
+ continue;
125
148
  }
149
+ throw error;
126
150
  }
127
- throw new AuthenticationError(404, `Failed to retrieve IMDS token after ${imdsMsiRetryConfig.maxRetries} retries.`);
128
- });
151
+ }
152
+ throw new AuthenticationError(404, `${msiName}: Failed to retrieve IMDS token after ${imdsMsiRetryConfig.maxRetries} retries.`);
129
153
  }
130
154
  };
131
155
  //# sourceMappingURL=imdsMsi.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"imdsMsi.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/imdsMsi.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport {\n AccessToken,\n delay,\n GetTokenOptions,\n RequestPrepareOptions,\n RestError\n} from \"@azure/core-http\";\nimport { SpanStatusCode } from \"@azure/core-tracing\";\nimport { AuthenticationError } from \"../../client/errors\";\nimport { IdentityClient } from \"../../client/identityClient\";\nimport { credentialLogger } from \"../../util/logging\";\nimport { createSpan } from \"../../util/tracing\";\nimport { imdsApiVersion, imdsEndpoint } from \"./constants\";\nimport { MSI } from \"./models\";\nimport { msiGenericGetToken } from \"./utils\";\n\nconst logger = credentialLogger(\"ManagedIdentityCredential - IMDS\");\n\nfunction expiresInParser(requestBody: any): number {\n if (requestBody.expires_on) {\n // Use the expires_on timestamp if it's available\n const expires = +requestBody.expires_on * 1000;\n logger.info(`IMDS using expires_on: ${expires} (original value: ${requestBody.expires_on})`);\n return expires;\n } else {\n // If these aren't possible, use expires_in and calculate a timestamp\n const expires = Date.now() + requestBody.expires_in * 1000;\n logger.info(`IMDS using expires_in: ${expires} (original value: ${requestBody.expires_in})`);\n return expires;\n }\n}\n\nfunction prepareRequestOptions(resource?: string, clientId?: string): RequestPrepareOptions {\n const queryParameters: any = {\n resource,\n \"api-version\": imdsApiVersion\n };\n\n if (clientId) {\n queryParameters.client_id = clientId;\n }\n\n return {\n url: imdsEndpoint,\n method: \"GET\",\n queryParameters,\n headers: {\n Accept: \"application/json\",\n Metadata: true\n }\n };\n}\n\n// 800ms -> 1600ms -> 3200ms\nexport const imdsMsiRetryConfig = {\n maxRetries: 3,\n startDelayInMs: 800,\n intervalIncrement: 2\n};\n\nexport const imdsMsi: MSI = {\n async isAvailable(\n identityClient: IdentityClient,\n resource: string,\n clientId?: string,\n getTokenOptions?: GetTokenOptions\n ): Promise<boolean> {\n const { span, updatedOptions } = createSpan(\n \"ManagedIdentityCredential-pingImdsEndpoint\",\n getTokenOptions\n );\n\n const request = prepareRequestOptions(resource, clientId);\n\n // This will always be populated, but let's make TypeScript happy\n if (request.headers) {\n // Remove the Metadata header to invoke a request error from\n // IMDS endpoint\n delete request.headers.Metadata;\n }\n\n request.spanOptions = updatedOptions?.tracingOptions?.spanOptions;\n request.tracingContext = updatedOptions?.tracingOptions?.tracingContext;\n\n try {\n // Create a request with a timeout since we expect that\n // not having a \"Metadata\" header should cause an error to be\n // returned quickly from the endpoint, proving its availability.\n const webResource = identityClient.createWebResource(request);\n webResource.timeout = updatedOptions?.requestOptions?.timeout || 500;\n\n try {\n logger.info(`Pinging IMDS endpoint`);\n await identityClient.sendRequest(webResource);\n } catch (err) {\n if (\n (err.name === \"RestError\" && err.code === RestError.REQUEST_SEND_ERROR) ||\n err.name === \"AbortError\" ||\n err.code === \"ECONNREFUSED\" || // connection refused\n err.code === \"EHOSTDOWN\" // host is down\n ) {\n // If the request failed, or NodeJS was unable to establish a connection,\n // or the host was down, we'll assume the IMDS endpoint isn't available.\n logger.info(`The Azure IMDS endpoint is unavailable`);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n return false;\n }\n }\n\n // If we received any response, the endpoint is available\n logger.info(`The Azure IMDS endpoint is available`);\n\n // IMDS MSI available!\n return true;\n } catch (err) {\n // createWebResource failed.\n // This error should bubble up to the user.\n logger.info(`Error when creating the WebResource for the IMDS endpoint: ${err.message}`);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n throw err;\n } finally {\n span.end();\n }\n },\n async getToken(\n identityClient: IdentityClient,\n resource: string,\n clientId?: string,\n getTokenOptions: GetTokenOptions = {}\n ): Promise<AccessToken | null> {\n logger.info(\n `Using the IMDS endpoint coming form the environment variable MSI_ENDPOINT=${process.env.MSI_ENDPOINT}, and using the cloud shell to proceed with the authentication.`\n );\n\n let nextDelayInMs = imdsMsiRetryConfig.startDelayInMs;\n for (let retries = 0; retries < imdsMsiRetryConfig.maxRetries; retries++) {\n try {\n return await msiGenericGetToken(\n identityClient,\n prepareRequestOptions(resource, clientId),\n expiresInParser,\n getTokenOptions\n );\n } catch (error) {\n if (error.statusCode === 404) {\n await delay(nextDelayInMs);\n nextDelayInMs *= imdsMsiRetryConfig.intervalIncrement;\n continue;\n }\n throw error;\n }\n }\n\n throw new AuthenticationError(\n 404,\n `Failed to retrieve IMDS token after ${imdsMsiRetryConfig.maxRetries} retries.`\n );\n }\n};\n"]}
1
+ {"version":3,"file":"imdsMsi.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/imdsMsi.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { delay } from \"@azure/core-util\";\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport {\n createHttpHeaders,\n PipelineRequestOptions,\n createPipelineRequest,\n RestError\n} from \"@azure/core-rest-pipeline\";\nimport { SpanStatusCode } from \"@azure/core-tracing\";\nimport { IdentityClient } from \"../../client/identityClient\";\nimport { credentialLogger } from \"../../util/logging\";\nimport { createSpan } from \"../../util/tracing\";\nimport { imdsApiVersion, imdsEndpointPath, imdsHost } from \"./constants\";\nimport { MSI, MSIConfiguration } from \"./models\";\nimport { mapScopesToResource, msiGenericGetToken } from \"./utils\";\nimport { AuthenticationError } from \"../../errors\";\n\nconst msiName = \"ManagedIdentityCredential - IMDS\";\nconst logger = credentialLogger(msiName);\n\nfunction expiresInParser(requestBody: any): number {\n if (requestBody.expires_on) {\n // Use the expires_on timestamp if it's available\n const expires = +requestBody.expires_on * 1000;\n logger.info(\n `${msiName}: Using expires_on: ${expires} (original value: ${requestBody.expires_on})`\n );\n return expires;\n } else {\n // If these aren't possible, use expires_in and calculate a timestamp\n const expires = Date.now() + requestBody.expires_in * 1000;\n logger.info(\n `${msiName}: IMDS using expires_in: ${expires} (original value: ${requestBody.expires_in})`\n );\n return expires;\n }\n}\n\nfunction prepareRequestOptions(\n scopes: string | string[],\n clientId?: string,\n options?: {\n skipQuery?: boolean;\n skipMetadataHeader?: boolean;\n }\n): PipelineRequestOptions {\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n throw new Error(`${msiName}: Multiple scopes are not supported.`);\n }\n\n const { skipQuery, skipMetadataHeader } = options || {};\n let query = \"\";\n\n // Pod Identity will try to process this request even if the Metadata header is missing.\n // We can exclude the request query to ensure no IMDS endpoint tries to process the ping request.\n if (!skipQuery) {\n const queryParameters: any = {\n resource,\n \"api-version\": imdsApiVersion\n };\n if (clientId) {\n queryParameters.client_id = clientId;\n }\n const params = new URLSearchParams(queryParameters);\n query = `?${params.toString()}`;\n }\n\n const url = new URL(imdsEndpointPath, process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST ?? imdsHost);\n\n const rawHeaders: Record<string, string> = {\n Accept: \"application/json\",\n Metadata: \"true\"\n };\n\n // Remove the Metadata header to invoke a request error from some IMDS endpoints.\n if (skipMetadataHeader) {\n delete rawHeaders.Metadata;\n }\n\n return {\n // In this case, the `?` should be added in the \"query\" variable `skipQuery` is not set.\n url: `${url}${query}`,\n method: \"GET\",\n headers: createHttpHeaders(rawHeaders)\n };\n}\n\n// 800ms -> 1600ms -> 3200ms\nexport const imdsMsiRetryConfig = {\n maxRetries: 3,\n startDelayInMs: 800,\n intervalIncrement: 2\n};\n\nexport const imdsMsi: MSI = {\n async isAvailable(\n scopes: string | string[],\n identityClient: IdentityClient,\n clientId?: string,\n getTokenOptions?: GetTokenOptions\n ): Promise<boolean> {\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n logger.info(`${msiName}: Unavailable. Multiple scopes are not supported.`);\n return false;\n }\n const { span, updatedOptions: options } = createSpan(\n \"ManagedIdentityCredential-pingImdsEndpoint\",\n getTokenOptions\n );\n\n // if the PodIdenityEndpoint environment variable was set no need to probe the endpoint, it can be assumed to exist\n if (process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) {\n return true;\n }\n\n const requestOptions = prepareRequestOptions(resource, clientId, {\n skipMetadataHeader: true,\n skipQuery: true\n });\n requestOptions.tracingOptions = options.tracingOptions;\n\n try {\n // Create a request with a timeout since we expect that\n // not having a \"Metadata\" header should cause an error to be\n // returned quickly from the endpoint, proving its availability.\n const request = createPipelineRequest(requestOptions);\n\n request.timeout = options.requestOptions?.timeout ?? 300;\n\n // This MSI uses the imdsEndpoint to get the token, which only uses http://\n request.allowInsecureConnection = true;\n\n try {\n logger.info(`${msiName}: Pinging the Azure IMDS endpoint`);\n await identityClient.sendRequest(request);\n } catch (err) {\n if (\n (err.name === \"RestError\" && err.code === RestError.REQUEST_SEND_ERROR) ||\n err.name === \"AbortError\" ||\n err.code === \"ENETUNREACH\" || // Network unreachable\n err.code === \"ECONNREFUSED\" || // connection refused\n err.code === \"EHOSTDOWN\" // host is down\n ) {\n // If the request failed, or Node.js was unable to establish a connection,\n // or the host was down, we'll assume the IMDS endpoint isn't available.\n logger.info(`${msiName}: The Azure IMDS endpoint is unavailable`);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n return false;\n }\n }\n\n // If we received any response, the endpoint is available\n logger.info(`${msiName}: The Azure IMDS endpoint is available`);\n return true;\n } catch (err) {\n // createWebResource failed.\n // This error should bubble up to the user.\n logger.info(\n `${msiName}: Error when creating the WebResource for the Azure IMDS endpoint: ${err.message}`\n );\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n throw err;\n } finally {\n span.end();\n }\n },\n async getToken(\n configuration: MSIConfiguration,\n getTokenOptions: GetTokenOptions = {}\n ): Promise<AccessToken | null> {\n const { identityClient, scopes, clientId } = configuration;\n\n logger.info(\n `${msiName}: Using the Azure IMDS endpoint coming from the environment variable MSI_ENDPOINT=${process.env.MSI_ENDPOINT}, and using the cloud shell to proceed with the authentication.`\n );\n\n let nextDelayInMs = imdsMsiRetryConfig.startDelayInMs;\n for (let retries = 0; retries < imdsMsiRetryConfig.maxRetries; retries++) {\n try {\n return await msiGenericGetToken(\n identityClient,\n prepareRequestOptions(scopes, clientId),\n expiresInParser,\n getTokenOptions\n );\n } catch (error) {\n if (error.statusCode === 404) {\n await delay(nextDelayInMs);\n nextDelayInMs *= imdsMsiRetryConfig.intervalIncrement;\n continue;\n }\n throw error;\n }\n }\n\n throw new AuthenticationError(\n 404,\n `${msiName}: Failed to retrieve IMDS token after ${imdsMsiRetryConfig.maxRetries} retries.`\n );\n }\n};\n"]}
@@ -1,6 +1,5 @@
1
1
  // Copyright (c) Microsoft Corporation.
2
2
  // Licensed under the MIT license.
3
- import { __awaiter } from "tslib";
4
3
  import { credentialLogger, formatError } from "../../util/logging";
5
4
  const BrowserNotSupportedError = new Error("ManagedIdentityCredential is not supported in the browser.");
6
5
  const logger = credentialLogger("ManagedIdentityCredential");
@@ -9,11 +8,9 @@ export class ManagedIdentityCredential {
9
8
  logger.info(formatError("", BrowserNotSupportedError));
10
9
  throw BrowserNotSupportedError;
11
10
  }
12
- getToken() {
13
- return __awaiter(this, void 0, void 0, function* () {
14
- logger.getToken.info(formatError("", BrowserNotSupportedError));
15
- throw BrowserNotSupportedError;
16
- });
11
+ async getToken() {
12
+ logger.getToken.info(formatError("", BrowserNotSupportedError));
13
+ throw BrowserNotSupportedError;
17
14
  }
18
15
  }
19
16
  //# sourceMappingURL=index.browser.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.browser.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/index.browser.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;;AAIlC,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEnE,MAAM,wBAAwB,GAAG,IAAI,KAAK,CACxC,4DAA4D,CAC7D,CAAC;AACF,MAAM,MAAM,GAAG,gBAAgB,CAAC,2BAA2B,CAAC,CAAC;AAE7D,MAAM,OAAO,yBAAyB;IAGpC;QACE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC;QACvD,MAAM,wBAAwB,CAAC;IACjC,CAAC;IAEY,QAAQ;;YACnB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC;YAChE,MAAM,wBAAwB,CAAC;QACjC,CAAC;KAAA;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, TokenCredential } from \"@azure/core-http\";\nimport { TokenCredentialOptions } from \"../../client/identityClient\";\nimport { credentialLogger, formatError } from \"../../util/logging\";\n\nconst BrowserNotSupportedError = new Error(\n \"ManagedIdentityCredential is not supported in the browser.\"\n);\nconst logger = credentialLogger(\"ManagedIdentityCredential\");\n\nexport class ManagedIdentityCredential implements TokenCredential {\n constructor(clientId: string, options?: TokenCredentialOptions);\n constructor(options?: TokenCredentialOptions);\n constructor() {\n logger.info(formatError(\"\", BrowserNotSupportedError));\n throw BrowserNotSupportedError;\n }\n\n public async getToken(): Promise<AccessToken | null> {\n logger.getToken.info(formatError(\"\", BrowserNotSupportedError));\n throw BrowserNotSupportedError;\n }\n}\n"]}
1
+ {"version":3,"file":"index.browser.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/index.browser.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAKlC,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEnE,MAAM,wBAAwB,GAAG,IAAI,KAAK,CACxC,4DAA4D,CAC7D,CAAC;AACF,MAAM,MAAM,GAAG,gBAAgB,CAAC,2BAA2B,CAAC,CAAC;AAE7D,MAAM,OAAO,yBAAyB;IAGpC;QACE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC;QACvD,MAAM,wBAAwB,CAAC;IACjC,CAAC;IAEM,KAAK,CAAC,QAAQ;QACnB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC;QAChE,MAAM,wBAAwB,CAAC;IACjC,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, TokenCredential } from \"@azure/core-auth\";\n\nimport { TokenCredentialOptions } from \"../../client/identityClient\";\nimport { credentialLogger, formatError } from \"../../util/logging\";\n\nconst BrowserNotSupportedError = new Error(\n \"ManagedIdentityCredential is not supported in the browser.\"\n);\nconst logger = credentialLogger(\"ManagedIdentityCredential\");\n\nexport class ManagedIdentityCredential implements TokenCredential {\n constructor(clientId: string, options?: TokenCredentialOptions);\n constructor(options?: TokenCredentialOptions);\n constructor() {\n logger.info(formatError(\"\", BrowserNotSupportedError));\n throw BrowserNotSupportedError;\n }\n\n public async getToken(): Promise<AccessToken | null> {\n logger.getToken.info(formatError(\"\", BrowserNotSupportedError));\n throw BrowserNotSupportedError;\n }\n}\n"]}
@@ -1,16 +1,15 @@
1
1
  // Copyright (c) Microsoft Corporation.
2
2
  // Licensed under the MIT license.
3
- import { __awaiter } from "tslib";
4
- import { IdentityClient } from "../../client/identityClient";
5
- import { createSpan } from "../../util/tracing";
6
- import { AuthenticationError, CredentialUnavailableError } from "../../client/errors";
7
3
  import { SpanStatusCode } from "@azure/core-tracing";
4
+ import { IdentityClient } from "../../client/identityClient";
5
+ import { AuthenticationError, CredentialUnavailableError } from "../../errors";
8
6
  import { credentialLogger, formatSuccess, formatError } from "../../util/logging";
9
- import { mapScopesToResource } from "./utils";
7
+ import { appServiceMsi2017 } from "./appServiceMsi2017";
8
+ import { createSpan } from "../../util/tracing";
10
9
  import { cloudShellMsi } from "./cloudShellMsi";
11
10
  import { imdsMsi } from "./imdsMsi";
12
- import { appServiceMsi2017 } from "./appServiceMsi2017";
13
11
  import { arcMsi } from "./arcMsi";
12
+ import { tokenExchangeMsi } from "./tokenExchangeMsi";
14
13
  const logger = credentialLogger("ManagedIdentityCredential");
15
14
  /**
16
15
  * Attempts authentication using a managed identity that has been assigned
@@ -38,140 +37,136 @@ export class ManagedIdentityCredential {
38
37
  this.identityClient = new IdentityClient(clientIdOrOptions);
39
38
  }
40
39
  }
41
- cachedAvailableMSI(resource, clientId, getTokenOptions) {
42
- return __awaiter(this, void 0, void 0, function* () {
43
- if (this.cachedMSI) {
44
- return this.cachedMSI;
45
- }
46
- // "fabricMsi" can't be added yet because our HTTPs pipeline doesn't allow skipping the SSL verification step,
47
- // which is necessary since Service Fabric only provides self-signed certificates on their Identity Endpoint.
48
- const MSIs = [appServiceMsi2017, cloudShellMsi, arcMsi, imdsMsi];
49
- for (const msi of MSIs) {
50
- if (yield msi.isAvailable(this.identityClient, resource, clientId, getTokenOptions)) {
51
- this.cachedMSI = msi;
52
- return msi;
53
- }
40
+ async cachedAvailableMSI(scopes, clientId, getTokenOptions) {
41
+ if (this.cachedMSI) {
42
+ return this.cachedMSI;
43
+ }
44
+ // "fabricMsi" can't be added yet because our HTTPs pipeline doesn't allow skipping the SSL verification step,
45
+ // which is necessary since Service Fabric only provides self-signed certificates on their Identity Endpoint.
46
+ const MSIs = [appServiceMsi2017, cloudShellMsi, arcMsi, tokenExchangeMsi(), imdsMsi];
47
+ for (const msi of MSIs) {
48
+ if (await msi.isAvailable(scopes, this.identityClient, clientId, getTokenOptions)) {
49
+ this.cachedMSI = msi;
50
+ return msi;
54
51
  }
55
- throw new CredentialUnavailableError("ManagedIdentityCredential - No MSI credential available");
56
- });
52
+ }
53
+ throw new CredentialUnavailableError("ManagedIdentityCredential - No MSI credential available");
57
54
  }
58
- authenticateManagedIdentity(scopes, clientId, getTokenOptions) {
59
- return __awaiter(this, void 0, void 0, function* () {
60
- const resource = mapScopesToResource(scopes);
61
- const { span, updatedOptions } = createSpan("ManagedIdentityCredential-authenticateManagedIdentity", getTokenOptions);
62
- try {
63
- // Determining the available MSI, and avoiding checking for other MSIs while the program is running.
64
- const availableMSI = yield this.cachedAvailableMSI(resource, clientId, updatedOptions);
65
- return availableMSI.getToken(this.identityClient, resource, clientId, updatedOptions);
66
- }
67
- catch (err) {
68
- span.setStatus({
69
- code: SpanStatusCode.ERROR,
70
- message: err.message
71
- });
72
- throw err;
73
- }
74
- finally {
75
- span.end();
76
- }
77
- });
55
+ async authenticateManagedIdentity(scopes, clientId, getTokenOptions) {
56
+ const { span, updatedOptions } = createSpan("ManagedIdentityCredential-authenticateManagedIdentity", getTokenOptions);
57
+ try {
58
+ // Determining the available MSI, and avoiding checking for other MSIs while the program is running.
59
+ const availableMSI = await this.cachedAvailableMSI(scopes, clientId, updatedOptions);
60
+ return availableMSI.getToken({
61
+ identityClient: this.identityClient,
62
+ scopes,
63
+ clientId
64
+ }, updatedOptions);
65
+ }
66
+ catch (err) {
67
+ span.setStatus({
68
+ code: SpanStatusCode.ERROR,
69
+ message: err.message
70
+ });
71
+ throw err;
72
+ }
73
+ finally {
74
+ span.end();
75
+ }
78
76
  }
79
77
  /**
80
- * Authenticates with Azure Active Directory and returns an access token if
81
- * successful. If authentication cannot be performed at this time, this method may
82
- * return null. If an error occurs during authentication, an {@link AuthenticationError}
83
- * containing failure details will be thrown.
78
+ * Authenticates with Azure Active Directory and returns an access token if successful.
79
+ * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.
80
+ * If an unexpected error occurs, an {@link AuthenticationError} will be thrown with the details of the failure.
84
81
  *
85
82
  * @param scopes - The list of scopes for which the token will have access.
86
83
  * @param options - The options used to configure any requests this
87
84
  * TokenCredential implementation might make.
88
85
  */
89
- getToken(scopes, options) {
90
- return __awaiter(this, void 0, void 0, function* () {
91
- let result = null;
92
- const { span, updatedOptions } = createSpan("ManagedIdentityCredential-getToken", options);
93
- try {
94
- // isEndpointAvailable can be true, false, or null,
95
- // If it's null, it means we don't yet know whether
96
- // the endpoint is available and need to check for it.
97
- if (this.isEndpointUnavailable !== true) {
98
- result = yield this.authenticateManagedIdentity(scopes, this.clientId, updatedOptions);
99
- if (result === null) {
100
- // If authenticateManagedIdentity returns null,
101
- // it means no MSI endpoints are available.
102
- // If so, we avoid trying to reach to them in future requests.
103
- this.isEndpointUnavailable = true;
104
- // It also means that the endpoint answered with either 200 or 201 (see the sendTokenRequest method),
105
- // yet we had no access token. For this reason, we'll throw once with a specific message:
106
- const error = new CredentialUnavailableError("The managed identity endpoint was reached, yet no tokens were received.");
107
- logger.getToken.info(formatError(scopes, error));
108
- throw error;
109
- }
110
- // Since `authenticateManagedIdentity` didn't throw, and the result was not null,
111
- // We will assume that this endpoint is reachable from this point forward,
112
- // and avoid pinging again to it.
113
- this.isEndpointUnavailable = false;
114
- }
115
- else {
116
- // We've previously determined that the endpoint was unavailable,
117
- // either because it was unreachable or permanently unable to authenticate.
118
- const error = new CredentialUnavailableError("The managed identity endpoint is not currently available");
86
+ async getToken(scopes, options) {
87
+ let result = null;
88
+ const { span, updatedOptions } = createSpan("ManagedIdentityCredential.getToken", options);
89
+ try {
90
+ // isEndpointAvailable can be true, false, or null,
91
+ // If it's null, it means we don't yet know whether
92
+ // the endpoint is available and need to check for it.
93
+ if (this.isEndpointUnavailable !== true) {
94
+ result = await this.authenticateManagedIdentity(scopes, this.clientId, updatedOptions);
95
+ if (result === null) {
96
+ // If authenticateManagedIdentity returns null,
97
+ // it means no MSI endpoints are available.
98
+ // If so, we avoid trying to reach to them in future requests.
99
+ this.isEndpointUnavailable = true;
100
+ // It also means that the endpoint answered with either 200 or 201 (see the sendTokenRequest method),
101
+ // yet we had no access token. For this reason, we'll throw once with a specific message:
102
+ const error = new CredentialUnavailableError("The managed identity endpoint was reached, yet no tokens were received.");
119
103
  logger.getToken.info(formatError(scopes, error));
120
104
  throw error;
121
105
  }
122
- logger.getToken.info(formatSuccess(scopes));
123
- return result;
106
+ // Since `authenticateManagedIdentity` didn't throw, and the result was not null,
107
+ // We will assume that this endpoint is reachable from this point forward,
108
+ // and avoid pinging again to it.
109
+ this.isEndpointUnavailable = false;
124
110
  }
125
- catch (err) {
126
- // CredentialUnavailable errors are expected to reach here.
127
- // We intend them to bubble up, so that DefaultAzureCredential can catch them.
128
- if (err.name === "AuthenticationRequiredError") {
129
- throw err;
130
- }
131
- // Expected errors to reach this point:
132
- // - Errors coming from a method unexpectedly breaking.
133
- // - When identityClient.sendTokenRequest throws, in which case
134
- // if the status code was 400, it means that the endpoint is working,
135
- // but no identity is available.
136
- span.setStatus({
137
- code: SpanStatusCode.ERROR,
138
- message: err.message
139
- });
140
- // If either the network is unreachable,
141
- // we can safely assume the credential is unavailable.
142
- if (err.code === "ENETUNREACH") {
143
- const error = new CredentialUnavailableError("ManagedIdentityCredential is unavailable. Network unreachable.");
144
- logger.getToken.info(formatError(scopes, error));
145
- throw error;
146
- }
147
- // If either the host was unreachable,
148
- // we can safely assume the credential is unavailable.
149
- if (err.code === "EHOSTUNREACH") {
150
- const error = new CredentialUnavailableError("ManagedIdentityCredential is unavailable. No managed identity endpoint found.");
151
- logger.getToken.info(formatError(scopes, error));
152
- throw error;
153
- }
154
- // If err.statusCode has a value of 400, it comes from sendTokenRequest,
155
- // and it means that the endpoint is working, but that no identity is available.
156
- if (err.statusCode === 400) {
157
- throw new CredentialUnavailableError("The managed identity endpoint is indicating there's no available identity");
158
- }
159
- // If the error has no status code, we can assume there was no available identity.
160
- // This will throw silently during any ChainedTokenCredential.
161
- if (err.statusCode === undefined) {
162
- throw new CredentialUnavailableError(`ManagedIdentityCredential authentication failed. Message ${err.message}`);
163
- }
164
- // Any other error should break the chain.
165
- throw new AuthenticationError(err.statusCode, {
166
- error: "ManagedIdentityCredential authentication failed.",
167
- error_description: err.message
168
- });
111
+ else {
112
+ // We've previously determined that the endpoint was unavailable,
113
+ // either because it was unreachable or permanently unable to authenticate.
114
+ const error = new CredentialUnavailableError("The managed identity endpoint is not currently available");
115
+ logger.getToken.info(formatError(scopes, error));
116
+ throw error;
169
117
  }
170
- finally {
171
- // Finally is always called, both if we return and if we throw in the above try/catch.
172
- span.end();
118
+ logger.getToken.info(formatSuccess(scopes));
119
+ return result;
120
+ }
121
+ catch (err) {
122
+ // CredentialUnavailable errors are expected to reach here.
123
+ // We intend them to bubble up, so that DefaultAzureCredential can catch them.
124
+ if (err.name === "AuthenticationRequiredError") {
125
+ throw err;
126
+ }
127
+ // Expected errors to reach this point:
128
+ // - Errors coming from a method unexpectedly breaking.
129
+ // - When identityClient.sendTokenRequest throws, in which case
130
+ // if the status code was 400, it means that the endpoint is working,
131
+ // but no identity is available.
132
+ span.setStatus({
133
+ code: SpanStatusCode.ERROR,
134
+ message: err.message
135
+ });
136
+ // If either the network is unreachable,
137
+ // we can safely assume the credential is unavailable.
138
+ if (err.code === "ENETUNREACH") {
139
+ const error = new CredentialUnavailableError(`ManagedIdentityCredential is unavailable. Network unreachable. Message: ${err.message}`);
140
+ logger.getToken.info(formatError(scopes, error));
141
+ throw error;
142
+ }
143
+ // If either the host was unreachable,
144
+ // we can safely assume the credential is unavailable.
145
+ if (err.code === "EHOSTUNREACH") {
146
+ const error = new CredentialUnavailableError(`ManagedIdentityCredential is unavailable. No managed identity endpoint found. Message: ${err.message}`);
147
+ logger.getToken.info(formatError(scopes, error));
148
+ throw error;
173
149
  }
174
- });
150
+ // If err.statusCode has a value of 400, it comes from sendTokenRequest,
151
+ // and it means that the endpoint is working, but that no identity is available.
152
+ if (err.statusCode === 400) {
153
+ throw new CredentialUnavailableError(`ManagedIdentityCredential: The managed identity endpoint is indicating there's no available identity. Message: ${err.message}`);
154
+ }
155
+ // If the error has no status code, we can assume there was no available identity.
156
+ // This will throw silently during any ChainedTokenCredential.
157
+ if (err.statusCode === undefined) {
158
+ throw new CredentialUnavailableError(`ManagedIdentityCredential authentication failed. Message ${err.message}`);
159
+ }
160
+ // Any other error should break the chain.
161
+ throw new AuthenticationError(err.statusCode, {
162
+ error: "ManagedIdentityCredential authentication failed.",
163
+ error_description: err.message
164
+ });
165
+ }
166
+ finally {
167
+ // Finally is always called, both if we return and if we throw in the above try/catch.
168
+ span.end();
169
+ }
175
170
  }
176
171
  }
177
172
  //# sourceMappingURL=index.js.map