@azure/identity 2.0.0-beta.5 → 2.0.0-beta.6

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 (81) hide show
  1. package/CHANGELOG.md +49 -10
  2. package/README.md +26 -21
  3. package/dist/index.js +461 -211
  4. package/dist/index.js.map +1 -1
  5. package/dist-esm/src/client/errors.js +1 -1
  6. package/dist-esm/src/client/errors.js.map +1 -1
  7. package/dist-esm/src/client/identityClient.js +2 -6
  8. package/dist-esm/src/client/identityClient.js.map +1 -1
  9. package/dist-esm/src/credentials/applicationCredential.js +0 -3
  10. package/dist-esm/src/credentials/applicationCredential.js.map +1 -1
  11. package/dist-esm/src/credentials/authorizationCodeCredential.js +12 -76
  12. package/dist-esm/src/credentials/authorizationCodeCredential.js.map +1 -1
  13. package/dist-esm/src/credentials/chainedTokenCredential.js +4 -3
  14. package/dist-esm/src/credentials/chainedTokenCredential.js.map +1 -1
  15. package/dist-esm/src/credentials/clientCertificateCredential.js +3 -0
  16. package/dist-esm/src/credentials/clientCertificateCredential.js.map +1 -1
  17. package/dist-esm/src/credentials/clientSecretCredential.browser.js +1 -4
  18. package/dist-esm/src/credentials/clientSecretCredential.browser.js.map +1 -1
  19. package/dist-esm/src/credentials/clientSecretCredential.js +3 -0
  20. package/dist-esm/src/credentials/clientSecretCredential.js.map +1 -1
  21. package/dist-esm/src/credentials/credentialPersistenceOptions.js.map +1 -1
  22. package/dist-esm/src/credentials/defaultAzureCredential.js +5 -8
  23. package/dist-esm/src/credentials/defaultAzureCredential.js.map +1 -1
  24. package/dist-esm/src/credentials/managedIdentityCredential/appServiceMsi2017.js +21 -10
  25. package/dist-esm/src/credentials/managedIdentityCredential/appServiceMsi2017.js.map +1 -1
  26. package/dist-esm/src/credentials/managedIdentityCredential/arcMsi.js +23 -12
  27. package/dist-esm/src/credentials/managedIdentityCredential/arcMsi.js.map +1 -1
  28. package/dist-esm/src/credentials/managedIdentityCredential/cloudShellMsi.js +22 -11
  29. package/dist-esm/src/credentials/managedIdentityCredential/cloudShellMsi.js.map +1 -1
  30. package/dist-esm/src/credentials/managedIdentityCredential/fabricMsi.js +19 -7
  31. package/dist-esm/src/credentials/managedIdentityCredential/fabricMsi.js.map +1 -1
  32. package/dist-esm/src/credentials/managedIdentityCredential/imdsMsi.js +29 -20
  33. package/dist-esm/src/credentials/managedIdentityCredential/imdsMsi.js.map +1 -1
  34. package/dist-esm/src/credentials/managedIdentityCredential/index.js +13 -10
  35. package/dist-esm/src/credentials/managedIdentityCredential/index.js.map +1 -1
  36. package/dist-esm/src/credentials/managedIdentityCredential/models.js.map +1 -1
  37. package/dist-esm/src/credentials/managedIdentityCredential/tokenExchangeMsi.js +82 -0
  38. package/dist-esm/src/credentials/managedIdentityCredential/tokenExchangeMsi.js.map +1 -0
  39. package/dist-esm/src/credentials/managedIdentityCredential/utils.js +10 -5
  40. package/dist-esm/src/credentials/managedIdentityCredential/utils.js.map +1 -1
  41. package/dist-esm/src/credentials/onBehalfOfCredential.browser.js +17 -0
  42. package/dist-esm/src/credentials/onBehalfOfCredential.browser.js.map +1 -0
  43. package/dist-esm/src/credentials/onBehalfOfCredential.js +62 -0
  44. package/dist-esm/src/credentials/onBehalfOfCredential.js.map +1 -0
  45. package/dist-esm/src/credentials/{visualStudioCodeCredentialExtension.js → onBehalfOfCredentialOptions.js} +1 -1
  46. package/dist-esm/src/credentials/onBehalfOfCredentialOptions.js.map +1 -0
  47. package/dist-esm/src/credentials/usernamePasswordCredential.browser.js +10 -13
  48. package/dist-esm/src/credentials/usernamePasswordCredential.browser.js.map +1 -1
  49. package/dist-esm/src/credentials/usernamePasswordCredential.js +3 -0
  50. package/dist-esm/src/credentials/usernamePasswordCredential.js.map +1 -1
  51. package/dist-esm/src/credentials/visualStudioCodeCredential.browser.js +1 -1
  52. package/dist-esm/src/credentials/visualStudioCodeCredential.browser.js.map +1 -1
  53. package/dist-esm/src/credentials/visualStudioCodeCredential.js +11 -1
  54. package/dist-esm/src/credentials/visualStudioCodeCredential.js.map +1 -1
  55. package/dist-esm/src/credentials/visualStudioCodeCredentialPlugin.js +4 -0
  56. package/dist-esm/src/credentials/visualStudioCodeCredentialPlugin.js.map +1 -0
  57. package/dist-esm/src/index.js +2 -1
  58. package/dist-esm/src/index.js.map +1 -1
  59. package/dist-esm/src/msal/nodeFlows/msalAuthorizationCode.js +41 -0
  60. package/dist-esm/src/msal/nodeFlows/msalAuthorizationCode.js.map +1 -0
  61. package/dist-esm/src/msal/nodeFlows/msalClientCertificate.js +48 -29
  62. package/dist-esm/src/msal/nodeFlows/msalClientCertificate.js.map +1 -1
  63. package/dist-esm/src/msal/nodeFlows/msalClientSecret.js.map +1 -1
  64. package/dist-esm/src/msal/nodeFlows/msalOnBehalfOf.js +56 -0
  65. package/dist-esm/src/msal/nodeFlows/msalOnBehalfOf.js.map +1 -0
  66. package/dist-esm/src/msal/nodeFlows/nodeCommon.js +6 -1
  67. package/dist-esm/src/msal/nodeFlows/nodeCommon.js.map +1 -1
  68. package/dist-esm/src/msal/nodeFlows/tokenCachePersistenceOptions.js.map +1 -1
  69. package/dist-esm/src/plugins/consumer.browser.js +7 -0
  70. package/dist-esm/src/plugins/consumer.browser.js.map +1 -0
  71. package/dist-esm/src/{extensions → plugins}/consumer.js +12 -12
  72. package/dist-esm/src/plugins/consumer.js.map +1 -0
  73. package/dist-esm/src/{extensions → plugins}/provider.js +0 -0
  74. package/dist-esm/src/plugins/provider.js.map +1 -0
  75. package/package.json +10 -12
  76. package/types/identity.d.ts +126 -41
  77. package/dist-esm/src/credentials/visualStudioCodeCredentialExtension.js.map +0 -1
  78. package/dist-esm/src/extensions/consumer.browser.js +0 -7
  79. package/dist-esm/src/extensions/consumer.browser.js.map +0 -1
  80. package/dist-esm/src/extensions/consumer.js.map +0 -1
  81. package/dist-esm/src/extensions/provider.js.map +0 -1
@@ -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 qs from \"qs\";\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 } from \"./models\";\nimport { msiGenericGetToken } from \"./utils\";\nimport { AuthenticationError } from \"../../client/errors\";\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): PipelineRequestOptions {\n const queryParameters: any = {\n resource,\n \"api-version\": imdsApiVersion\n };\n\n if (clientId) {\n queryParameters.client_id = clientId;\n }\n\n const query = qs.stringify(queryParameters);\n const url = new URL(imdsEndpointPath, process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST ?? imdsHost);\n\n return {\n url: `${url}?${query}`,\n method: \"GET\",\n headers: createHttpHeaders({\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: 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\n // This will always be populated, but let's make TypeScript happy\n if (requestOptions.headers) {\n // Remove the Metadata header to invoke a request error from\n // IMDS endpoint\n requestOptions.headers.delete(\"Metadata\");\n }\n\n requestOptions.tracingOptions = {\n spanOptions: options.tracingOptions && options.tracingOptions.spanOptions,\n tracingContext: options.tracingOptions && options.tracingOptions.tracingContext\n };\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(`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 === \"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(`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 return true;\n } catch (err) {\n // createWebResource failed.\n // This error should bubble up to the user.\n logger.info(\n `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 identityClient: IdentityClient,\n resource: string,\n clientId?: string,\n getTokenOptions: GetTokenOptions = {}\n ): Promise<AccessToken | null> {\n logger.info(\n `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(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 \"../../client/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}: IMDS 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): PipelineRequestOptions {\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n throw new Error(`${msiName}: Multiple scopes are not supported.`);\n }\n\n const queryParameters: any = {\n resource,\n \"api-version\": imdsApiVersion\n };\n\n if (clientId) {\n queryParameters.client_id = clientId;\n }\n\n const params = new URLSearchParams(queryParameters);\n const query = params.toString();\n const url = new URL(imdsEndpointPath, process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST ?? imdsHost);\n\n return {\n url: `${url}?${query}`,\n method: \"GET\",\n headers: createHttpHeaders({\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 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\n // This will always be populated, but let's make TypeScript happy\n if (requestOptions.headers) {\n // Remove the Metadata header to invoke a request error from\n // IMDS endpoint\n requestOptions.headers.delete(\"Metadata\");\n }\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"]}
@@ -6,10 +6,10 @@ import { AuthenticationError, CredentialUnavailableError } from "../../client/er
6
6
  import { credentialLogger, formatSuccess, formatError } from "../../util/logging";
7
7
  import { appServiceMsi2017 } from "./appServiceMsi2017";
8
8
  import { createSpan } from "../../util/tracing";
9
- import { mapScopesToResource } from "./utils";
10
9
  import { cloudShellMsi } from "./cloudShellMsi";
11
10
  import { imdsMsi } from "./imdsMsi";
12
11
  import { arcMsi } from "./arcMsi";
12
+ import { tokenExchangeMsi } from "./tokenExchangeMsi";
13
13
  const logger = credentialLogger("ManagedIdentityCredential");
14
14
  /**
15
15
  * Attempts authentication using a managed identity that has been assigned
@@ -37,15 +37,15 @@ export class ManagedIdentityCredential {
37
37
  this.identityClient = new IdentityClient(clientIdOrOptions);
38
38
  }
39
39
  }
40
- async cachedAvailableMSI(resource, clientId, getTokenOptions) {
40
+ async cachedAvailableMSI(scopes, clientId, getTokenOptions) {
41
41
  if (this.cachedMSI) {
42
42
  return this.cachedMSI;
43
43
  }
44
44
  // "fabricMsi" can't be added yet because our HTTPs pipeline doesn't allow skipping the SSL verification step,
45
45
  // which is necessary since Service Fabric only provides self-signed certificates on their Identity Endpoint.
46
- const MSIs = [appServiceMsi2017, cloudShellMsi, arcMsi, imdsMsi];
46
+ const MSIs = [appServiceMsi2017, cloudShellMsi, arcMsi, tokenExchangeMsi(), imdsMsi];
47
47
  for (const msi of MSIs) {
48
- if (await msi.isAvailable(this.identityClient, resource, clientId, getTokenOptions)) {
48
+ if (await msi.isAvailable(scopes, this.identityClient, clientId, getTokenOptions)) {
49
49
  this.cachedMSI = msi;
50
50
  return msi;
51
51
  }
@@ -53,12 +53,15 @@ export class ManagedIdentityCredential {
53
53
  throw new CredentialUnavailableError("ManagedIdentityCredential - No MSI credential available");
54
54
  }
55
55
  async authenticateManagedIdentity(scopes, clientId, getTokenOptions) {
56
- const resource = mapScopesToResource(scopes);
57
56
  const { span, updatedOptions } = createSpan("ManagedIdentityCredential-authenticateManagedIdentity", getTokenOptions);
58
57
  try {
59
58
  // Determining the available MSI, and avoiding checking for other MSIs while the program is running.
60
- const availableMSI = await this.cachedAvailableMSI(resource, clientId, updatedOptions);
61
- return availableMSI.getToken(this.identityClient, resource, clientId, updatedOptions);
59
+ const availableMSI = await this.cachedAvailableMSI(scopes, clientId, updatedOptions);
60
+ return availableMSI.getToken({
61
+ identityClient: this.identityClient,
62
+ scopes,
63
+ clientId
64
+ }, updatedOptions);
62
65
  }
63
66
  catch (err) {
64
67
  span.setStatus({
@@ -133,21 +136,21 @@ export class ManagedIdentityCredential {
133
136
  // If either the network is unreachable,
134
137
  // we can safely assume the credential is unavailable.
135
138
  if (err.code === "ENETUNREACH") {
136
- const error = new CredentialUnavailableError("ManagedIdentityCredential is unavailable. Network unreachable.");
139
+ const error = new CredentialUnavailableError(`ManagedIdentityCredential is unavailable. Network unreachable. Message: ${err.message}`);
137
140
  logger.getToken.info(formatError(scopes, error));
138
141
  throw error;
139
142
  }
140
143
  // If either the host was unreachable,
141
144
  // we can safely assume the credential is unavailable.
142
145
  if (err.code === "EHOSTUNREACH") {
143
- const error = new CredentialUnavailableError("ManagedIdentityCredential is unavailable. No managed identity endpoint found.");
146
+ const error = new CredentialUnavailableError(`ManagedIdentityCredential is unavailable. No managed identity endpoint found. Message: ${err.message}`);
144
147
  logger.getToken.info(formatError(scopes, error));
145
148
  throw error;
146
149
  }
147
150
  // If err.statusCode has a value of 400, it comes from sendTokenRequest,
148
151
  // and it means that the endpoint is working, but that no identity is available.
149
152
  if (err.statusCode === 400) {
150
- throw new CredentialUnavailableError("The managed identity endpoint is indicating there's no available identity");
153
+ throw new CredentialUnavailableError(`ManagedIdentityCredential: The managed identity endpoint is indicating there's no available identity. Message: ${err.message}`);
151
154
  }
152
155
  // If the error has no status code, we can assume there was no available identity.
153
156
  // This will throw silently during any ChainedTokenCredential.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/index.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { SpanStatusCode } from \"@azure/core-tracing\";\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\n\nimport { IdentityClient, TokenCredentialOptions } from \"../../client/identityClient\";\nimport { AuthenticationError, CredentialUnavailableError } from \"../../client/errors\";\nimport { credentialLogger, formatSuccess, formatError } from \"../../util/logging\";\nimport { appServiceMsi2017 } from \"./appServiceMsi2017\";\nimport { createSpan } from \"../../util/tracing\";\nimport { mapScopesToResource } from \"./utils\";\nimport { cloudShellMsi } from \"./cloudShellMsi\";\nimport { imdsMsi } from \"./imdsMsi\";\nimport { MSI } from \"./models\";\nimport { arcMsi } from \"./arcMsi\";\n\nconst logger = credentialLogger(\"ManagedIdentityCredential\");\n\n/**\n * Attempts authentication using a managed identity that has been assigned\n * to the deployment environment. This authentication type works in Azure VMs,\n * App Service and Azure Functions applications, and inside of Azure Cloud Shell.\n *\n * More information about configuring managed identities can be found here:\n *\n * https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview\n */\nexport class ManagedIdentityCredential implements TokenCredential {\n private identityClient: IdentityClient;\n private clientId: string | undefined;\n private isEndpointUnavailable: boolean | null = null;\n\n /**\n * Creates an instance of ManagedIdentityCredential with the client ID of a\n * user-assigned identity, or app registration (when working with AKS pod-identity).\n *\n * @param clientId - The client ID of the user-assigned identity, or app registration (when working with AKS pod-identity).\n * @param options - Options for configuring the client which makes the access token request.\n */\n constructor(clientId: string, options?: TokenCredentialOptions);\n /**\n * Creates an instance of ManagedIdentityCredential\n *\n * @param options - Options for configuring the client which makes the access token request.\n */\n constructor(options?: TokenCredentialOptions);\n /**\n * @internal\n * @hidden\n */\n constructor(\n clientIdOrOptions: string | TokenCredentialOptions | undefined,\n options?: TokenCredentialOptions\n ) {\n if (typeof clientIdOrOptions === \"string\") {\n // clientId, options constructor\n this.clientId = clientIdOrOptions;\n this.identityClient = new IdentityClient(options);\n } else {\n // options only constructor\n this.identityClient = new IdentityClient(clientIdOrOptions);\n }\n }\n\n private cachedMSI: MSI | undefined;\n\n private async cachedAvailableMSI(\n resource: string,\n clientId?: string,\n getTokenOptions?: GetTokenOptions\n ): Promise<MSI> {\n if (this.cachedMSI) {\n return this.cachedMSI;\n }\n\n // \"fabricMsi\" can't be added yet because our HTTPs pipeline doesn't allow skipping the SSL verification step,\n // which is necessary since Service Fabric only provides self-signed certificates on their Identity Endpoint.\n const MSIs = [appServiceMsi2017, cloudShellMsi, arcMsi, imdsMsi];\n\n for (const msi of MSIs) {\n if (await msi.isAvailable(this.identityClient, resource, clientId, getTokenOptions)) {\n this.cachedMSI = msi;\n return msi;\n }\n }\n\n throw new CredentialUnavailableError(\"ManagedIdentityCredential - No MSI credential available\");\n }\n\n private async authenticateManagedIdentity(\n scopes: string | string[],\n clientId?: string,\n getTokenOptions?: GetTokenOptions\n ): Promise<AccessToken | null> {\n const resource = mapScopesToResource(scopes);\n const { span, updatedOptions } = createSpan(\n \"ManagedIdentityCredential-authenticateManagedIdentity\",\n getTokenOptions\n );\n\n try {\n // Determining the available MSI, and avoiding checking for other MSIs while the program is running.\n const availableMSI = await this.cachedAvailableMSI(resource, clientId, updatedOptions);\n\n return availableMSI.getToken(this.identityClient, resource, clientId, updatedOptions);\n } catch (err) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n throw err;\n } finally {\n span.end();\n }\n }\n\n /**\n * Authenticates with Azure Active Directory and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.\n * If an unexpected error occurs, an {@link AuthenticationError} will be thrown with the details of the failure.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n public async getToken(\n scopes: string | string[],\n options?: GetTokenOptions\n ): Promise<AccessToken> {\n let result: AccessToken | null = null;\n\n const { span, updatedOptions } = createSpan(\"ManagedIdentityCredential-getToken\", options);\n\n try {\n // isEndpointAvailable can be true, false, or null,\n // If it's null, it means we don't yet know whether\n // the endpoint is available and need to check for it.\n if (this.isEndpointUnavailable !== true) {\n result = await this.authenticateManagedIdentity(scopes, this.clientId, updatedOptions);\n\n if (result === null) {\n // If authenticateManagedIdentity returns null,\n // it means no MSI endpoints are available.\n // If so, we avoid trying to reach to them in future requests.\n this.isEndpointUnavailable = true;\n\n // It also means that the endpoint answered with either 200 or 201 (see the sendTokenRequest method),\n // yet we had no access token. For this reason, we'll throw once with a specific message:\n const error = new CredentialUnavailableError(\n \"The managed identity endpoint was reached, yet no tokens were received.\"\n );\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n\n // Since `authenticateManagedIdentity` didn't throw, and the result was not null,\n // We will assume that this endpoint is reachable from this point forward,\n // and avoid pinging again to it.\n this.isEndpointUnavailable = false;\n } else {\n // We've previously determined that the endpoint was unavailable,\n // either because it was unreachable or permanently unable to authenticate.\n const error = new CredentialUnavailableError(\n \"The managed identity endpoint is not currently available\"\n );\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n\n logger.getToken.info(formatSuccess(scopes));\n return result;\n } catch (err) {\n // CredentialUnavailable errors are expected to reach here.\n // We intend them to bubble up, so that DefaultAzureCredential can catch them.\n if (err.name === \"AuthenticationRequiredError\") {\n throw err;\n }\n\n // Expected errors to reach this point:\n // - Errors coming from a method unexpectedly breaking.\n // - When identityClient.sendTokenRequest throws, in which case\n // if the status code was 400, it means that the endpoint is working,\n // but no identity is available.\n\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n\n // If either the network is unreachable,\n // we can safely assume the credential is unavailable.\n if (err.code === \"ENETUNREACH\") {\n const error = new CredentialUnavailableError(\n \"ManagedIdentityCredential is unavailable. Network unreachable.\"\n );\n\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n\n // If either the host was unreachable,\n // we can safely assume the credential is unavailable.\n if (err.code === \"EHOSTUNREACH\") {\n const error = new CredentialUnavailableError(\n \"ManagedIdentityCredential is unavailable. No managed identity endpoint found.\"\n );\n\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n\n // If err.statusCode has a value of 400, it comes from sendTokenRequest,\n // and it means that the endpoint is working, but that no identity is available.\n if (err.statusCode === 400) {\n throw new CredentialUnavailableError(\n \"The managed identity endpoint is indicating there's no available identity\"\n );\n }\n\n // If the error has no status code, we can assume there was no available identity.\n // This will throw silently during any ChainedTokenCredential.\n if (err.statusCode === undefined) {\n throw new CredentialUnavailableError(\n `ManagedIdentityCredential authentication failed. Message ${err.message}`\n );\n }\n\n // Any other error should break the chain.\n throw new AuthenticationError(err.statusCode, {\n error: \"ManagedIdentityCredential authentication failed.\",\n error_description: err.message\n });\n } finally {\n // Finally is always called, both if we return and if we throw in the above try/catch.\n span.end();\n }\n }\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/index.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { SpanStatusCode } from \"@azure/core-tracing\";\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\n\nimport { IdentityClient, TokenCredentialOptions } from \"../../client/identityClient\";\nimport { AuthenticationError, CredentialUnavailableError } from \"../../client/errors\";\nimport { credentialLogger, formatSuccess, formatError } from \"../../util/logging\";\nimport { appServiceMsi2017 } from \"./appServiceMsi2017\";\nimport { createSpan } from \"../../util/tracing\";\nimport { cloudShellMsi } from \"./cloudShellMsi\";\nimport { imdsMsi } from \"./imdsMsi\";\nimport { MSI } from \"./models\";\nimport { arcMsi } from \"./arcMsi\";\nimport { tokenExchangeMsi } from \"./tokenExchangeMsi\";\n\nconst logger = credentialLogger(\"ManagedIdentityCredential\");\n\n/**\n * Attempts authentication using a managed identity that has been assigned\n * to the deployment environment. This authentication type works in Azure VMs,\n * App Service and Azure Functions applications, and inside of Azure Cloud Shell.\n *\n * More information about configuring managed identities can be found here:\n *\n * https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview\n */\nexport class ManagedIdentityCredential implements TokenCredential {\n private identityClient: IdentityClient;\n private clientId: string | undefined;\n private isEndpointUnavailable: boolean | null = null;\n\n /**\n * Creates an instance of ManagedIdentityCredential with the client ID of a\n * user-assigned identity, or app registration (when working with AKS pod-identity).\n *\n * @param clientId - The client ID of the user-assigned identity, or app registration (when working with AKS pod-identity).\n * @param options - Options for configuring the client which makes the access token request.\n */\n constructor(clientId: string, options?: TokenCredentialOptions);\n /**\n * Creates an instance of ManagedIdentityCredential\n *\n * @param options - Options for configuring the client which makes the access token request.\n */\n constructor(options?: TokenCredentialOptions);\n /**\n * @internal\n * @hidden\n */\n constructor(\n clientIdOrOptions: string | TokenCredentialOptions | undefined,\n options?: TokenCredentialOptions\n ) {\n if (typeof clientIdOrOptions === \"string\") {\n // clientId, options constructor\n this.clientId = clientIdOrOptions;\n this.identityClient = new IdentityClient(options);\n } else {\n // options only constructor\n this.identityClient = new IdentityClient(clientIdOrOptions);\n }\n }\n\n private cachedMSI: MSI | undefined;\n\n private async cachedAvailableMSI(\n scopes: string | string[],\n clientId?: string,\n getTokenOptions?: GetTokenOptions\n ): Promise<MSI> {\n if (this.cachedMSI) {\n return this.cachedMSI;\n }\n\n // \"fabricMsi\" can't be added yet because our HTTPs pipeline doesn't allow skipping the SSL verification step,\n // which is necessary since Service Fabric only provides self-signed certificates on their Identity Endpoint.\n const MSIs = [appServiceMsi2017, cloudShellMsi, arcMsi, tokenExchangeMsi(), imdsMsi];\n\n for (const msi of MSIs) {\n if (await msi.isAvailable(scopes, this.identityClient, clientId, getTokenOptions)) {\n this.cachedMSI = msi;\n return msi;\n }\n }\n\n throw new CredentialUnavailableError(\"ManagedIdentityCredential - No MSI credential available\");\n }\n\n private async authenticateManagedIdentity(\n scopes: string | string[],\n clientId?: string,\n getTokenOptions?: GetTokenOptions\n ): Promise<AccessToken | null> {\n const { span, updatedOptions } = createSpan(\n \"ManagedIdentityCredential-authenticateManagedIdentity\",\n getTokenOptions\n );\n\n try {\n // Determining the available MSI, and avoiding checking for other MSIs while the program is running.\n const availableMSI = await this.cachedAvailableMSI(scopes, clientId, updatedOptions);\n\n return availableMSI.getToken(\n {\n identityClient: this.identityClient,\n scopes,\n clientId\n },\n updatedOptions\n );\n } catch (err) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n throw err;\n } finally {\n span.end();\n }\n }\n\n /**\n * Authenticates with Azure Active Directory and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.\n * If an unexpected error occurs, an {@link AuthenticationError} will be thrown with the details of the failure.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n public async getToken(\n scopes: string | string[],\n options?: GetTokenOptions\n ): Promise<AccessToken> {\n let result: AccessToken | null = null;\n\n const { span, updatedOptions } = createSpan(\"ManagedIdentityCredential-getToken\", options);\n\n try {\n // isEndpointAvailable can be true, false, or null,\n // If it's null, it means we don't yet know whether\n // the endpoint is available and need to check for it.\n if (this.isEndpointUnavailable !== true) {\n result = await this.authenticateManagedIdentity(scopes, this.clientId, updatedOptions);\n\n if (result === null) {\n // If authenticateManagedIdentity returns null,\n // it means no MSI endpoints are available.\n // If so, we avoid trying to reach to them in future requests.\n this.isEndpointUnavailable = true;\n\n // It also means that the endpoint answered with either 200 or 201 (see the sendTokenRequest method),\n // yet we had no access token. For this reason, we'll throw once with a specific message:\n const error = new CredentialUnavailableError(\n \"The managed identity endpoint was reached, yet no tokens were received.\"\n );\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n\n // Since `authenticateManagedIdentity` didn't throw, and the result was not null,\n // We will assume that this endpoint is reachable from this point forward,\n // and avoid pinging again to it.\n this.isEndpointUnavailable = false;\n } else {\n // We've previously determined that the endpoint was unavailable,\n // either because it was unreachable or permanently unable to authenticate.\n const error = new CredentialUnavailableError(\n \"The managed identity endpoint is not currently available\"\n );\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n\n logger.getToken.info(formatSuccess(scopes));\n return result;\n } catch (err) {\n // CredentialUnavailable errors are expected to reach here.\n // We intend them to bubble up, so that DefaultAzureCredential can catch them.\n if (err.name === \"AuthenticationRequiredError\") {\n throw err;\n }\n\n // Expected errors to reach this point:\n // - Errors coming from a method unexpectedly breaking.\n // - When identityClient.sendTokenRequest throws, in which case\n // if the status code was 400, it means that the endpoint is working,\n // but no identity is available.\n\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n\n // If either the network is unreachable,\n // we can safely assume the credential is unavailable.\n if (err.code === \"ENETUNREACH\") {\n const error = new CredentialUnavailableError(\n `ManagedIdentityCredential is unavailable. Network unreachable. Message: ${err.message}`\n );\n\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n\n // If either the host was unreachable,\n // we can safely assume the credential is unavailable.\n if (err.code === \"EHOSTUNREACH\") {\n const error = new CredentialUnavailableError(\n `ManagedIdentityCredential is unavailable. No managed identity endpoint found. Message: ${err.message}`\n );\n\n logger.getToken.info(formatError(scopes, error));\n throw error;\n }\n\n // If err.statusCode has a value of 400, it comes from sendTokenRequest,\n // and it means that the endpoint is working, but that no identity is available.\n if (err.statusCode === 400) {\n throw new CredentialUnavailableError(\n `ManagedIdentityCredential: The managed identity endpoint is indicating there's no available identity. Message: ${err.message}`\n );\n }\n\n // If the error has no status code, we can assume there was no available identity.\n // This will throw silently during any ChainedTokenCredential.\n if (err.statusCode === undefined) {\n throw new CredentialUnavailableError(\n `ManagedIdentityCredential authentication failed. Message ${err.message}`\n );\n }\n\n // Any other error should break the chain.\n throw new AuthenticationError(err.statusCode, {\n error: \"ManagedIdentityCredential authentication failed.\",\n error_description: err.message\n });\n } finally {\n // Finally is always called, both if we return and if we throw in the above try/catch.\n span.end();\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"models.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/models.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { IdentityClient } from \"../../client/identityClient\";\n\nexport type MSIExpiresInParser = (requestBody: any) => number;\n\nexport interface MSI {\n isAvailable(\n identityClient?: IdentityClient,\n resource?: string,\n clientId?: string,\n getTokenOptions?: GetTokenOptions\n ): Promise<boolean>;\n getToken(\n identityClient: IdentityClient,\n resource: string,\n clientId?: string,\n getTokenOptions?: GetTokenOptions\n ): Promise<AccessToken | null>;\n}\n"]}
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/models.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { IdentityClient } from \"../../client/identityClient\";\n\n/**\n * @internal\n */\nexport type MSIExpiresInParser = (requestBody: any) => number;\n\n/**\n * @internal\n */\nexport interface MSIConfiguration {\n identityClient: IdentityClient;\n scopes: string | string[];\n clientId?: string;\n}\n\n/**\n * @internal\n */\nexport interface MSI {\n isAvailable(\n scopes: string | string[],\n identityClient?: IdentityClient,\n clientId?: string,\n getTokenOptions?: GetTokenOptions\n ): Promise<boolean>;\n getToken(\n configuration: MSIConfiguration,\n getTokenOptions?: GetTokenOptions\n ): Promise<AccessToken | null>;\n}\n"]}
@@ -0,0 +1,82 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT license.
3
+ import fs from "fs";
4
+ import { createHttpHeaders } from "@azure/core-rest-pipeline";
5
+ import { promisify } from "util";
6
+ import { credentialLogger } from "../../util/logging";
7
+ import { msiGenericGetToken } from "./utils";
8
+ import { DefaultAuthorityHost } from "../../constants";
9
+ const msiName = "ManagedIdentityCredential - Token Exchange";
10
+ const logger = credentialLogger(msiName);
11
+ const readFileAsync = promisify(fs.readFile);
12
+ function expiresInParser(requestBody) {
13
+ // Parses a string representation of the seconds since epoch into a number value
14
+ return Number(requestBody.expires_on);
15
+ }
16
+ function prepareRequestOptions(scopes, clientAssertion, clientId) {
17
+ var _a;
18
+ const bodyParams = {
19
+ scope: Array.isArray(scopes) ? scopes.join(" ") : scopes,
20
+ client_assertion: clientAssertion,
21
+ client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
22
+ client_id: clientId,
23
+ grant_type: "client_credentials"
24
+ };
25
+ const urlParams = new URLSearchParams(bodyParams);
26
+ const url = new URL(`${process.env.AZURE_TENANT_ID}/oauth2/v2.0/token`, (_a = process.env.AZURE_AUTHORITY_HOST) !== null && _a !== void 0 ? _a : DefaultAuthorityHost);
27
+ return {
28
+ url: url.toString(),
29
+ method: "POST",
30
+ body: urlParams.toString(),
31
+ headers: createHttpHeaders({
32
+ Accept: "application/json"
33
+ })
34
+ };
35
+ }
36
+ export function tokenExchangeMsi() {
37
+ const azureFederatedTokenFilePath = process.env.AZURE_FEDERATED_TOKEN_FILE;
38
+ let azureFederatedTokenFileContent = undefined;
39
+ let cacheDate = undefined;
40
+ // Only reads from the assertion file once every 5 minutes
41
+ async function readAssertion() {
42
+ // Cached assertions expire after 5 minutes
43
+ if (cacheDate !== undefined && Date.now() - cacheDate >= 1000 * 60 * 5) {
44
+ azureFederatedTokenFileContent = undefined;
45
+ }
46
+ if (!azureFederatedTokenFileContent) {
47
+ const file = await readFileAsync(azureFederatedTokenFilePath, "utf8");
48
+ const value = file.trim();
49
+ if (!value) {
50
+ throw new Error(`No content on the file ${azureFederatedTokenFilePath}, indicated by the environment variable AZURE_FEDERATED_TOKEN_FILE`);
51
+ }
52
+ else {
53
+ azureFederatedTokenFileContent = value;
54
+ cacheDate = Date.now();
55
+ }
56
+ }
57
+ return azureFederatedTokenFileContent;
58
+ }
59
+ return {
60
+ async isAvailable(_scopes, _identityClient, clientId) {
61
+ const env = process.env;
62
+ const result = Boolean((clientId || env.AZURE_CLIENT_ID) && env.AZURE_TENANT_ID && azureFederatedTokenFilePath);
63
+ if (!result) {
64
+ logger.info(`${msiName}: Unavailable. The environment variables needed are: AZURE_CLIENT_ID (or the client ID sent through the parameters), AZURE_TENANT_ID and AZURE_FEDERATED_TOKEN_FILE`);
65
+ }
66
+ return result;
67
+ },
68
+ async getToken(configuration, getTokenOptions = {}) {
69
+ const { identityClient, scopes, clientId } = configuration;
70
+ logger.info(`${msiName}: Using the client assertion coming from environment variables.`);
71
+ let assertion;
72
+ try {
73
+ assertion = await readAssertion();
74
+ }
75
+ catch (err) {
76
+ throw new Error(`${msiName}: Failed to read ${azureFederatedTokenFilePath}, indicated by the environment variable AZURE_FEDERATED_TOKEN_FILE`);
77
+ }
78
+ return msiGenericGetToken(identityClient, prepareRequestOptions(scopes, assertion, clientId || process.env.AZURE_CLIENT_ID), expiresInParser, getTokenOptions);
79
+ }
80
+ };
81
+ }
82
+ //# sourceMappingURL=tokenExchangeMsi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenExchangeMsi.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/tokenExchangeMsi.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAA0B,MAAM,2BAA2B,CAAC;AAEtF,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEvD,MAAM,OAAO,GAAG,4CAA4C,CAAC;AAC7D,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;AAEzC,MAAM,aAAa,GAAG,SAAS,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;AAE7C,SAAS,eAAe,CAAC,WAAgB;IACvC,gFAAgF;IAChF,OAAO,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,qBAAqB,CAC5B,MAAyB,EACzB,eAAuB,EACvB,QAAiB;;IAEjB,MAAM,UAAU,GAAQ;QACtB,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM;QACxD,gBAAgB,EAAE,eAAe;QACjC,qBAAqB,EAAE,wDAAwD;QAC/E,SAAS,EAAE,QAAQ;QACnB,UAAU,EAAE,oBAAoB;KACjC,CAAC;IAEF,MAAM,SAAS,GAAG,IAAI,eAAe,CAAC,UAAU,CAAC,CAAC;IAClD,MAAM,GAAG,GAAG,IAAI,GAAG,CACjB,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,oBAAoB,EAClD,MAAA,OAAO,CAAC,GAAG,CAAC,oBAAoB,mCAAI,oBAAoB,CACzD,CAAC;IAEF,OAAO;QACL,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE;QACnB,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,SAAS,CAAC,QAAQ,EAAE;QAC1B,OAAO,EAAE,iBAAiB,CAAC;YACzB,MAAM,EAAE,kBAAkB;SAC3B,CAAC;KACH,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,MAAM,2BAA2B,GAAG,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC;IAC3E,IAAI,8BAA8B,GAAuB,SAAS,CAAC;IACnE,IAAI,SAAS,GAAuB,SAAS,CAAC;IAE9C,0DAA0D;IAC1D,KAAK,UAAU,aAAa;QAC1B,2CAA2C;QAC3C,IAAI,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,IAAI,IAAI,GAAG,EAAE,GAAG,CAAC,EAAE;YACtE,8BAA8B,GAAG,SAAS,CAAC;SAC5C;QACD,IAAI,CAAC,8BAA8B,EAAE;YACnC,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,2BAA4B,EAAE,MAAM,CAAC,CAAC;YACvE,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC1B,IAAI,CAAC,KAAK,EAAE;gBACV,MAAM,IAAI,KAAK,CACb,0BAA0B,2BAA2B,oEAAoE,CAC1H,CAAC;aACH;iBAAM;gBACL,8BAA8B,GAAG,KAAK,CAAC;gBACvC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;aACxB;SACF;QACD,OAAO,8BAA8B,CAAC;IACxC,CAAC;IAED,OAAO;QACL,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ;YAClD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;YACxB,MAAM,MAAM,GAAG,OAAO,CACpB,CAAC,QAAQ,IAAI,GAAG,CAAC,eAAe,CAAC,IAAI,GAAG,CAAC,eAAe,IAAI,2BAA2B,CACxF,CAAC;YACF,IAAI,CAAC,MAAM,EAAE;gBACX,MAAM,CAAC,IAAI,CACT,GAAG,OAAO,qKAAqK,CAChL,CAAC;aACH;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,KAAK,CAAC,QAAQ,CACZ,aAA+B,EAC/B,kBAAmC,EAAE;YAErC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC;YAC3D,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,iEAAiE,CAAC,CAAC;YAEzF,IAAI,SAAiB,CAAC;YAEtB,IAAI;gBACF,SAAS,GAAG,MAAM,aAAa,EAAE,CAAC;aACnC;YAAC,OAAO,GAAG,EAAE;gBACZ,MAAM,IAAI,KAAK,CACb,GAAG,OAAO,oBAAoB,2BAA2B,oEAAoE,CAC9H,CAAC;aACH;YAED,OAAO,kBAAkB,CACvB,cAAc,EACd,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,EACjF,eAAe,EACf,eAAe,CAChB,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport fs from \"fs\";\nimport { createHttpHeaders, PipelineRequestOptions } from \"@azure/core-rest-pipeline\";\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { promisify } from \"util\";\nimport { credentialLogger } from \"../../util/logging\";\nimport { MSI, MSIConfiguration } from \"./models\";\nimport { msiGenericGetToken } from \"./utils\";\nimport { DefaultAuthorityHost } from \"../../constants\";\n\nconst msiName = \"ManagedIdentityCredential - Token Exchange\";\nconst logger = credentialLogger(msiName);\n\nconst readFileAsync = promisify(fs.readFile);\n\nfunction expiresInParser(requestBody: any): number {\n // Parses a string representation of the seconds since epoch into a number value\n return Number(requestBody.expires_on);\n}\n\nfunction prepareRequestOptions(\n scopes: string | string[],\n clientAssertion: string,\n clientId?: string\n): PipelineRequestOptions {\n const bodyParams: any = {\n scope: Array.isArray(scopes) ? scopes.join(\" \") : scopes,\n client_assertion: clientAssertion,\n client_assertion_type: \"urn:ietf:params:oauth:client-assertion-type:jwt-bearer\",\n client_id: clientId,\n grant_type: \"client_credentials\"\n };\n\n const urlParams = new URLSearchParams(bodyParams);\n const url = new URL(\n `${process.env.AZURE_TENANT_ID}/oauth2/v2.0/token`,\n process.env.AZURE_AUTHORITY_HOST ?? DefaultAuthorityHost\n );\n\n return {\n url: url.toString(),\n method: \"POST\",\n body: urlParams.toString(),\n headers: createHttpHeaders({\n Accept: \"application/json\"\n })\n };\n}\n\nexport function tokenExchangeMsi(): MSI {\n const azureFederatedTokenFilePath = process.env.AZURE_FEDERATED_TOKEN_FILE;\n let azureFederatedTokenFileContent: string | undefined = undefined;\n let cacheDate: number | undefined = undefined;\n\n // Only reads from the assertion file once every 5 minutes\n async function readAssertion(): Promise<string> {\n // Cached assertions expire after 5 minutes\n if (cacheDate !== undefined && Date.now() - cacheDate >= 1000 * 60 * 5) {\n azureFederatedTokenFileContent = undefined;\n }\n if (!azureFederatedTokenFileContent) {\n const file = await readFileAsync(azureFederatedTokenFilePath!, \"utf8\");\n const value = file.trim();\n if (!value) {\n throw new Error(\n `No content on the file ${azureFederatedTokenFilePath}, indicated by the environment variable AZURE_FEDERATED_TOKEN_FILE`\n );\n } else {\n azureFederatedTokenFileContent = value;\n cacheDate = Date.now();\n }\n }\n return azureFederatedTokenFileContent;\n }\n\n return {\n async isAvailable(_scopes, _identityClient, clientId): Promise<boolean> {\n const env = process.env;\n const result = Boolean(\n (clientId || env.AZURE_CLIENT_ID) && env.AZURE_TENANT_ID && azureFederatedTokenFilePath\n );\n if (!result) {\n logger.info(\n `${msiName}: Unavailable. The environment variables needed are: AZURE_CLIENT_ID (or the client ID sent through the parameters), AZURE_TENANT_ID and AZURE_FEDERATED_TOKEN_FILE`\n );\n }\n return result;\n },\n async getToken(\n configuration: MSIConfiguration,\n getTokenOptions: GetTokenOptions = {}\n ): Promise<AccessToken | null> {\n const { identityClient, scopes, clientId } = configuration;\n logger.info(`${msiName}: Using the client assertion coming from environment variables.`);\n\n let assertion: string;\n\n try {\n assertion = await readAssertion();\n } catch (err) {\n throw new Error(\n `${msiName}: Failed to read ${azureFederatedTokenFilePath}, indicated by the environment variable AZURE_FEDERATED_TOKEN_FILE`\n );\n }\n\n return msiGenericGetToken(\n identityClient,\n prepareRequestOptions(scopes, assertion, clientId || process.env.AZURE_CLIENT_ID),\n expiresInParser,\n getTokenOptions\n );\n }\n };\n}\n"]}
@@ -2,11 +2,19 @@
2
2
  // Licensed under the MIT license.
3
3
  import { createPipelineRequest } from "@azure/core-rest-pipeline";
4
4
  import { DefaultScopeSuffix } from "./constants";
5
+ /**
6
+ * Most MSIs send requests to the IMDS endpoint, or a similar endpoint. These are GET requests that require sending a `resource` parameter on the query.
7
+ * This resource can be derived from the scopes received through the getToken call, as long as only one scope is received.
8
+ * Multiple scopes assume that the resulting token will have access to multiple resources, which won't be the case.
9
+ *
10
+ * For that reason, when we encounter multiple scopes, we return undefined.
11
+ * It's up to the individual MSI implementations to throw the errors (which helps us provide less generic errors).
12
+ */
5
13
  export function mapScopesToResource(scopes) {
6
14
  let scope = "";
7
15
  if (Array.isArray(scopes)) {
8
16
  if (scopes.length !== 1) {
9
- throw new Error("To convert to a resource string the specified array must be exactly length 1");
17
+ return;
10
18
  }
11
19
  scope = scopes[0];
12
20
  }
@@ -19,10 +27,7 @@ export function mapScopesToResource(scopes) {
19
27
  return scope.substr(0, scope.lastIndexOf(DefaultScopeSuffix));
20
28
  }
21
29
  export async function msiGenericGetToken(identityClient, requestOptions, expiresInParser, getTokenOptions = {}) {
22
- const request = createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal, tracingOptions: {
23
- spanOptions: getTokenOptions.tracingOptions && getTokenOptions.tracingOptions.spanOptions,
24
- tracingContext: getTokenOptions.tracingOptions && getTokenOptions.tracingOptions.tracingContext
25
- } }, requestOptions), { allowInsecureConnection: true }));
30
+ const request = createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, requestOptions), { allowInsecureConnection: true }));
26
31
  const tokenResponse = await identityClient.sendTokenRequest(request, expiresInParser);
27
32
  return (tokenResponse && tokenResponse.accessToken) || null;
28
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/utils.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EAA0B,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAE1F,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGjD,MAAM,UAAU,mBAAmB,CAAC,MAAyB;IAC3D,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;QACzB,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;YACvB,MAAM,IAAI,KAAK,CACb,8EAA8E,CAC/E,CAAC;SACH;QAED,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;KACnB;SAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;QACrC,KAAK,GAAG,MAAM,CAAC;KAChB;IAED,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE;QACvC,OAAO,KAAK,CAAC;KACd;IAED,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,cAA8B,EAC9B,cAAsC,EACtC,eAA+C,EAC/C,kBAAmC,EAAE;IAErC,MAAM,OAAO,GAAG,qBAAqB,+BACnC,WAAW,EAAE,eAAe,CAAC,WAAW,EACxC,cAAc,EAAE;YACd,WAAW,EAAE,eAAe,CAAC,cAAc,IAAI,eAAe,CAAC,cAAc,CAAC,WAAW;YACzF,cAAc,EACZ,eAAe,CAAC,cAAc,IAAI,eAAe,CAAC,cAAc,CAAC,cAAc;SAClF,IACE,cAAc,KACjB,uBAAuB,EAAE,IAAI,IAC7B,CAAC;IAEH,MAAM,aAAa,GAAG,MAAM,cAAc,CAAC,gBAAgB,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IACtF,OAAO,CAAC,aAAa,IAAI,aAAa,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC;AAC9D,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { PipelineRequestOptions, createPipelineRequest } from \"@azure/core-rest-pipeline\";\nimport { IdentityClient } from \"../../client/identityClient\";\nimport { DefaultScopeSuffix } from \"./constants\";\nimport { MSIExpiresInParser } from \"./models\";\n\nexport function mapScopesToResource(scopes: string | string[]): string {\n let scope = \"\";\n if (Array.isArray(scopes)) {\n if (scopes.length !== 1) {\n throw new Error(\n \"To convert to a resource string the specified array must be exactly length 1\"\n );\n }\n\n scope = scopes[0];\n } else if (typeof scopes === \"string\") {\n scope = scopes;\n }\n\n if (!scope.endsWith(DefaultScopeSuffix)) {\n return scope;\n }\n\n return scope.substr(0, scope.lastIndexOf(DefaultScopeSuffix));\n}\n\nexport async function msiGenericGetToken(\n identityClient: IdentityClient,\n requestOptions: PipelineRequestOptions,\n expiresInParser: MSIExpiresInParser | undefined,\n getTokenOptions: GetTokenOptions = {}\n): Promise<AccessToken | null> {\n const request = createPipelineRequest({\n abortSignal: getTokenOptions.abortSignal,\n tracingOptions: {\n spanOptions: getTokenOptions.tracingOptions && getTokenOptions.tracingOptions.spanOptions,\n tracingContext:\n getTokenOptions.tracingOptions && getTokenOptions.tracingOptions.tracingContext\n },\n ...requestOptions,\n allowInsecureConnection: true\n });\n\n const tokenResponse = await identityClient.sendTokenRequest(request, expiresInParser);\n return (tokenResponse && tokenResponse.accessToken) || null;\n}\n"]}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/utils.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EAA0B,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAE1F,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGjD;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAyB;IAC3D,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;QACzB,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;YACvB,OAAO;SACR;QAED,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;KACnB;SAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;QACrC,KAAK,GAAG,MAAM,CAAC;KAChB;IAED,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE;QACvC,OAAO,KAAK,CAAC;KACd;IAED,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,cAA8B,EAC9B,cAAsC,EACtC,eAA+C,EAC/C,kBAAmC,EAAE;IAErC,MAAM,OAAO,GAAG,qBAAqB,+BACnC,WAAW,EAAE,eAAe,CAAC,WAAW,IACrC,cAAc,KACjB,uBAAuB,EAAE,IAAI,IAC7B,CAAC;IAEH,MAAM,aAAa,GAAG,MAAM,cAAc,CAAC,gBAAgB,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IACtF,OAAO,CAAC,aAAa,IAAI,aAAa,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC;AAC9D,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { PipelineRequestOptions, createPipelineRequest } from \"@azure/core-rest-pipeline\";\nimport { IdentityClient } from \"../../client/identityClient\";\nimport { DefaultScopeSuffix } from \"./constants\";\nimport { MSIExpiresInParser } from \"./models\";\n\n/**\n * Most MSIs send requests to the IMDS endpoint, or a similar endpoint. These are GET requests that require sending a `resource` parameter on the query.\n * This resource can be derived from the scopes received through the getToken call, as long as only one scope is received.\n * Multiple scopes assume that the resulting token will have access to multiple resources, which won't be the case.\n *\n * For that reason, when we encounter multiple scopes, we return undefined.\n * It's up to the individual MSI implementations to throw the errors (which helps us provide less generic errors).\n */\nexport function mapScopesToResource(scopes: string | string[]): string | undefined {\n let scope = \"\";\n if (Array.isArray(scopes)) {\n if (scopes.length !== 1) {\n return;\n }\n\n scope = scopes[0];\n } else if (typeof scopes === \"string\") {\n scope = scopes;\n }\n\n if (!scope.endsWith(DefaultScopeSuffix)) {\n return scope;\n }\n\n return scope.substr(0, scope.lastIndexOf(DefaultScopeSuffix));\n}\n\nexport async function msiGenericGetToken(\n identityClient: IdentityClient,\n requestOptions: PipelineRequestOptions,\n expiresInParser: MSIExpiresInParser | undefined,\n getTokenOptions: GetTokenOptions = {}\n): Promise<AccessToken | null> {\n const request = createPipelineRequest({\n abortSignal: getTokenOptions.abortSignal,\n ...requestOptions,\n allowInsecureConnection: true\n });\n\n const tokenResponse = await identityClient.sendTokenRequest(request, expiresInParser);\n return (tokenResponse && tokenResponse.accessToken) || null;\n}\n"]}
@@ -0,0 +1,17 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT license.
3
+ import { credentialLogger, formatError } from "../util/logging";
4
+ const credentialName = "OnBehalfOfCredential";
5
+ const BrowserNotSupportedError = new Error(`${credentialName}: Not supported in the browser.`);
6
+ const logger = credentialLogger(credentialName);
7
+ export class OnBehalfOfCredential {
8
+ constructor() {
9
+ logger.info(formatError("", BrowserNotSupportedError));
10
+ throw BrowserNotSupportedError;
11
+ }
12
+ getToken() {
13
+ logger.getToken.info(formatError("", BrowserNotSupportedError));
14
+ throw BrowserNotSupportedError;
15
+ }
16
+ }
17
+ //# sourceMappingURL=onBehalfOfCredential.browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onBehalfOfCredential.browser.js","sourceRoot":"","sources":["../../../src/credentials/onBehalfOfCredential.browser.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEhE,MAAM,cAAc,GAAG,sBAAsB,CAAC;AAC9C,MAAM,wBAAwB,GAAG,IAAI,KAAK,CAAC,GAAG,cAAc,iCAAiC,CAAC,CAAC;AAC/F,MAAM,MAAM,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC;AAEhD,MAAM,OAAO,oBAAoB;IAC/B;QACE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC;QACvD,MAAM,wBAAwB,CAAC;IACjC,CAAC;IAEM,QAAQ;QACb,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 { TokenCredential, AccessToken } from \"@azure/core-auth\";\nimport { credentialLogger, formatError } from \"../util/logging\";\n\nconst credentialName = \"OnBehalfOfCredential\";\nconst BrowserNotSupportedError = new Error(`${credentialName}: Not supported in the browser.`);\nconst logger = credentialLogger(credentialName);\n\nexport class OnBehalfOfCredential implements TokenCredential {\n constructor() {\n logger.info(formatError(\"\", BrowserNotSupportedError));\n throw BrowserNotSupportedError;\n }\n\n public getToken(): Promise<AccessToken | null> {\n logger.getToken.info(formatError(\"\", BrowserNotSupportedError));\n throw BrowserNotSupportedError;\n }\n}\n"]}
@@ -0,0 +1,62 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT license.
3
+ import { MsalOnBehalfOf } from "../msal/nodeFlows/msalOnBehalfOf";
4
+ import { credentialLogger } from "../util/logging";
5
+ import { trace } from "../util/tracing";
6
+ const credentialName = "OnBehalfOfCredential";
7
+ const logger = credentialLogger(credentialName);
8
+ /**
9
+ * Enables authentication to Azure Active Directory using the [On Behalf Of flow](https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow).
10
+ */
11
+ export class OnBehalfOfCredential {
12
+ /**
13
+ * Creates an instance of the {@link OnBehalfOfCredential} with the details
14
+ * needed to authenticate against Azure Active Directory with a client
15
+ * secret or a path to a PEM certificate, and an user assertion.
16
+ *
17
+ * Example using the `KeyClient` from [\@azure/keyvault-keys](https://www.npmjs.com/package/\@azure/keyvault-keys):
18
+ *
19
+ * ```ts
20
+ * const tokenCredential = new OnBehalfOfCredential({
21
+ * tenantId,
22
+ * clientId,
23
+ * clientSecret, // or `certificatePath: "/path/to/certificate.pem"
24
+ * userAssertionToken: "access-token"
25
+ * });
26
+ * const client = new KeyClient("vault-url", tokenCredential);
27
+ *
28
+ * await client.getKey("key-name");
29
+ * ```
30
+ *
31
+ * @param configuration - Configuration specific to this credential.
32
+ * @param options - Optional parameters, generally common across credentials.
33
+ */
34
+ constructor(configuration, options = {}) {
35
+ this.configuration = configuration;
36
+ this.options = options;
37
+ const { tenantId, clientId, userAssertionToken } = configuration;
38
+ const secretConfiguration = configuration;
39
+ const certificateConfiguration = configuration;
40
+ if (!tenantId ||
41
+ !clientId ||
42
+ !(secretConfiguration.clientSecret || certificateConfiguration.certificatePath) ||
43
+ !userAssertionToken) {
44
+ throw new Error(`${credentialName}: tenantId, clientId, clientSecret (or certificatePath) and userAssertionToken are required parameters.`);
45
+ }
46
+ this.msalFlow = new MsalOnBehalfOf(Object.assign(Object.assign(Object.assign({}, this.options), this.configuration), { logger, tokenCredentialOptions: this.options }));
47
+ }
48
+ /**
49
+ * Authenticates with Azure Active Directory and returns an access token if successful.
50
+ * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.
51
+ *
52
+ * @param scopes - The list of scopes for which the token will have access.
53
+ * @param options - The options used to configure the underlying network requests.
54
+ */
55
+ async getToken(scopes, options = {}) {
56
+ return trace(`${credentialName}.getToken`, options, async (newOptions) => {
57
+ const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];
58
+ return this.msalFlow.getToken(arrayScopes, newOptions);
59
+ });
60
+ }
61
+ }
62
+ //# sourceMappingURL=onBehalfOfCredential.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onBehalfOfCredential.js","sourceRoot":"","sources":["../../../src/credentials/onBehalfOfCredential.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAIlC,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAIxC,MAAM,cAAc,GAAG,sBAAsB,CAAC;AAC9C,MAAM,MAAM,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC;AAmDhD;;GAEG;AACH,MAAM,OAAO,oBAAoB;IAG/B;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,YACU,aAEwC,EACxC,UAAuC,EAAE;QAHzC,kBAAa,GAAb,aAAa,CAE2B;QACxC,YAAO,GAAP,OAAO,CAAkC;QAEjD,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,kBAAkB,EAAE,GAAG,aAAa,CAAC;QACjE,MAAM,mBAAmB,GAAG,aAAwD,CAAC;QACrF,MAAM,wBAAwB,GAAG,aAA6D,CAAC;QAC/F,IACE,CAAC,QAAQ;YACT,CAAC,QAAQ;YACT,CAAC,CAAC,mBAAmB,CAAC,YAAY,IAAI,wBAAwB,CAAC,eAAe,CAAC;YAC/E,CAAC,kBAAkB,EACnB;YACA,MAAM,IAAI,KAAK,CACb,GAAG,cAAc,yGAAyG,CAC3H,CAAC;SACH;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,cAAc,+CAC7B,IAAI,CAAC,OAAO,GACZ,IAAI,CAAC,aAAa,KACrB,MAAM,EACN,sBAAsB,EAAE,IAAI,CAAC,OAAO,IACpC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,QAAQ,CAAC,MAAyB,EAAE,UAA2B,EAAE;QACrE,OAAO,KAAK,CAAC,GAAG,cAAc,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;YACvE,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC9D,OAAO,IAAI,CAAC,QAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\n\nimport { MsalOnBehalfOf } from \"../msal/nodeFlows/msalOnBehalfOf\";\nimport { credentialLogger } from \"../util/logging\";\nimport { trace } from \"../util/tracing\";\nimport { MsalFlow } from \"../msal/flows\";\nimport { OnBehalfOfCredentialOptions } from \"./onBehalfOfCredentialOptions\";\n\nconst credentialName = \"OnBehalfOfCredential\";\nconst logger = credentialLogger(credentialName);\n\n/**\n * Defines the configuration parameters to authenticate the {@link OnBehalfOfCredential} with a secret.\n */\nexport interface OnBehalfOfCredentialSecretConfiguration {\n /**\n * The Azure Active Directory tenant (directory) ID.\n */\n tenantId: string;\n /**\n * The client (application) ID of an App Registration in the tenant.\n */\n clientId: string;\n /**\n * A client secret that was generated for the App Registration.\n */\n clientSecret: string;\n /**\n * The user assertion for the On-Behalf-Of flow.\n */\n userAssertionToken: string;\n}\n\n/**\n * Defines the configuration parameters to authenticate the {@link OnBehalfOfCredential} with a certificate.\n */\nexport interface OnBehalfOfCredentialCertificateConfiguration {\n /**\n * The Azure Active Directory tenant (directory) ID.\n */\n tenantId: string;\n /**\n * The client (application) ID of an App Registration in the tenant.\n */\n clientId: string;\n /**\n * The path to a PEM-encoded public/private key certificate on the filesystem.\n */\n certificatePath: string;\n /**\n * Option to include x5c header for SubjectName and Issuer name authorization.\n * Set this option to send base64 encoded public certificate in the client assertion header as an x5c claim\n */\n sendCertificateChain?: boolean;\n /**\n * The user assertion for the On-Behalf-Of flow.\n */\n userAssertionToken: string;\n}\n\n/**\n * Enables authentication to Azure Active Directory using the [On Behalf Of flow](https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow).\n */\nexport class OnBehalfOfCredential implements TokenCredential {\n private msalFlow: MsalFlow;\n\n /**\n * Creates an instance of the {@link OnBehalfOfCredential} with the details\n * needed to authenticate against Azure Active Directory with a client\n * secret or a path to a PEM certificate, and an user assertion.\n *\n * Example using the `KeyClient` from [\\@azure/keyvault-keys](https://www.npmjs.com/package/\\@azure/keyvault-keys):\n *\n * ```ts\n * const tokenCredential = new OnBehalfOfCredential({\n * tenantId,\n * clientId,\n * clientSecret, // or `certificatePath: \"/path/to/certificate.pem\"\n * userAssertionToken: \"access-token\"\n * });\n * const client = new KeyClient(\"vault-url\", tokenCredential);\n *\n * await client.getKey(\"key-name\");\n * ```\n *\n * @param configuration - Configuration specific to this credential.\n * @param options - Optional parameters, generally common across credentials.\n */\n constructor(\n private configuration:\n | OnBehalfOfCredentialSecretConfiguration\n | OnBehalfOfCredentialCertificateConfiguration,\n private options: OnBehalfOfCredentialOptions = {}\n ) {\n const { tenantId, clientId, userAssertionToken } = configuration;\n const secretConfiguration = configuration as OnBehalfOfCredentialSecretConfiguration;\n const certificateConfiguration = configuration as OnBehalfOfCredentialCertificateConfiguration;\n if (\n !tenantId ||\n !clientId ||\n !(secretConfiguration.clientSecret || certificateConfiguration.certificatePath) ||\n !userAssertionToken\n ) {\n throw new Error(\n `${credentialName}: tenantId, clientId, clientSecret (or certificatePath) and userAssertionToken are required parameters.`\n );\n }\n this.msalFlow = new MsalOnBehalfOf({\n ...this.options,\n ...this.configuration,\n logger,\n tokenCredentialOptions: this.options\n });\n }\n\n /**\n * Authenticates with Azure Active Directory and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure the underlying network requests.\n */\n async getToken(scopes: string | string[], options: GetTokenOptions = {}): Promise<AccessToken> {\n return trace(`${credentialName}.getToken`, options, async (newOptions) => {\n const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];\n return this.msalFlow!.getToken(arrayScopes, newOptions);\n });\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
1
  // Copyright (c) Microsoft Corporation.
2
2
  // Licensed under the MIT license.
3
3
  export {};
4
- //# sourceMappingURL=visualStudioCodeCredentialExtension.js.map
4
+ //# sourceMappingURL=onBehalfOfCredentialOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onBehalfOfCredentialOptions.js","sourceRoot":"","sources":["../../../src/credentials/onBehalfOfCredentialOptions.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { TokenCredentialOptions } from \"../client/identityClient\";\nimport { CredentialPersistenceOptions } from \"./credentialPersistenceOptions\";\n\n/**\n * Optional parameters for the {@link OnBehalfOfCredential} class.\n */\nexport interface OnBehalfOfCredentialOptions\n extends TokenCredentialOptions,\n CredentialPersistenceOptions {}\n"]}
@@ -1,6 +1,5 @@
1
1
  // Copyright (c) Microsoft Corporation.
2
2
  // Licensed under the MIT license.
3
- import qs from "qs";
4
3
  import { createHttpHeaders, createPipelineRequest } from "@azure/core-rest-pipeline";
5
4
  import { SpanStatusCode } from "@azure/core-tracing";
6
5
  import { IdentityClient } from "../client/identityClient";
@@ -49,26 +48,24 @@ export class UsernamePasswordCredential {
49
48
  const { span, updatedOptions: newOptions } = createSpan("UsernamePasswordCredential-getToken", options);
50
49
  try {
51
50
  const urlSuffix = getIdentityTokenEndpointSuffix(this.tenantId);
51
+ const params = new URLSearchParams({
52
+ response_type: "token",
53
+ grant_type: "password",
54
+ client_id: this.clientId,
55
+ username: this.username,
56
+ password: this.password,
57
+ scope: typeof scopes === "string" ? scopes : scopes.join(" ")
58
+ });
52
59
  const webResource = createPipelineRequest({
53
60
  url: `${this.identityClient.authorityHost}/${this.tenantId}/${urlSuffix}`,
54
61
  method: "POST",
55
- body: qs.stringify({
56
- response_type: "token",
57
- grant_type: "password",
58
- client_id: this.clientId,
59
- username: this.username,
60
- password: this.password,
61
- scope: typeof scopes === "string" ? scopes : scopes.join(" ")
62
- }),
62
+ body: params.toString(),
63
63
  headers: createHttpHeaders({
64
64
  Accept: "application/json",
65
65
  "Content-Type": "application/x-www-form-urlencoded"
66
66
  }),
67
67
  abortSignal: options && options.abortSignal,
68
- tracingOptions: {
69
- spanOptions: newOptions.tracingOptions && newOptions.tracingOptions.spanOptions,
70
- tracingContext: newOptions.tracingOptions && newOptions.tracingOptions.tracingContext
71
- }
68
+ tracingOptions: newOptions.tracingOptions
72
69
  });
73
70
  const tokenResponse = await this.identityClient.sendTokenRequest(webResource);
74
71
  logger.getToken.info(formatSuccess(scopes));
@@ -1 +1 @@
1
- {"version":3,"file":"usernamePasswordCredential.browser.js","sourceRoot":"","sources":["../../../src/credentials/usernamePasswordCredential.browser.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport qs from \"qs\";\n\nimport { TokenCredential, GetTokenOptions, AccessToken } from \"@azure/core-auth\";\nimport { createHttpHeaders, createPipelineRequest } from \"@azure/core-rest-pipeline\";\nimport { SpanStatusCode } from \"@azure/core-tracing\";\nimport { TokenCredentialOptions, IdentityClient } from \"../client/identityClient\";\nimport { credentialLogger, formatSuccess, formatError } from \"../util/logging\";\nimport { getIdentityTokenEndpointSuffix } from \"../util/identityTokenEndpoint\";\nimport { createSpan } from \"../util/tracing\";\nimport { checkTenantId } from \"../util/checkTenantId\";\n\nconst logger = credentialLogger(\"UsernamePasswordCredential\");\n\n/**\n * Enables authentication to Azure Active Directory with a user's\n * username and password. This credential requires a high degree of\n * trust so you should only use it when other, more secure credential\n * types can't be used.\n */\nexport class UsernamePasswordCredential implements TokenCredential {\n private identityClient: IdentityClient;\n private tenantId: string;\n private clientId: string;\n private username: string;\n private password: string;\n\n /**\n * Creates an instance of the UsernamePasswordCredential with the details\n * needed to authenticate against Azure Active Directory with a username\n * and password.\n *\n * @param tenantIdOrName - The Azure Active Directory tenant (directory) ID or name.\n * @param clientId - The client (application) ID of an App Registration in the tenant.\n * @param username - The user account's e-mail address (user name).\n * @param password - The user account's account password\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantIdOrName: string,\n clientId: string,\n username: string,\n password: string,\n options?: TokenCredentialOptions\n ) {\n checkTenantId(logger, tenantIdOrName);\n\n this.identityClient = new IdentityClient(options);\n this.tenantId = tenantIdOrName;\n this.clientId = clientId;\n this.username = username;\n this.password = password;\n }\n\n /**\n * Authenticates with Azure Active Directory and returns an access token if\n * successful. If authentication cannot be performed at this time, this method may\n * return null. If an error occurs during authentication, an {@link AuthenticationError}\n * containing failure details will be thrown.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n public async getToken(\n scopes: string | string[],\n options?: GetTokenOptions\n ): Promise<AccessToken | null> {\n const { span, updatedOptions: newOptions } = createSpan(\n \"UsernamePasswordCredential-getToken\",\n options\n );\n try {\n const urlSuffix = getIdentityTokenEndpointSuffix(this.tenantId);\n const webResource = createPipelineRequest({\n url: `${this.identityClient.authorityHost}/${this.tenantId}/${urlSuffix}`,\n method: \"POST\",\n body: qs.stringify({\n response_type: \"token\",\n grant_type: \"password\",\n client_id: this.clientId,\n username: this.username,\n password: this.password,\n scope: typeof scopes === \"string\" ? scopes : scopes.join(\" \")\n }),\n headers: createHttpHeaders({\n Accept: \"application/json\",\n \"Content-Type\": \"application/x-www-form-urlencoded\"\n }),\n abortSignal: options && options.abortSignal,\n tracingOptions: {\n spanOptions: newOptions.tracingOptions && newOptions.tracingOptions.spanOptions,\n tracingContext: newOptions.tracingOptions && newOptions.tracingOptions.tracingContext\n }\n });\n\n const tokenResponse = await this.identityClient.sendTokenRequest(webResource);\n logger.getToken.info(formatSuccess(scopes));\n return (tokenResponse && tokenResponse.accessToken) || null;\n } catch (err) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n logger.getToken.info(formatError(scopes, err));\n throw err;\n } finally {\n span.end();\n }\n }\n}\n"]}
1
+ {"version":3,"file":"usernamePasswordCredential.browser.js","sourceRoot":"","sources":["../../../src/credentials/usernamePasswordCredential.browser.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { TokenCredential, GetTokenOptions, AccessToken } from \"@azure/core-auth\";\nimport { createHttpHeaders, createPipelineRequest } from \"@azure/core-rest-pipeline\";\nimport { SpanStatusCode } from \"@azure/core-tracing\";\nimport { TokenCredentialOptions, IdentityClient } from \"../client/identityClient\";\nimport { credentialLogger, formatSuccess, formatError } from \"../util/logging\";\nimport { getIdentityTokenEndpointSuffix } from \"../util/identityTokenEndpoint\";\nimport { createSpan } from \"../util/tracing\";\nimport { checkTenantId } from \"../util/checkTenantId\";\n\nconst logger = credentialLogger(\"UsernamePasswordCredential\");\n\n/**\n * Enables authentication to Azure Active Directory with a user's\n * username and password. This credential requires a high degree of\n * trust so you should only use it when other, more secure credential\n * types can't be used.\n */\nexport class UsernamePasswordCredential implements TokenCredential {\n private identityClient: IdentityClient;\n private tenantId: string;\n private clientId: string;\n private username: string;\n private password: string;\n\n /**\n * Creates an instance of the UsernamePasswordCredential with the details\n * needed to authenticate against Azure Active Directory with a username\n * and password.\n *\n * @param tenantIdOrName - The Azure Active Directory tenant (directory) ID or name.\n * @param clientId - The client (application) ID of an App Registration in the tenant.\n * @param username - The user account's e-mail address (user name).\n * @param password - The user account's account password\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantIdOrName: string,\n clientId: string,\n username: string,\n password: string,\n options?: TokenCredentialOptions\n ) {\n checkTenantId(logger, tenantIdOrName);\n\n this.identityClient = new IdentityClient(options);\n this.tenantId = tenantIdOrName;\n this.clientId = clientId;\n this.username = username;\n this.password = password;\n }\n\n /**\n * Authenticates with Azure Active Directory and returns an access token if\n * successful. If authentication cannot be performed at this time, this method may\n * return null. If an error occurs during authentication, an {@link AuthenticationError}\n * containing failure details will be thrown.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n public async getToken(\n scopes: string | string[],\n options?: GetTokenOptions\n ): Promise<AccessToken | null> {\n const { span, updatedOptions: newOptions } = createSpan(\n \"UsernamePasswordCredential-getToken\",\n options\n );\n try {\n const urlSuffix = getIdentityTokenEndpointSuffix(this.tenantId);\n const params = new URLSearchParams({\n response_type: \"token\",\n grant_type: \"password\",\n client_id: this.clientId,\n username: this.username,\n password: this.password,\n scope: typeof scopes === \"string\" ? scopes : scopes.join(\" \")\n });\n const webResource = createPipelineRequest({\n url: `${this.identityClient.authorityHost}/${this.tenantId}/${urlSuffix}`,\n method: \"POST\",\n body: params.toString(),\n headers: createHttpHeaders({\n Accept: \"application/json\",\n \"Content-Type\": \"application/x-www-form-urlencoded\"\n }),\n abortSignal: options && options.abortSignal,\n tracingOptions: newOptions.tracingOptions\n });\n\n const tokenResponse = await this.identityClient.sendTokenRequest(webResource);\n logger.getToken.info(formatSuccess(scopes));\n return (tokenResponse && tokenResponse.accessToken) || null;\n } catch (err) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n logger.getToken.info(formatError(scopes, err));\n throw err;\n } finally {\n span.end();\n }\n }\n}\n"]}
@@ -25,6 +25,9 @@ export class UsernamePasswordCredential {
25
25
  * @param options - Options for configuring the client which makes the authentication request.
26
26
  */
27
27
  constructor(tenantId, clientId, username, password, options = {}) {
28
+ if (!tenantId || !clientId || !username || !password) {
29
+ throw new Error("UsernamePasswordCredential: tenantId, clientId, username and password are required parameters.");
30
+ }
28
31
  this.msalFlow = new MsalUsernamePassword(Object.assign(Object.assign({}, options), { logger,
29
32
  clientId,
30
33
  tenantId,
@@ -1 +1 @@
1
- {"version":3,"file":"usernamePasswordCredential.js","sourceRoot":"","sources":["../../../src/credentials/usernamePasswordCredential.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAIlC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAE9E,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAGxC,MAAM,MAAM,GAAG,gBAAgB,CAAC,4BAA4B,CAAC,CAAC;AAE9D;;;;;GAKG;AACH,+GAA+G;AAC/G,uEAAuE;AACvE,MAAM,OAAO,0BAA0B;IAGrC;;;;;;;;;;OAUG;IACH,YACE,QAAgB,EAChB,QAAgB,EAChB,QAAgB,EAChB,QAAgB,EAChB,UAA6C,EAAE;QAE/C,IAAI,CAAC,QAAQ,GAAG,IAAI,oBAAoB,iCACnC,OAAO,KACV,MAAM;YACN,QAAQ;YACR,QAAQ;YACR,QAAQ;YACR,QAAQ,EACR,sBAAsB,EAAE,OAAO,IAAI,EAAE,IACrC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,QAAQ,CAAC,MAAyB,EAAE,UAA2B,EAAE;QACrE,OAAO,KAAK,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;YAC9E,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC9D,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\n\nimport { credentialLogger } from \"../util/logging\";\nimport { MsalUsernamePassword } from \"../msal/nodeFlows/msalUsernamePassword\";\nimport { MsalFlow } from \"../msal/flows\";\nimport { trace } from \"../util/tracing\";\nimport { UsernamePasswordCredentialOptions } from \"./usernamePasswordCredentialOptions\";\n\nconst logger = credentialLogger(\"UsernamePasswordCredential\");\n\n/**\n * Enables authentication to Azure Active Directory with a user's\n * username and password. This credential requires a high degree of\n * trust so you should only use it when other, more secure credential\n * types can't be used.\n */\n// We'll be using InteractiveCredential as the base of this class, which requires us to support authenticate(),\n// to reduce the number of times we send the password over the network.\nexport class UsernamePasswordCredential implements TokenCredential {\n private msalFlow: MsalFlow;\n\n /**\n * Creates an instance of the UsernamePasswordCredential with the details\n * needed to authenticate against Azure Active Directory with a username\n * and password.\n *\n * @param tenantId - The Azure Active Directory tenant (directory).\n * @param clientId - The client (application) ID of an App Registration in the tenant.\n * @param username - The user account's e-mail address (user name).\n * @param password - The user account's account password\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n username: string,\n password: string,\n options: UsernamePasswordCredentialOptions = {}\n ) {\n this.msalFlow = new MsalUsernamePassword({\n ...options,\n logger,\n clientId,\n tenantId,\n username,\n password,\n tokenCredentialOptions: options || {}\n });\n }\n\n /**\n * Authenticates with Azure Active Directory and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.\n *\n * If the user provided the option `disableAutomaticAuthentication`,\n * once the token can't be retrieved silently,\n * this method won't attempt to request user interaction to retrieve the token.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n async getToken(scopes: string | string[], options: GetTokenOptions = {}): Promise<AccessToken> {\n return trace(`${this.constructor.name}.getToken`, options, async (newOptions) => {\n const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];\n return this.msalFlow.getToken(arrayScopes, newOptions);\n });\n }\n}\n"]}
1
+ {"version":3,"file":"usernamePasswordCredential.js","sourceRoot":"","sources":["../../../src/credentials/usernamePasswordCredential.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAIlC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAE9E,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAGxC,MAAM,MAAM,GAAG,gBAAgB,CAAC,4BAA4B,CAAC,CAAC;AAE9D;;;;;GAKG;AACH,+GAA+G;AAC/G,uEAAuE;AACvE,MAAM,OAAO,0BAA0B;IAGrC;;;;;;;;;;OAUG;IACH,YACE,QAAgB,EAChB,QAAgB,EAChB,QAAgB,EAChB,QAAgB,EAChB,UAA6C,EAAE;QAE/C,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,EAAE;YACpD,MAAM,IAAI,KAAK,CACb,gGAAgG,CACjG,CAAC;SACH;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,oBAAoB,iCACnC,OAAO,KACV,MAAM;YACN,QAAQ;YACR,QAAQ;YACR,QAAQ;YACR,QAAQ,EACR,sBAAsB,EAAE,OAAO,IAAI,EAAE,IACrC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,QAAQ,CAAC,MAAyB,EAAE,UAA2B,EAAE;QACrE,OAAO,KAAK,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;YAC9E,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC9D,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\n\nimport { credentialLogger } from \"../util/logging\";\nimport { MsalUsernamePassword } from \"../msal/nodeFlows/msalUsernamePassword\";\nimport { MsalFlow } from \"../msal/flows\";\nimport { trace } from \"../util/tracing\";\nimport { UsernamePasswordCredentialOptions } from \"./usernamePasswordCredentialOptions\";\n\nconst logger = credentialLogger(\"UsernamePasswordCredential\");\n\n/**\n * Enables authentication to Azure Active Directory with a user's\n * username and password. This credential requires a high degree of\n * trust so you should only use it when other, more secure credential\n * types can't be used.\n */\n// We'll be using InteractiveCredential as the base of this class, which requires us to support authenticate(),\n// to reduce the number of times we send the password over the network.\nexport class UsernamePasswordCredential implements TokenCredential {\n private msalFlow: MsalFlow;\n\n /**\n * Creates an instance of the UsernamePasswordCredential with the details\n * needed to authenticate against Azure Active Directory with a username\n * and password.\n *\n * @param tenantId - The Azure Active Directory tenant (directory).\n * @param clientId - The client (application) ID of an App Registration in the tenant.\n * @param username - The user account's e-mail address (user name).\n * @param password - The user account's account password\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n username: string,\n password: string,\n options: UsernamePasswordCredentialOptions = {}\n ) {\n if (!tenantId || !clientId || !username || !password) {\n throw new Error(\n \"UsernamePasswordCredential: tenantId, clientId, username and password are required parameters.\"\n );\n }\n this.msalFlow = new MsalUsernamePassword({\n ...options,\n logger,\n clientId,\n tenantId,\n username,\n password,\n tokenCredentialOptions: options || {}\n });\n }\n\n /**\n * Authenticates with Azure Active Directory and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.\n *\n * If the user provided the option `disableAutomaticAuthentication`,\n * once the token can't be retrieved silently,\n * this method won't attempt to request user interaction to retrieve the token.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n async getToken(scopes: string | string[], options: GetTokenOptions = {}): Promise<AccessToken> {\n return trace(`${this.constructor.name}.getToken`, options, async (newOptions) => {\n const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];\n return this.msalFlow.getToken(arrayScopes, newOptions);\n });\n }\n}\n"]}
@@ -5,7 +5,7 @@ const BrowserNotSupportedError = new Error("VisualStudioCodeCredential is not su
5
5
  const logger = credentialLogger("VisualStudioCodeCredential");
6
6
  export const vsCodeCredentialControl = {
7
7
  set vsCodeCredentialFinder(_finder) {
8
- throw new Error("Attempted to register a VisualStudioCodeCredential provider extension in the browser. This environment is not supported by VisualStudioCodeCredential.");
8
+ throw new Error("Attempted to register a VisualStudioCodeCredential provider plugin in the browser. This environment is not supported by VisualStudioCodeCredential.");
9
9
  }
10
10
  };
11
11
  export class VisualStudioCodeCredential {