@azure/identity 4.1.1-alpha.20240416.1 → 4.1.1-alpha.20240419.1

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

Potentially problematic release.


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

package/dist/index.js CHANGED
@@ -16,8 +16,8 @@ var https = require('https');
16
16
  var promises = require('fs/promises');
17
17
  var child_process = require('child_process');
18
18
  var crypto = require('crypto');
19
- var util = require('util');
20
19
  var open = require('open');
20
+ var util = require('util');
21
21
 
22
22
  function _interopNamespaceDefault(e) {
23
23
  var n = Object.create(null);
@@ -141,6 +141,55 @@ const msalNodeFlowNativeBrokerControl = {
141
141
  };
142
142
  },
143
143
  };
144
+ /**
145
+ * Configures plugins, validating that required plugins are available and enabled.
146
+ *
147
+ * Does not create the plugins themselves, but rather returns the configuration that will be used to create them.
148
+ *
149
+ * @param options - options for creating the MSAL client
150
+ * @returns plugin configuration
151
+ */
152
+ function generatePluginConfiguration(options) {
153
+ var _a, _b, _c, _d, _e;
154
+ const config = {
155
+ cache: {},
156
+ broker: {
157
+ enableMsaPassthrough: (_b = (_a = options.brokerOptions) === null || _a === void 0 ? void 0 : _a.legacyEnableMsaPassthrough) !== null && _b !== void 0 ? _b : false,
158
+ parentWindowHandle: (_c = options.brokerOptions) === null || _c === void 0 ? void 0 : _c.parentWindowHandle,
159
+ },
160
+ };
161
+ if ((_d = options.tokenCachePersistenceOptions) === null || _d === void 0 ? void 0 : _d.enabled) {
162
+ if (persistenceProvider === undefined) {
163
+ throw new Error([
164
+ "Persistent token caching was requested, but no persistence provider was configured.",
165
+ "You must install the identity-cache-persistence plugin package (`npm install --save @azure/identity-cache-persistence`)",
166
+ "and enable it by importing `useIdentityPlugin` from `@azure/identity` and calling",
167
+ "`useIdentityPlugin(cachePersistencePlugin)` before using `tokenCachePersistenceOptions`.",
168
+ ].join(" "));
169
+ }
170
+ const cacheBaseName = options.tokenCachePersistenceOptions.name || DEFAULT_TOKEN_CACHE_NAME;
171
+ config.cache.cachePlugin = persistenceProvider(Object.assign({ name: `${cacheBaseName}.${CACHE_NON_CAE_SUFFIX}` }, options.tokenCachePersistenceOptions));
172
+ config.cache.cachePluginCae = persistenceProvider(Object.assign({ name: `${cacheBaseName}.${CACHE_CAE_SUFFIX}` }, options.tokenCachePersistenceOptions));
173
+ }
174
+ if ((_e = options.brokerOptions) === null || _e === void 0 ? void 0 : _e.enabled) {
175
+ if (nativeBrokerInfo === undefined) {
176
+ throw new Error([
177
+ "Broker for WAM was requested to be enabled, but no native broker was configured.",
178
+ "You must install the identity-broker plugin package (`npm install --save @azure/identity-broker`)",
179
+ "and enable it by importing `useIdentityPlugin` from `@azure/identity` and calling",
180
+ "`useIdentityPlugin(createNativeBrokerPlugin())` before using `enableBroker`.",
181
+ ].join(" "));
182
+ }
183
+ config.broker.nativeBrokerPlugin = nativeBrokerInfo.broker;
184
+ }
185
+ return config;
186
+ }
187
+ /**
188
+ * Wraps generatePluginConfiguration as a writeable property for test stubbing purposes.
189
+ */
190
+ const msalPlugins = {
191
+ generatePluginConfiguration,
192
+ };
144
193
 
145
194
  // Copyright (c) Microsoft Corporation.
146
195
  // Licensed under the MIT license.
@@ -1713,488 +1762,186 @@ const imdsMsi = {
1713
1762
  // Copyright (c) Microsoft Corporation.
1714
1763
  // Licensed under the MIT license.
1715
1764
  /**
1716
- * Helps specify a regional authority, or "AutoDiscoverRegion" to auto-detect the region.
1765
+ * The logger for all MsalClient instances.
1717
1766
  */
1718
- var RegionalAuthority;
1719
- (function (RegionalAuthority) {
1720
- /** Instructs MSAL to attempt to discover the region */
1721
- RegionalAuthority["AutoDiscoverRegion"] = "AutoDiscoverRegion";
1722
- /** Uses the {@link RegionalAuthority} for the Azure 'westus' region. */
1723
- RegionalAuthority["USWest"] = "westus";
1724
- /** Uses the {@link RegionalAuthority} for the Azure 'westus2' region. */
1725
- RegionalAuthority["USWest2"] = "westus2";
1726
- /** Uses the {@link RegionalAuthority} for the Azure 'centralus' region. */
1727
- RegionalAuthority["USCentral"] = "centralus";
1728
- /** Uses the {@link RegionalAuthority} for the Azure 'eastus' region. */
1729
- RegionalAuthority["USEast"] = "eastus";
1730
- /** Uses the {@link RegionalAuthority} for the Azure 'eastus2' region. */
1731
- RegionalAuthority["USEast2"] = "eastus2";
1732
- /** Uses the {@link RegionalAuthority} for the Azure 'northcentralus' region. */
1733
- RegionalAuthority["USNorthCentral"] = "northcentralus";
1734
- /** Uses the {@link RegionalAuthority} for the Azure 'southcentralus' region. */
1735
- RegionalAuthority["USSouthCentral"] = "southcentralus";
1736
- /** Uses the {@link RegionalAuthority} for the Azure 'westcentralus' region. */
1737
- RegionalAuthority["USWestCentral"] = "westcentralus";
1738
- /** Uses the {@link RegionalAuthority} for the Azure 'canadacentral' region. */
1739
- RegionalAuthority["CanadaCentral"] = "canadacentral";
1740
- /** Uses the {@link RegionalAuthority} for the Azure 'canadaeast' region. */
1741
- RegionalAuthority["CanadaEast"] = "canadaeast";
1742
- /** Uses the {@link RegionalAuthority} for the Azure 'brazilsouth' region. */
1743
- RegionalAuthority["BrazilSouth"] = "brazilsouth";
1744
- /** Uses the {@link RegionalAuthority} for the Azure 'northeurope' region. */
1745
- RegionalAuthority["EuropeNorth"] = "northeurope";
1746
- /** Uses the {@link RegionalAuthority} for the Azure 'westeurope' region. */
1747
- RegionalAuthority["EuropeWest"] = "westeurope";
1748
- /** Uses the {@link RegionalAuthority} for the Azure 'uksouth' region. */
1749
- RegionalAuthority["UKSouth"] = "uksouth";
1750
- /** Uses the {@link RegionalAuthority} for the Azure 'ukwest' region. */
1751
- RegionalAuthority["UKWest"] = "ukwest";
1752
- /** Uses the {@link RegionalAuthority} for the Azure 'francecentral' region. */
1753
- RegionalAuthority["FranceCentral"] = "francecentral";
1754
- /** Uses the {@link RegionalAuthority} for the Azure 'francesouth' region. */
1755
- RegionalAuthority["FranceSouth"] = "francesouth";
1756
- /** Uses the {@link RegionalAuthority} for the Azure 'switzerlandnorth' region. */
1757
- RegionalAuthority["SwitzerlandNorth"] = "switzerlandnorth";
1758
- /** Uses the {@link RegionalAuthority} for the Azure 'switzerlandwest' region. */
1759
- RegionalAuthority["SwitzerlandWest"] = "switzerlandwest";
1760
- /** Uses the {@link RegionalAuthority} for the Azure 'germanynorth' region. */
1761
- RegionalAuthority["GermanyNorth"] = "germanynorth";
1762
- /** Uses the {@link RegionalAuthority} for the Azure 'germanywestcentral' region. */
1763
- RegionalAuthority["GermanyWestCentral"] = "germanywestcentral";
1764
- /** Uses the {@link RegionalAuthority} for the Azure 'norwaywest' region. */
1765
- RegionalAuthority["NorwayWest"] = "norwaywest";
1766
- /** Uses the {@link RegionalAuthority} for the Azure 'norwayeast' region. */
1767
- RegionalAuthority["NorwayEast"] = "norwayeast";
1768
- /** Uses the {@link RegionalAuthority} for the Azure 'eastasia' region. */
1769
- RegionalAuthority["AsiaEast"] = "eastasia";
1770
- /** Uses the {@link RegionalAuthority} for the Azure 'southeastasia' region. */
1771
- RegionalAuthority["AsiaSouthEast"] = "southeastasia";
1772
- /** Uses the {@link RegionalAuthority} for the Azure 'japaneast' region. */
1773
- RegionalAuthority["JapanEast"] = "japaneast";
1774
- /** Uses the {@link RegionalAuthority} for the Azure 'japanwest' region. */
1775
- RegionalAuthority["JapanWest"] = "japanwest";
1776
- /** Uses the {@link RegionalAuthority} for the Azure 'australiaeast' region. */
1777
- RegionalAuthority["AustraliaEast"] = "australiaeast";
1778
- /** Uses the {@link RegionalAuthority} for the Azure 'australiasoutheast' region. */
1779
- RegionalAuthority["AustraliaSouthEast"] = "australiasoutheast";
1780
- /** Uses the {@link RegionalAuthority} for the Azure 'australiacentral' region. */
1781
- RegionalAuthority["AustraliaCentral"] = "australiacentral";
1782
- /** Uses the {@link RegionalAuthority} for the Azure 'australiacentral2' region. */
1783
- RegionalAuthority["AustraliaCentral2"] = "australiacentral2";
1784
- /** Uses the {@link RegionalAuthority} for the Azure 'centralindia' region. */
1785
- RegionalAuthority["IndiaCentral"] = "centralindia";
1786
- /** Uses the {@link RegionalAuthority} for the Azure 'southindia' region. */
1787
- RegionalAuthority["IndiaSouth"] = "southindia";
1788
- /** Uses the {@link RegionalAuthority} for the Azure 'westindia' region. */
1789
- RegionalAuthority["IndiaWest"] = "westindia";
1790
- /** Uses the {@link RegionalAuthority} for the Azure 'koreasouth' region. */
1791
- RegionalAuthority["KoreaSouth"] = "koreasouth";
1792
- /** Uses the {@link RegionalAuthority} for the Azure 'koreacentral' region. */
1793
- RegionalAuthority["KoreaCentral"] = "koreacentral";
1794
- /** Uses the {@link RegionalAuthority} for the Azure 'uaecentral' region. */
1795
- RegionalAuthority["UAECentral"] = "uaecentral";
1796
- /** Uses the {@link RegionalAuthority} for the Azure 'uaenorth' region. */
1797
- RegionalAuthority["UAENorth"] = "uaenorth";
1798
- /** Uses the {@link RegionalAuthority} for the Azure 'southafricanorth' region. */
1799
- RegionalAuthority["SouthAfricaNorth"] = "southafricanorth";
1800
- /** Uses the {@link RegionalAuthority} for the Azure 'southafricawest' region. */
1801
- RegionalAuthority["SouthAfricaWest"] = "southafricawest";
1802
- /** Uses the {@link RegionalAuthority} for the Azure 'chinanorth' region. */
1803
- RegionalAuthority["ChinaNorth"] = "chinanorth";
1804
- /** Uses the {@link RegionalAuthority} for the Azure 'chinaeast' region. */
1805
- RegionalAuthority["ChinaEast"] = "chinaeast";
1806
- /** Uses the {@link RegionalAuthority} for the Azure 'chinanorth2' region. */
1807
- RegionalAuthority["ChinaNorth2"] = "chinanorth2";
1808
- /** Uses the {@link RegionalAuthority} for the Azure 'chinaeast2' region. */
1809
- RegionalAuthority["ChinaEast2"] = "chinaeast2";
1810
- /** Uses the {@link RegionalAuthority} for the Azure 'germanycentral' region. */
1811
- RegionalAuthority["GermanyCentral"] = "germanycentral";
1812
- /** Uses the {@link RegionalAuthority} for the Azure 'germanynortheast' region. */
1813
- RegionalAuthority["GermanyNorthEast"] = "germanynortheast";
1814
- /** Uses the {@link RegionalAuthority} for the Azure 'usgovvirginia' region. */
1815
- RegionalAuthority["GovernmentUSVirginia"] = "usgovvirginia";
1816
- /** Uses the {@link RegionalAuthority} for the Azure 'usgoviowa' region. */
1817
- RegionalAuthority["GovernmentUSIowa"] = "usgoviowa";
1818
- /** Uses the {@link RegionalAuthority} for the Azure 'usgovarizona' region. */
1819
- RegionalAuthority["GovernmentUSArizona"] = "usgovarizona";
1820
- /** Uses the {@link RegionalAuthority} for the Azure 'usgovtexas' region. */
1821
- RegionalAuthority["GovernmentUSTexas"] = "usgovtexas";
1822
- /** Uses the {@link RegionalAuthority} for the Azure 'usdodeast' region. */
1823
- RegionalAuthority["GovernmentUSDodEast"] = "usdodeast";
1824
- /** Uses the {@link RegionalAuthority} for the Azure 'usdodcentral' region. */
1825
- RegionalAuthority["GovernmentUSDodCentral"] = "usdodcentral";
1826
- })(RegionalAuthority || (RegionalAuthority = {}));
1767
+ const msalLogger = credentialLogger("MsalClient");
1827
1768
  /**
1828
- * Calculates the correct regional authority based on the supplied value
1829
- * and the AZURE_REGIONAL_AUTHORITY_NAME environment variable.
1769
+ * Generates the configuration for MSAL (Microsoft Authentication Library).
1830
1770
  *
1831
- * Values will be returned verbatim, except for {@link RegionalAuthority.AutoDiscoverRegion}
1832
- * which is mapped to a value MSAL can understand.
1833
- *
1834
- * @internal
1771
+ * @param clientId - The client ID of the application.
1772
+ * @param tenantId - The tenant ID of the Azure Active Directory.
1773
+ * @param msalClientOptions - Optional. Additional options for creating the MSAL client.
1774
+ * @returns The MSAL configuration object.
1835
1775
  */
1836
- function calculateRegionalAuthority(regionalAuthority) {
1837
- var _a, _b;
1838
- let azureRegion = regionalAuthority;
1839
- if (azureRegion === undefined &&
1840
- ((_b = (_a = globalThis.process) === null || _a === void 0 ? void 0 : _a.env) === null || _b === void 0 ? void 0 : _b.AZURE_REGIONAL_AUTHORITY_NAME) !== undefined) {
1841
- azureRegion = process.env.AZURE_REGIONAL_AUTHORITY_NAME;
1842
- }
1843
- if (azureRegion === RegionalAuthority.AutoDiscoverRegion) {
1844
- return "AUTO_DISCOVER";
1845
- }
1846
- return azureRegion;
1776
+ function generateMsalConfiguration(clientId, tenantId, msalClientOptions = {}) {
1777
+ var _a, _b, _c;
1778
+ const resolvedTenant = resolveTenantId(msalLogger, tenantId, clientId);
1779
+ // TODO: move and reuse getIdentityClientAuthorityHost
1780
+ const authority = getAuthority(resolvedTenant, (_a = msalClientOptions.authorityHost) !== null && _a !== void 0 ? _a : process.env.AZURE_AUTHORITY_HOST);
1781
+ const httpClient = new IdentityClient(Object.assign(Object.assign({}, msalClientOptions.tokenCredentialOptions), { authorityHost: authority, loggingOptions: msalClientOptions.loggingOptions }));
1782
+ const msalConfig = {
1783
+ auth: {
1784
+ clientId,
1785
+ authority,
1786
+ knownAuthorities: getKnownAuthorities(resolvedTenant, authority, msalClientOptions.disableInstanceDiscovery),
1787
+ },
1788
+ system: {
1789
+ networkClient: httpClient,
1790
+ loggerOptions: {
1791
+ loggerCallback: defaultLoggerCallback((_b = msalClientOptions.logger) !== null && _b !== void 0 ? _b : msalLogger),
1792
+ logLevel: getMSALLogLevel(logger$q.getLogLevel()),
1793
+ piiLoggingEnabled: (_c = msalClientOptions.loggingOptions) === null || _c === void 0 ? void 0 : _c.enableUnsafeSupportLogging,
1794
+ },
1795
+ },
1796
+ };
1797
+ return msalConfig;
1847
1798
  }
1848
-
1849
- // Copyright (c) Microsoft Corporation.
1850
- // Licensed under the MIT license.
1851
1799
  /**
1852
- * MSAL partial base client for Node.js.
1800
+ * Creates an instance of the MSAL (Microsoft Authentication Library) client.
1853
1801
  *
1854
- * It completes the input configuration with some default values.
1855
- * It also provides with utility protected methods that can be used from any of the clients,
1856
- * which includes handlers for successful responses and errors.
1802
+ * @param clientId - The client ID of the application.
1803
+ * @param tenantId - The tenant ID of the Azure Active Directory.
1804
+ * @param createMsalClientOptions - Optional. Additional options for creating the MSAL client.
1805
+ * @returns An instance of the MSAL client.
1857
1806
  *
1858
- * @internal
1807
+ * @public
1859
1808
  */
1860
- class MsalNode {
1861
- constructor(options) {
1862
- var _a, _b, _c, _d, _e, _f;
1863
- this.app = {};
1864
- this.caeApp = {};
1865
- this.requiresConfidential = false;
1866
- this.logger = options.logger;
1867
- this.msalConfig = this.defaultNodeMsalConfig(options);
1868
- this.tenantId = resolveTenantId(options.logger, options.tenantId, options.clientId);
1869
- this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds((_a = options === null || options === void 0 ? void 0 : options.tokenCredentialOptions) === null || _a === void 0 ? void 0 : _a.additionallyAllowedTenants);
1870
- this.clientId = this.msalConfig.auth.clientId;
1871
- if (options === null || options === void 0 ? void 0 : options.getAssertion) {
1872
- this.getAssertion = options.getAssertion;
1873
- }
1874
- this.enableBroker = (_b = options === null || options === void 0 ? void 0 : options.brokerOptions) === null || _b === void 0 ? void 0 : _b.enabled;
1875
- this.enableMsaPassthrough = (_c = options === null || options === void 0 ? void 0 : options.brokerOptions) === null || _c === void 0 ? void 0 : _c.legacyEnableMsaPassthrough;
1876
- this.parentWindowHandle = (_d = options.brokerOptions) === null || _d === void 0 ? void 0 : _d.parentWindowHandle;
1877
- // If persistence has been configured
1878
- if (persistenceProvider !== undefined && ((_e = options.tokenCachePersistenceOptions) === null || _e === void 0 ? void 0 : _e.enabled)) {
1879
- const cacheBaseName = options.tokenCachePersistenceOptions.name || DEFAULT_TOKEN_CACHE_NAME;
1880
- const nonCaeOptions = Object.assign({ name: `${cacheBaseName}.${CACHE_NON_CAE_SUFFIX}` }, options.tokenCachePersistenceOptions);
1881
- const caeOptions = Object.assign({ name: `${cacheBaseName}.${CACHE_CAE_SUFFIX}` }, options.tokenCachePersistenceOptions);
1882
- this.createCachePlugin = () => persistenceProvider(nonCaeOptions);
1883
- this.createCachePluginCae = () => persistenceProvider(caeOptions);
1884
- }
1885
- else if ((_f = options.tokenCachePersistenceOptions) === null || _f === void 0 ? void 0 : _f.enabled) {
1886
- throw new Error([
1887
- "Persistent token caching was requested, but no persistence provider was configured.",
1888
- "You must install the identity-cache-persistence plugin package (`npm install --save @azure/identity-cache-persistence`)",
1889
- "and enable it by importing `useIdentityPlugin` from `@azure/identity` and calling",
1890
- "`useIdentityPlugin(cachePersistencePlugin)` before using `tokenCachePersistenceOptions`.",
1891
- ].join(" "));
1809
+ function createMsalClient(clientId, tenantId, createMsalClientOptions = {}) {
1810
+ const state = {
1811
+ msalConfig: generateMsalConfiguration(clientId, tenantId, createMsalClientOptions),
1812
+ cachedAccount: createMsalClientOptions.authenticationRecord
1813
+ ? publicToMsal(createMsalClientOptions.authenticationRecord)
1814
+ : null,
1815
+ pluginConfiguration: msalPlugins.generatePluginConfiguration(createMsalClientOptions),
1816
+ };
1817
+ const confidentialApps = new Map();
1818
+ async function getConfidentialApp(options = {}) {
1819
+ const appKey = options.enableCae ? "CAE" : "default";
1820
+ let confidentialClientApp = confidentialApps.get(appKey);
1821
+ if (confidentialClientApp) {
1822
+ return confidentialClientApp;
1823
+ }
1824
+ // Initialize a new app and cache it
1825
+ const cachePlugin = options.enableCae
1826
+ ? state.pluginConfiguration.cache.cachePluginCae
1827
+ : state.pluginConfiguration.cache.cachePlugin;
1828
+ state.msalConfig.auth.clientCapabilities = options.enableCae ? ["cp1"] : undefined;
1829
+ confidentialClientApp = new msalCommon__namespace.ConfidentialClientApplication(Object.assign(Object.assign({}, state.msalConfig), { broker: { nativeBrokerPlugin: state.pluginConfiguration.broker.nativeBrokerPlugin }, cache: { cachePlugin: await cachePlugin } }));
1830
+ confidentialApps.set(appKey, confidentialClientApp);
1831
+ return confidentialClientApp;
1832
+ }
1833
+ async function getTokenSilent(app, scopes, options = {}) {
1834
+ if (state.cachedAccount === null) {
1835
+ const cache = app.getTokenCache();
1836
+ const accounts = await cache.getAllAccounts();
1837
+ if (accounts === undefined || accounts.length === 0) {
1838
+ throw new AuthenticationRequiredError({ scopes });
1839
+ }
1840
+ if (accounts.length > 1) {
1841
+ msalLogger.info(`More than one account was found authenticated for this Client ID and Tenant ID.
1842
+ However, no "authenticationRecord" has been provided for this credential,
1843
+ therefore we're unable to pick between these accounts.
1844
+ A new login attempt will be requested, to ensure the correct account is picked.
1845
+ To work with multiple accounts for the same Client ID and Tenant ID, please provide an "authenticationRecord" when initializing a credential to prevent this from happening.`);
1846
+ throw new AuthenticationRequiredError({ scopes });
1847
+ }
1848
+ state.cachedAccount = accounts[0];
1892
1849
  }
1893
- // If broker has not been configured
1894
- if (!hasNativeBroker() && this.enableBroker) {
1895
- throw new Error([
1896
- "Broker for WAM was requested to be enabled, but no native broker was configured.",
1897
- "You must install the identity-broker plugin package (`npm install --save @azure/identity-broker`)",
1898
- "and enable it by importing `useIdentityPlugin` from `@azure/identity` and calling",
1899
- "`useIdentityPlugin(createNativeBrokerPlugin())` before using `enableBroker`.",
1900
- ].join(" "));
1850
+ // Keep track and reuse the claims we received across challenges
1851
+ if (options.claims) {
1852
+ state.cachedClaims = options.claims;
1901
1853
  }
1902
- this.azureRegion = calculateRegionalAuthority(options.regionalAuthority);
1854
+ // TODO: port over changes for broker
1855
+ // https://github.com/Azure/azure-sdk-for-js/blob/727a7208251961b5036d8e1d86edaa944c42e3d6/sdk/identity/identity/src/msal/nodeFlows/msalNodeCommon.ts#L383-L395
1856
+ msalLogger.getToken.info("Attempting to acquire token silently");
1857
+ return app.acquireTokenSilent({
1858
+ account: state.cachedAccount,
1859
+ scopes,
1860
+ claims: state.cachedClaims,
1861
+ });
1903
1862
  }
1904
1863
  /**
1905
- * Generates a MSAL configuration that generally works for Node.js
1864
+ * Performs silent authentication using MSAL to acquire an access token.
1865
+ * If silent authentication fails, falls back to interactive authentication.
1866
+ *
1867
+ * @param msalApp - The MSAL application instance.
1868
+ * @param scopes - The scopes for which to acquire the access token.
1869
+ * @param options - The options for acquiring the access token.
1870
+ * @param onAuthenticationRequired - A callback function to handle interactive authentication when silent authentication fails.
1871
+ * @returns A promise that resolves to an AccessToken object containing the access token and its expiration timestamp.
1906
1872
  */
1907
- defaultNodeMsalConfig(options) {
1873
+ async function withSilentAuthentication(msalApp, scopes, options, onAuthenticationRequired) {
1908
1874
  var _a;
1909
- const clientId = options.clientId || DeveloperSignOnClientId;
1910
- const tenantId = resolveTenantId(options.logger, options.tenantId, options.clientId);
1911
- this.authorityHost = options.authorityHost || process.env.AZURE_AUTHORITY_HOST;
1912
- const authority = getAuthority(tenantId, this.authorityHost);
1913
- this.identityClient = new IdentityClient(Object.assign(Object.assign({}, options.tokenCredentialOptions), { authorityHost: authority, loggingOptions: options.loggingOptions }));
1914
- const clientCapabilities = [];
1915
- return {
1916
- auth: {
1917
- clientId,
1918
- authority,
1919
- knownAuthorities: getKnownAuthorities(tenantId, authority, options.disableInstanceDiscovery),
1920
- clientCapabilities,
1921
- },
1922
- // Cache is defined in this.prepare();
1923
- system: {
1924
- networkClient: this.identityClient,
1925
- loggerOptions: {
1926
- loggerCallback: defaultLoggerCallback(options.logger),
1927
- logLevel: getMSALLogLevel(logger$q.getLogLevel()),
1928
- piiLoggingEnabled: (_a = options.loggingOptions) === null || _a === void 0 ? void 0 : _a.enableUnsafeSupportLogging,
1929
- },
1930
- },
1931
- };
1932
- }
1933
- getApp(appType, enableCae) {
1934
- const app = enableCae ? this.caeApp : this.app;
1935
- if (appType === "publicFirst") {
1936
- return (app.public || app.confidential);
1937
- }
1938
- else if (appType === "confidentialFirst") {
1939
- return (app.confidential || app.public);
1875
+ let response = null;
1876
+ try {
1877
+ response = await getTokenSilent(msalApp, scopes, options);
1940
1878
  }
1941
- else if (appType === "confidential") {
1942
- return app.confidential;
1943
- }
1944
- else {
1945
- return app.public;
1946
- }
1947
- }
1948
- /**
1949
- * Prepares the MSAL applications.
1950
- */
1951
- async init(options) {
1952
- if (options === null || options === void 0 ? void 0 : options.abortSignal) {
1953
- options.abortSignal.addEventListener("abort", () => {
1954
- // This will abort any pending request in the IdentityClient,
1955
- // based on the received or generated correlationId
1956
- this.identityClient.abortRequests(options.correlationId);
1957
- });
1958
- }
1959
- const app = (options === null || options === void 0 ? void 0 : options.enableCae) ? this.caeApp : this.app;
1960
- if (options === null || options === void 0 ? void 0 : options.enableCae) {
1961
- this.msalConfig.auth.clientCapabilities = ["cp1"];
1962
- }
1963
- if (app.public || app.confidential) {
1964
- return;
1965
- }
1966
- if ((options === null || options === void 0 ? void 0 : options.enableCae) && this.createCachePluginCae !== undefined) {
1967
- this.msalConfig.cache = {
1968
- cachePlugin: await this.createCachePluginCae(),
1969
- };
1970
- }
1971
- if (this.createCachePlugin !== undefined) {
1972
- this.msalConfig.cache = {
1973
- cachePlugin: await this.createCachePlugin(),
1974
- };
1975
- }
1976
- if (hasNativeBroker() && this.enableBroker) {
1977
- this.msalConfig.broker = {
1978
- nativeBrokerPlugin: nativeBrokerInfo.broker,
1979
- };
1980
- if (!this.parentWindowHandle) {
1981
- // error should have been thrown from within the constructor of InteractiveBrowserCredential
1982
- this.logger.warning("Parent window handle is not specified for the broker. This may cause unexpected behavior. Please provide the parentWindowHandle.");
1983
- }
1984
- }
1985
- if (options === null || options === void 0 ? void 0 : options.enableCae) {
1986
- this.caeApp.public = new msalCommon__namespace.PublicClientApplication(this.msalConfig);
1987
- }
1988
- else {
1989
- this.app.public = new msalCommon__namespace.PublicClientApplication(this.msalConfig);
1990
- }
1991
- if (this.getAssertion) {
1992
- this.msalConfig.auth.clientAssertion = await this.getAssertion();
1993
- }
1994
- // The confidential client requires either a secret, assertion or certificate.
1995
- if (this.msalConfig.auth.clientSecret ||
1996
- this.msalConfig.auth.clientAssertion ||
1997
- this.msalConfig.auth.clientCertificate) {
1998
- if (options === null || options === void 0 ? void 0 : options.enableCae) {
1999
- this.caeApp.confidential = new msalCommon__namespace.ConfidentialClientApplication(this.msalConfig);
2000
- }
2001
- else {
2002
- this.app.confidential = new msalCommon__namespace.ConfidentialClientApplication(this.msalConfig);
2003
- }
2004
- }
2005
- else {
2006
- if (this.requiresConfidential) {
2007
- throw new Error("Unable to generate the MSAL confidential client. Missing either the client's secret, certificate or assertion.");
2008
- }
2009
- }
2010
- }
2011
- /**
2012
- * Allows the cancellation of a MSAL request.
2013
- */
2014
- withCancellation(promise, abortSignal, onCancel) {
2015
- return new Promise((resolve, reject) => {
2016
- promise
2017
- .then((msalToken) => {
2018
- return resolve(msalToken);
2019
- })
2020
- .catch(reject);
2021
- if (abortSignal) {
2022
- abortSignal.addEventListener("abort", () => {
2023
- onCancel === null || onCancel === void 0 ? void 0 : onCancel();
2024
- });
2025
- }
2026
- });
2027
- }
2028
- /**
2029
- * Returns the existing account, attempts to load the account from MSAL.
2030
- */
2031
- async getActiveAccount(enableCae = false) {
2032
- if (this.account) {
2033
- return this.account;
2034
- }
2035
- const cache = this.getApp("confidentialFirst", enableCae).getTokenCache();
2036
- const accountsByTenant = await (cache === null || cache === void 0 ? void 0 : cache.getAllAccounts());
2037
- if (!accountsByTenant) {
2038
- return;
2039
- }
2040
- if (accountsByTenant.length === 1) {
2041
- this.account = msalToPublic(this.clientId, accountsByTenant[0]);
2042
- }
2043
- else {
2044
- this.logger
2045
- .info(`More than one account was found authenticated for this Client ID and Tenant ID.
2046
- However, no "authenticationRecord" has been provided for this credential,
2047
- therefore we're unable to pick between these accounts.
2048
- A new login attempt will be requested, to ensure the correct account is picked.
2049
- To work with multiple accounts for the same Client ID and Tenant ID, please provide an "authenticationRecord" when initializing a credential to prevent this from happening.`);
2050
- return;
2051
- }
2052
- return this.account;
2053
- }
2054
- /**
2055
- * Attempts to retrieve a token from cache.
2056
- */
2057
- async getTokenSilent(scopes, options) {
2058
- var _a, _b, _c;
2059
- await this.getActiveAccount(options === null || options === void 0 ? void 0 : options.enableCae);
2060
- if (!this.account) {
2061
- throw new AuthenticationRequiredError({
2062
- scopes,
2063
- getTokenOptions: options,
2064
- message: "Silent authentication failed. We couldn't retrieve an active account from the cache.",
2065
- });
2066
- }
2067
- const silentRequest = {
2068
- // To be able to re-use the account, the Token Cache must also have been provided.
2069
- account: publicToMsal(this.account),
2070
- correlationId: options === null || options === void 0 ? void 0 : options.correlationId,
2071
- scopes,
2072
- authority: options === null || options === void 0 ? void 0 : options.authority,
2073
- claims: options === null || options === void 0 ? void 0 : options.claims,
2074
- };
2075
- if (hasNativeBroker() && this.enableBroker) {
2076
- if (!silentRequest.tokenQueryParameters) {
2077
- silentRequest.tokenQueryParameters = {};
2078
- }
2079
- if (!this.parentWindowHandle) {
2080
- // error should have been thrown from within the constructor of InteractiveBrowserCredential
2081
- this.logger.warning("Parent window handle is not specified for the broker. This may cause unexpected behavior. Please provide the parentWindowHandle.");
2082
- }
2083
- if (this.enableMsaPassthrough) {
2084
- silentRequest.tokenQueryParameters["msal_request_type"] = "consumer_passthrough";
2085
- }
2086
- }
2087
- try {
2088
- this.logger.info("Attempting to acquire token silently");
2089
- /**
2090
- * The following code to retrieve all accounts is done as a workaround in an attempt to force the
2091
- * refresh of the token cache with the token and the account passed in through the
2092
- * `authenticationRecord` parameter. See issue - https://github.com/Azure/azure-sdk-for-js/issues/24349#issuecomment-1496715651
2093
- * This workaround serves as a workaround for silent authentication not happening when authenticationRecord is passed.
2094
- */
2095
- await ((_a = this.getApp("publicFirst", options === null || options === void 0 ? void 0 : options.enableCae)) === null || _a === void 0 ? void 0 : _a.getTokenCache().getAllAccounts());
2096
- const response = (_c = (await ((_b = this.getApp("confidential", options === null || options === void 0 ? void 0 : options.enableCae)) === null || _b === void 0 ? void 0 : _b.acquireTokenSilent(silentRequest)))) !== null && _c !== void 0 ? _c : (await this.getApp("public", options === null || options === void 0 ? void 0 : options.enableCae).acquireTokenSilent(silentRequest));
2097
- return this.handleResult(scopes, response || undefined);
2098
- }
2099
- catch (err) {
2100
- throw handleMsalError(scopes, err, options);
2101
- }
2102
- }
2103
- /**
2104
- * Wrapper around each MSAL flow get token operation: doGetToken.
2105
- * If disableAutomaticAuthentication is sent through the constructor, it will prevent MSAL from requesting the user input.
2106
- */
2107
- async getToken(scopes, options = {}) {
2108
- const tenantId = processMultiTenantRequest(this.tenantId, options, this.additionallyAllowedTenantIds) ||
2109
- this.tenantId;
2110
- options.authority = getAuthority(tenantId, this.authorityHost);
2111
- options.correlationId = (options === null || options === void 0 ? void 0 : options.correlationId) || randomUUID();
2112
- await this.init(options);
2113
- try {
2114
- // MSAL now caches tokens based on their claims,
2115
- // so now one has to keep track fo claims in order to retrieve the newer tokens from acquireTokenSilent
2116
- // This update happened on PR: https://github.com/AzureAD/microsoft-authentication-library-for-js/pull/4533
2117
- const optionsClaims = options.claims;
2118
- if (optionsClaims) {
2119
- this.cachedClaims = optionsClaims;
2120
- }
2121
- if (this.cachedClaims && !optionsClaims) {
2122
- options.claims = this.cachedClaims;
2123
- }
2124
- // We don't return the promise since we want to catch errors right here.
2125
- return await this.getTokenSilent(scopes, options);
2126
- }
2127
- catch (err) {
2128
- if (err.name !== "AuthenticationRequiredError") {
2129
- throw err;
1879
+ catch (e) {
1880
+ if (e.name !== "AuthenticationRequiredError") {
1881
+ throw e;
2130
1882
  }
2131
- if (options === null || options === void 0 ? void 0 : options.disableAutomaticAuthentication) {
1883
+ if (createMsalClientOptions.disableAutomaticAuthentication) {
2132
1884
  throw new AuthenticationRequiredError({
2133
1885
  scopes,
2134
1886
  getTokenOptions: options,
2135
1887
  message: "Automatic authentication has been disabled. You may call the authentication() method.",
2136
1888
  });
2137
1889
  }
2138
- this.logger.info(`Silent authentication failed, falling back to interactive method.`);
2139
- return this.doGetToken(scopes, options);
2140
1890
  }
2141
- }
2142
- /**
2143
- * Handles the MSAL authentication result.
2144
- * If the result has an account, we update the local account reference.
2145
- * If the token received is invalid, an error will be thrown depending on what's missing.
2146
- */
2147
- handleResult(scopes, result, getTokenOptions) {
2148
- if (result === null || result === void 0 ? void 0 : result.account) {
2149
- this.account = msalToPublic(this.clientId, result.account);
1891
+ // Silent authentication failed
1892
+ if (response === null) {
1893
+ try {
1894
+ response = await onAuthenticationRequired();
1895
+ }
1896
+ catch (err) {
1897
+ throw handleMsalError(scopes, err, options);
1898
+ }
2150
1899
  }
2151
- ensureValidMsalToken(scopes, result, getTokenOptions);
2152
- this.logger.getToken.info(formatSuccess(scopes));
1900
+ // At this point we should have a token, process it
1901
+ ensureValidMsalToken(scopes, response, options);
1902
+ state.cachedAccount = (_a = response === null || response === void 0 ? void 0 : response.account) !== null && _a !== void 0 ? _a : null;
1903
+ msalLogger.getToken.info(formatSuccess(scopes));
2153
1904
  return {
2154
- token: result.accessToken,
2155
- expiresOnTimestamp: result.expiresOn.getTime(),
1905
+ token: response.accessToken,
1906
+ expiresOnTimestamp: response.expiresOn.getTime(),
2156
1907
  };
2157
1908
  }
2158
- }
2159
-
2160
- // Copyright (c) Microsoft Corporation.
2161
- // Licensed under the MIT license.
2162
- /**
2163
- * MSAL client assertion client. Calls to MSAL's confidential application's `acquireTokenByClientCredential` during `doGetToken`.
2164
- * @internal
2165
- */
2166
- class MsalClientAssertion extends MsalNode {
2167
- constructor(options) {
2168
- super(options);
2169
- this.requiresConfidential = true;
2170
- this.getAssertion = options.getAssertion;
1909
+ async function getTokenByClientSecret(scopes, clientSecret, options = {}) {
1910
+ msalLogger.getToken.info(`Attempting to acquire token using client secret`);
1911
+ state.msalConfig.auth.clientSecret = clientSecret;
1912
+ const msalApp = await getConfidentialApp(options);
1913
+ return withSilentAuthentication(msalApp, scopes, options, () => msalApp.acquireTokenByClientCredential({
1914
+ scopes,
1915
+ authority: state.msalConfig.auth.authority,
1916
+ claims: options === null || options === void 0 ? void 0 : options.claims,
1917
+ }));
2171
1918
  }
2172
- async doGetToken(scopes, options = {}) {
2173
- try {
2174
- const assertion = await this.getAssertion();
2175
- const result = await this.getApp("confidential", options.enableCae).acquireTokenByClientCredential({
2176
- scopes,
2177
- correlationId: options.correlationId,
2178
- azureRegion: this.azureRegion,
2179
- authority: options.authority,
2180
- claims: options.claims,
2181
- clientAssertion: assertion,
2182
- });
2183
- // The Client Credential flow does not return an account,
2184
- // so each time getToken gets called, we will have to acquire a new token through the service.
2185
- return this.handleResult(scopes, result || undefined);
2186
- }
2187
- catch (err) {
2188
- let err2 = err;
2189
- if (err === null || err === undefined) {
2190
- err2 = new Error(JSON.stringify(err));
2191
- }
2192
- else {
2193
- err2 = coreUtil.isError(err) ? err : new Error(String(err));
2194
- }
2195
- throw handleMsalError(scopes, err2, options);
2196
- }
1919
+ async function getTokenByClientAssertion(scopes, clientAssertion, options = {}) {
1920
+ msalLogger.getToken.info(`Attempting to acquire token using client assertion`);
1921
+ state.msalConfig.auth.clientAssertion = clientAssertion;
1922
+ const msalApp = await getConfidentialApp(options);
1923
+ return withSilentAuthentication(msalApp, scopes, options, () => msalApp.acquireTokenByClientCredential({
1924
+ scopes,
1925
+ authority: state.msalConfig.auth.authority,
1926
+ claims: options === null || options === void 0 ? void 0 : options.claims,
1927
+ clientAssertion,
1928
+ }));
2197
1929
  }
1930
+ async function getTokenByClientCertificate(scopes, certificate, options = {}) {
1931
+ msalLogger.getToken.info(`Attempting to acquire token using client certificate`);
1932
+ state.msalConfig.auth.clientCertificate = certificate;
1933
+ const msalApp = await getConfidentialApp(options);
1934
+ return withSilentAuthentication(msalApp, scopes, options, () => msalApp.acquireTokenByClientCredential({
1935
+ scopes,
1936
+ authority: state.msalConfig.auth.authority,
1937
+ claims: options === null || options === void 0 ? void 0 : options.claims,
1938
+ }));
1939
+ }
1940
+ return {
1941
+ getTokenByClientSecret,
1942
+ getTokenByClientAssertion,
1943
+ getTokenByClientCertificate,
1944
+ };
2198
1945
  }
2199
1946
 
2200
1947
  // Copyright (c) Microsoft Corporation.
@@ -2220,9 +1967,9 @@ class ClientAssertionCredential {
2220
1967
  }
2221
1968
  this.tenantId = tenantId;
2222
1969
  this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants);
2223
- this.clientId = clientId;
2224
1970
  this.options = options;
2225
- this.msalFlow = new MsalClientAssertion(Object.assign(Object.assign({}, options), { logger: logger$g, clientId: this.clientId, tenantId: this.tenantId, tokenCredentialOptions: this.options, getAssertion }));
1971
+ this.getAssertion = getAssertion;
1972
+ this.msalClient = createMsalClient(clientId, tenantId, Object.assign(Object.assign({}, options), { logger: logger$g, tokenCredentialOptions: this.options }));
2226
1973
  }
2227
1974
  /**
2228
1975
  * Authenticates with Microsoft Entra ID and returns an access token if successful.
@@ -2235,8 +1982,9 @@ class ClientAssertionCredential {
2235
1982
  async getToken(scopes, options = {}) {
2236
1983
  return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async (newOptions) => {
2237
1984
  newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger$g);
1985
+ const clientAssertion = await this.getAssertion();
2238
1986
  const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];
2239
- return this.msalFlow.getToken(arrayScopes, newOptions);
1987
+ return this.msalClient.getTokenByClientAssertion(arrayScopes, clientAssertion, newOptions);
2240
1988
  });
2241
1989
  }
2242
1990
  }
@@ -3318,243 +3066,601 @@ class ChainedTokenCredential {
3318
3066
 
3319
3067
  // Copyright (c) Microsoft Corporation.
3320
3068
  // Licensed under the MIT license.
3321
- const readFileAsync = util.promisify(fs.readFile);
3069
+ const credentialName$2 = "ClientCertificateCredential";
3070
+ const logger$8 = credentialLogger(credentialName$2);
3322
3071
  /**
3323
- * Tries to asynchronously load a certificate from the given path.
3072
+ * Enables authentication to Microsoft Entra ID using a PEM-encoded
3073
+ * certificate that is assigned to an App Registration. More information
3074
+ * on how to configure certificate authentication can be found here:
3075
+ *
3076
+ * https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-certificate-credentials#register-your-certificate-with-azure-ad
3324
3077
  *
3325
- * @param configuration - Either the PEM value or the path to the certificate.
3326
- * @param sendCertificateChain - Option to include x5c header for SubjectName and Issuer name authorization.
3327
- * @returns - The certificate parts, or `undefined` if the certificate could not be loaded.
3328
- * @internal
3329
3078
  */
3330
- async function parseCertificate(configuration, sendCertificateChain) {
3331
- const certificateParts = {};
3332
- const certificate = configuration
3333
- .certificate;
3334
- const certificatePath = configuration
3335
- .certificatePath;
3336
- certificateParts.certificateContents =
3337
- certificate || (await readFileAsync(certificatePath, "utf8"));
3338
- if (sendCertificateChain) {
3339
- certificateParts.x5c = certificateParts.certificateContents;
3340
- }
3341
- const certificatePattern = /(-+BEGIN CERTIFICATE-+)(\n\r?|\r\n?)([A-Za-z0-9+/\n\r]+=*)(\n\r?|\r\n?)(-+END CERTIFICATE-+)/g;
3342
- const publicKeys = [];
3343
- // Match all possible certificates, in the order they are in the file. These will form the chain that is used for x5c
3344
- let match;
3345
- do {
3346
- match = certificatePattern.exec(certificateParts.certificateContents);
3347
- if (match) {
3348
- publicKeys.push(match[3]);
3079
+ class ClientCertificateCredential {
3080
+ constructor(tenantId, clientId, certificatePathOrConfiguration, options = {}) {
3081
+ if (!tenantId || !clientId) {
3082
+ throw new Error(`${credentialName$2}: tenantId and clientId are required parameters.`);
3349
3083
  }
3350
- } while (match);
3351
- if (publicKeys.length === 0) {
3352
- throw new Error("The file at the specified path does not contain a PEM-encoded certificate.");
3353
- }
3354
- certificateParts.thumbprint = crypto.createHash("sha1")
3355
- .update(Buffer.from(publicKeys[0], "base64"))
3356
- .digest("hex")
3357
- .toUpperCase();
3358
- return certificateParts;
3359
- }
3360
- /**
3361
- * MSAL client certificate client. Calls to MSAL's confidential application's `acquireTokenByClientCredential` during `doGetToken`.
3362
- * @internal
3363
- */
3364
- class MsalClientCertificate extends MsalNode {
3365
- constructor(options) {
3366
- super(options);
3367
- this.requiresConfidential = true;
3368
- this.configuration = options.configuration;
3084
+ this.tenantId = tenantId;
3085
+ this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants);
3369
3086
  this.sendCertificateChain = options.sendCertificateChain;
3370
- }
3371
- // Changing the MSAL configuration asynchronously
3372
- async init(options) {
3373
- try {
3374
- const parts = await parseCertificate(this.configuration, this.sendCertificateChain);
3375
- let privateKey;
3376
- if (this.configuration.certificatePassword !== undefined) {
3377
- const privateKeyObject = crypto.createPrivateKey({
3378
- key: parts.certificateContents,
3379
- passphrase: this.configuration.certificatePassword,
3380
- format: "pem",
3381
- });
3382
- privateKey = privateKeyObject
3383
- .export({
3384
- format: "pem",
3385
- type: "pkcs8",
3386
- })
3387
- .toString();
3388
- }
3389
- else {
3390
- privateKey = parts.certificateContents;
3087
+ this.certificateConfiguration = Object.assign({}, (typeof certificatePathOrConfiguration === "string"
3088
+ ? {
3089
+ certificatePath: certificatePathOrConfiguration,
3391
3090
  }
3392
- this.msalConfig.auth.clientCertificate = {
3393
- thumbprint: parts.thumbprint,
3394
- privateKey: privateKey,
3395
- x5c: parts.x5c,
3396
- };
3091
+ : certificatePathOrConfiguration));
3092
+ const certificate = this.certificateConfiguration.certificate;
3093
+ const certificatePath = this.certificateConfiguration.certificatePath;
3094
+ if (!this.certificateConfiguration || !(certificate || certificatePath)) {
3095
+ throw new Error(`${credentialName$2}: Provide either a PEM certificate in string form, or the path to that certificate in the filesystem. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`);
3397
3096
  }
3398
- catch (error) {
3399
- this.logger.info(formatError("", error));
3400
- throw error;
3097
+ if (certificate && certificatePath) {
3098
+ throw new Error(`${credentialName$2}: To avoid unexpected behaviors, providing both the contents of a PEM certificate and the path to a PEM certificate is forbidden. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`);
3401
3099
  }
3402
- return super.init(options);
3100
+ this.msalClient = createMsalClient(clientId, tenantId, Object.assign(Object.assign({}, options), { logger: logger$8, tokenCredentialOptions: options }));
3403
3101
  }
3404
- async doGetToken(scopes, options = {}) {
3405
- try {
3406
- const clientCredReq = {
3407
- scopes,
3408
- correlationId: options.correlationId,
3409
- azureRegion: this.azureRegion,
3410
- authority: options.authority,
3411
- claims: options.claims,
3412
- };
3413
- const result = await this.getApp("confidential", options.enableCae).acquireTokenByClientCredential(clientCredReq);
3414
- // Even though we're providing the same default in memory persistence cache that we use for DeviceCodeCredential,
3415
- // The Client Credential flow does not return the account information from the authentication service,
3416
- // so each time getToken gets called, we will have to acquire a new token through the service.
3417
- return this.handleResult(scopes, result || undefined);
3102
+ /**
3103
+ * Authenticates with Microsoft Entra ID and returns an access token if successful.
3104
+ * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.
3105
+ *
3106
+ * @param scopes - The list of scopes for which the token will have access.
3107
+ * @param options - The options used to configure any requests this
3108
+ * TokenCredential implementation might make.
3109
+ */
3110
+ async getToken(scopes, options = {}) {
3111
+ return tracingClient.withSpan(`${credentialName$2}.getToken`, options, async (newOptions) => {
3112
+ newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger$8);
3113
+ const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];
3114
+ const certificate = await this.buildClientCertificate();
3115
+ return this.msalClient.getTokenByClientCertificate(arrayScopes, certificate, newOptions);
3116
+ });
3117
+ }
3118
+ async buildClientCertificate() {
3119
+ const parts = await this.parseCertificate();
3120
+ let privateKey;
3121
+ if (this.certificateConfiguration.certificatePassword !== undefined) {
3122
+ privateKey = crypto.createPrivateKey({
3123
+ key: parts.certificateContents,
3124
+ passphrase: this.certificateConfiguration.certificatePassword,
3125
+ format: "pem",
3126
+ })
3127
+ .export({
3128
+ format: "pem",
3129
+ type: "pkcs8",
3130
+ })
3131
+ .toString();
3418
3132
  }
3419
- catch (err) {
3420
- throw handleMsalError(scopes, err, options);
3133
+ else {
3134
+ privateKey = parts.certificateContents;
3421
3135
  }
3136
+ return {
3137
+ thumbprint: parts.thumbprint,
3138
+ privateKey,
3139
+ x5c: parts.x5c,
3140
+ };
3141
+ }
3142
+ async parseCertificate() {
3143
+ const certificate = this.certificateConfiguration.certificate;
3144
+ const certificatePath = this.certificateConfiguration.certificatePath;
3145
+ const certificateContents = certificate || (await promises.readFile(certificatePath, "utf8"));
3146
+ const x5c = this.sendCertificateChain ? certificateContents : undefined;
3147
+ const certificatePattern = /(-+BEGIN CERTIFICATE-+)(\n\r?|\r\n?)([A-Za-z0-9+/\n\r]+=*)(\n\r?|\r\n?)(-+END CERTIFICATE-+)/g;
3148
+ const publicKeys = [];
3149
+ // Match all possible certificates, in the order they are in the file. These will form the chain that is used for x5c
3150
+ let match;
3151
+ do {
3152
+ match = certificatePattern.exec(certificateContents);
3153
+ if (match) {
3154
+ publicKeys.push(match[3]);
3155
+ }
3156
+ } while (match);
3157
+ if (publicKeys.length === 0) {
3158
+ throw new Error("The file at the specified path does not contain a PEM-encoded certificate.");
3159
+ }
3160
+ const thumbprint = crypto.createHash("sha1")
3161
+ .update(Buffer.from(publicKeys[0], "base64"))
3162
+ .digest("hex")
3163
+ .toUpperCase();
3164
+ return {
3165
+ certificateContents,
3166
+ thumbprint,
3167
+ x5c,
3168
+ };
3422
3169
  }
3423
3170
  }
3424
3171
 
3425
3172
  // Copyright (c) Microsoft Corporation.
3426
3173
  // Licensed under the MIT license.
3427
- const credentialName$2 = "ClientCertificateCredential";
3428
- const logger$8 = credentialLogger(credentialName$2);
3174
+ const logger$7 = credentialLogger("ClientSecretCredential");
3429
3175
  /**
3430
- * Enables authentication to Microsoft Entra ID using a PEM-encoded
3431
- * certificate that is assigned to an App Registration. More information
3432
- * on how to configure certificate authentication can be found here:
3176
+ * Enables authentication to Microsoft Entra ID using a client secret
3177
+ * that was generated for an App Registration. More information on how
3178
+ * to configure a client secret can be found here:
3433
3179
  *
3434
- * https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-certificate-credentials#register-your-certificate-with-azure-ad
3180
+ * https://learn.microsoft.com/entra/identity-platform/quickstart-configure-app-access-web-apis#add-credentials-to-your-web-application
3435
3181
  *
3436
3182
  */
3437
- class ClientCertificateCredential {
3438
- constructor(tenantId, clientId, certificatePathOrConfiguration, options = {}) {
3439
- if (!tenantId || !clientId) {
3440
- throw new Error(`${credentialName$2}: tenantId and clientId are required parameters.`);
3183
+ class ClientSecretCredential {
3184
+ /**
3185
+ * Creates an instance of the ClientSecretCredential with the details
3186
+ * needed to authenticate against Microsoft Entra ID with a client
3187
+ * secret.
3188
+ *
3189
+ * @param tenantId - The Microsoft Entra tenant (directory) ID.
3190
+ * @param clientId - The client (application) ID of an App Registration in the tenant.
3191
+ * @param clientSecret - A client secret that was generated for the App Registration.
3192
+ * @param options - Options for configuring the client which makes the authentication request.
3193
+ */
3194
+ constructor(tenantId, clientId, clientSecret, options = {}) {
3195
+ if (!tenantId || !clientId || !clientSecret) {
3196
+ throw new Error("ClientSecretCredential: tenantId, clientId, and clientSecret are required parameters. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.");
3441
3197
  }
3198
+ this.clientSecret = clientSecret;
3442
3199
  this.tenantId = tenantId;
3443
3200
  this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants);
3444
- const configuration = Object.assign({}, (typeof certificatePathOrConfiguration === "string"
3445
- ? {
3446
- certificatePath: certificatePathOrConfiguration,
3201
+ this.msalClient = createMsalClient(clientId, tenantId, Object.assign(Object.assign({}, options), { logger: logger$7, tokenCredentialOptions: options }));
3202
+ }
3203
+ /**
3204
+ * Authenticates with Microsoft Entra ID and returns an access token if successful.
3205
+ * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.
3206
+ *
3207
+ * @param scopes - The list of scopes for which the token will have access.
3208
+ * @param options - The options used to configure any requests this
3209
+ * TokenCredential implementation might make.
3210
+ */
3211
+ async getToken(scopes, options = {}) {
3212
+ return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async (newOptions) => {
3213
+ newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger$7);
3214
+ const arrayScopes = ensureScopes(scopes);
3215
+ return this.msalClient.getTokenByClientSecret(arrayScopes, this.clientSecret, newOptions);
3216
+ });
3217
+ }
3218
+ }
3219
+
3220
+ // Copyright (c) Microsoft Corporation.
3221
+ // Licensed under the MIT license.
3222
+ /**
3223
+ * Helps specify a regional authority, or "AutoDiscoverRegion" to auto-detect the region.
3224
+ */
3225
+ var RegionalAuthority;
3226
+ (function (RegionalAuthority) {
3227
+ /** Instructs MSAL to attempt to discover the region */
3228
+ RegionalAuthority["AutoDiscoverRegion"] = "AutoDiscoverRegion";
3229
+ /** Uses the {@link RegionalAuthority} for the Azure 'westus' region. */
3230
+ RegionalAuthority["USWest"] = "westus";
3231
+ /** Uses the {@link RegionalAuthority} for the Azure 'westus2' region. */
3232
+ RegionalAuthority["USWest2"] = "westus2";
3233
+ /** Uses the {@link RegionalAuthority} for the Azure 'centralus' region. */
3234
+ RegionalAuthority["USCentral"] = "centralus";
3235
+ /** Uses the {@link RegionalAuthority} for the Azure 'eastus' region. */
3236
+ RegionalAuthority["USEast"] = "eastus";
3237
+ /** Uses the {@link RegionalAuthority} for the Azure 'eastus2' region. */
3238
+ RegionalAuthority["USEast2"] = "eastus2";
3239
+ /** Uses the {@link RegionalAuthority} for the Azure 'northcentralus' region. */
3240
+ RegionalAuthority["USNorthCentral"] = "northcentralus";
3241
+ /** Uses the {@link RegionalAuthority} for the Azure 'southcentralus' region. */
3242
+ RegionalAuthority["USSouthCentral"] = "southcentralus";
3243
+ /** Uses the {@link RegionalAuthority} for the Azure 'westcentralus' region. */
3244
+ RegionalAuthority["USWestCentral"] = "westcentralus";
3245
+ /** Uses the {@link RegionalAuthority} for the Azure 'canadacentral' region. */
3246
+ RegionalAuthority["CanadaCentral"] = "canadacentral";
3247
+ /** Uses the {@link RegionalAuthority} for the Azure 'canadaeast' region. */
3248
+ RegionalAuthority["CanadaEast"] = "canadaeast";
3249
+ /** Uses the {@link RegionalAuthority} for the Azure 'brazilsouth' region. */
3250
+ RegionalAuthority["BrazilSouth"] = "brazilsouth";
3251
+ /** Uses the {@link RegionalAuthority} for the Azure 'northeurope' region. */
3252
+ RegionalAuthority["EuropeNorth"] = "northeurope";
3253
+ /** Uses the {@link RegionalAuthority} for the Azure 'westeurope' region. */
3254
+ RegionalAuthority["EuropeWest"] = "westeurope";
3255
+ /** Uses the {@link RegionalAuthority} for the Azure 'uksouth' region. */
3256
+ RegionalAuthority["UKSouth"] = "uksouth";
3257
+ /** Uses the {@link RegionalAuthority} for the Azure 'ukwest' region. */
3258
+ RegionalAuthority["UKWest"] = "ukwest";
3259
+ /** Uses the {@link RegionalAuthority} for the Azure 'francecentral' region. */
3260
+ RegionalAuthority["FranceCentral"] = "francecentral";
3261
+ /** Uses the {@link RegionalAuthority} for the Azure 'francesouth' region. */
3262
+ RegionalAuthority["FranceSouth"] = "francesouth";
3263
+ /** Uses the {@link RegionalAuthority} for the Azure 'switzerlandnorth' region. */
3264
+ RegionalAuthority["SwitzerlandNorth"] = "switzerlandnorth";
3265
+ /** Uses the {@link RegionalAuthority} for the Azure 'switzerlandwest' region. */
3266
+ RegionalAuthority["SwitzerlandWest"] = "switzerlandwest";
3267
+ /** Uses the {@link RegionalAuthority} for the Azure 'germanynorth' region. */
3268
+ RegionalAuthority["GermanyNorth"] = "germanynorth";
3269
+ /** Uses the {@link RegionalAuthority} for the Azure 'germanywestcentral' region. */
3270
+ RegionalAuthority["GermanyWestCentral"] = "germanywestcentral";
3271
+ /** Uses the {@link RegionalAuthority} for the Azure 'norwaywest' region. */
3272
+ RegionalAuthority["NorwayWest"] = "norwaywest";
3273
+ /** Uses the {@link RegionalAuthority} for the Azure 'norwayeast' region. */
3274
+ RegionalAuthority["NorwayEast"] = "norwayeast";
3275
+ /** Uses the {@link RegionalAuthority} for the Azure 'eastasia' region. */
3276
+ RegionalAuthority["AsiaEast"] = "eastasia";
3277
+ /** Uses the {@link RegionalAuthority} for the Azure 'southeastasia' region. */
3278
+ RegionalAuthority["AsiaSouthEast"] = "southeastasia";
3279
+ /** Uses the {@link RegionalAuthority} for the Azure 'japaneast' region. */
3280
+ RegionalAuthority["JapanEast"] = "japaneast";
3281
+ /** Uses the {@link RegionalAuthority} for the Azure 'japanwest' region. */
3282
+ RegionalAuthority["JapanWest"] = "japanwest";
3283
+ /** Uses the {@link RegionalAuthority} for the Azure 'australiaeast' region. */
3284
+ RegionalAuthority["AustraliaEast"] = "australiaeast";
3285
+ /** Uses the {@link RegionalAuthority} for the Azure 'australiasoutheast' region. */
3286
+ RegionalAuthority["AustraliaSouthEast"] = "australiasoutheast";
3287
+ /** Uses the {@link RegionalAuthority} for the Azure 'australiacentral' region. */
3288
+ RegionalAuthority["AustraliaCentral"] = "australiacentral";
3289
+ /** Uses the {@link RegionalAuthority} for the Azure 'australiacentral2' region. */
3290
+ RegionalAuthority["AustraliaCentral2"] = "australiacentral2";
3291
+ /** Uses the {@link RegionalAuthority} for the Azure 'centralindia' region. */
3292
+ RegionalAuthority["IndiaCentral"] = "centralindia";
3293
+ /** Uses the {@link RegionalAuthority} for the Azure 'southindia' region. */
3294
+ RegionalAuthority["IndiaSouth"] = "southindia";
3295
+ /** Uses the {@link RegionalAuthority} for the Azure 'westindia' region. */
3296
+ RegionalAuthority["IndiaWest"] = "westindia";
3297
+ /** Uses the {@link RegionalAuthority} for the Azure 'koreasouth' region. */
3298
+ RegionalAuthority["KoreaSouth"] = "koreasouth";
3299
+ /** Uses the {@link RegionalAuthority} for the Azure 'koreacentral' region. */
3300
+ RegionalAuthority["KoreaCentral"] = "koreacentral";
3301
+ /** Uses the {@link RegionalAuthority} for the Azure 'uaecentral' region. */
3302
+ RegionalAuthority["UAECentral"] = "uaecentral";
3303
+ /** Uses the {@link RegionalAuthority} for the Azure 'uaenorth' region. */
3304
+ RegionalAuthority["UAENorth"] = "uaenorth";
3305
+ /** Uses the {@link RegionalAuthority} for the Azure 'southafricanorth' region. */
3306
+ RegionalAuthority["SouthAfricaNorth"] = "southafricanorth";
3307
+ /** Uses the {@link RegionalAuthority} for the Azure 'southafricawest' region. */
3308
+ RegionalAuthority["SouthAfricaWest"] = "southafricawest";
3309
+ /** Uses the {@link RegionalAuthority} for the Azure 'chinanorth' region. */
3310
+ RegionalAuthority["ChinaNorth"] = "chinanorth";
3311
+ /** Uses the {@link RegionalAuthority} for the Azure 'chinaeast' region. */
3312
+ RegionalAuthority["ChinaEast"] = "chinaeast";
3313
+ /** Uses the {@link RegionalAuthority} for the Azure 'chinanorth2' region. */
3314
+ RegionalAuthority["ChinaNorth2"] = "chinanorth2";
3315
+ /** Uses the {@link RegionalAuthority} for the Azure 'chinaeast2' region. */
3316
+ RegionalAuthority["ChinaEast2"] = "chinaeast2";
3317
+ /** Uses the {@link RegionalAuthority} for the Azure 'germanycentral' region. */
3318
+ RegionalAuthority["GermanyCentral"] = "germanycentral";
3319
+ /** Uses the {@link RegionalAuthority} for the Azure 'germanynortheast' region. */
3320
+ RegionalAuthority["GermanyNorthEast"] = "germanynortheast";
3321
+ /** Uses the {@link RegionalAuthority} for the Azure 'usgovvirginia' region. */
3322
+ RegionalAuthority["GovernmentUSVirginia"] = "usgovvirginia";
3323
+ /** Uses the {@link RegionalAuthority} for the Azure 'usgoviowa' region. */
3324
+ RegionalAuthority["GovernmentUSIowa"] = "usgoviowa";
3325
+ /** Uses the {@link RegionalAuthority} for the Azure 'usgovarizona' region. */
3326
+ RegionalAuthority["GovernmentUSArizona"] = "usgovarizona";
3327
+ /** Uses the {@link RegionalAuthority} for the Azure 'usgovtexas' region. */
3328
+ RegionalAuthority["GovernmentUSTexas"] = "usgovtexas";
3329
+ /** Uses the {@link RegionalAuthority} for the Azure 'usdodeast' region. */
3330
+ RegionalAuthority["GovernmentUSDodEast"] = "usdodeast";
3331
+ /** Uses the {@link RegionalAuthority} for the Azure 'usdodcentral' region. */
3332
+ RegionalAuthority["GovernmentUSDodCentral"] = "usdodcentral";
3333
+ })(RegionalAuthority || (RegionalAuthority = {}));
3334
+ /**
3335
+ * Calculates the correct regional authority based on the supplied value
3336
+ * and the AZURE_REGIONAL_AUTHORITY_NAME environment variable.
3337
+ *
3338
+ * Values will be returned verbatim, except for {@link RegionalAuthority.AutoDiscoverRegion}
3339
+ * which is mapped to a value MSAL can understand.
3340
+ *
3341
+ * @internal
3342
+ */
3343
+ function calculateRegionalAuthority(regionalAuthority) {
3344
+ var _a, _b;
3345
+ let azureRegion = regionalAuthority;
3346
+ if (azureRegion === undefined &&
3347
+ ((_b = (_a = globalThis.process) === null || _a === void 0 ? void 0 : _a.env) === null || _b === void 0 ? void 0 : _b.AZURE_REGIONAL_AUTHORITY_NAME) !== undefined) {
3348
+ azureRegion = process.env.AZURE_REGIONAL_AUTHORITY_NAME;
3349
+ }
3350
+ if (azureRegion === RegionalAuthority.AutoDiscoverRegion) {
3351
+ return "AUTO_DISCOVER";
3352
+ }
3353
+ return azureRegion;
3354
+ }
3355
+
3356
+ // Copyright (c) Microsoft Corporation.
3357
+ // Licensed under the MIT license.
3358
+ /**
3359
+ * MSAL partial base client for Node.js.
3360
+ *
3361
+ * It completes the input configuration with some default values.
3362
+ * It also provides with utility protected methods that can be used from any of the clients,
3363
+ * which includes handlers for successful responses and errors.
3364
+ *
3365
+ * @internal
3366
+ */
3367
+ class MsalNode {
3368
+ constructor(options) {
3369
+ var _a, _b, _c, _d, _e, _f;
3370
+ this.app = {};
3371
+ this.caeApp = {};
3372
+ this.requiresConfidential = false;
3373
+ this.logger = options.logger;
3374
+ this.msalConfig = this.defaultNodeMsalConfig(options);
3375
+ this.tenantId = resolveTenantId(options.logger, options.tenantId, options.clientId);
3376
+ this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds((_a = options === null || options === void 0 ? void 0 : options.tokenCredentialOptions) === null || _a === void 0 ? void 0 : _a.additionallyAllowedTenants);
3377
+ this.clientId = this.msalConfig.auth.clientId;
3378
+ if (options === null || options === void 0 ? void 0 : options.getAssertion) {
3379
+ this.getAssertion = options.getAssertion;
3380
+ }
3381
+ this.enableBroker = (_b = options === null || options === void 0 ? void 0 : options.brokerOptions) === null || _b === void 0 ? void 0 : _b.enabled;
3382
+ this.enableMsaPassthrough = (_c = options === null || options === void 0 ? void 0 : options.brokerOptions) === null || _c === void 0 ? void 0 : _c.legacyEnableMsaPassthrough;
3383
+ this.parentWindowHandle = (_d = options.brokerOptions) === null || _d === void 0 ? void 0 : _d.parentWindowHandle;
3384
+ // If persistence has been configured
3385
+ if (persistenceProvider !== undefined && ((_e = options.tokenCachePersistenceOptions) === null || _e === void 0 ? void 0 : _e.enabled)) {
3386
+ const cacheBaseName = options.tokenCachePersistenceOptions.name || DEFAULT_TOKEN_CACHE_NAME;
3387
+ const nonCaeOptions = Object.assign({ name: `${cacheBaseName}.${CACHE_NON_CAE_SUFFIX}` }, options.tokenCachePersistenceOptions);
3388
+ const caeOptions = Object.assign({ name: `${cacheBaseName}.${CACHE_CAE_SUFFIX}` }, options.tokenCachePersistenceOptions);
3389
+ this.createCachePlugin = () => persistenceProvider(nonCaeOptions);
3390
+ this.createCachePluginCae = () => persistenceProvider(caeOptions);
3391
+ }
3392
+ else if ((_f = options.tokenCachePersistenceOptions) === null || _f === void 0 ? void 0 : _f.enabled) {
3393
+ throw new Error([
3394
+ "Persistent token caching was requested, but no persistence provider was configured.",
3395
+ "You must install the identity-cache-persistence plugin package (`npm install --save @azure/identity-cache-persistence`)",
3396
+ "and enable it by importing `useIdentityPlugin` from `@azure/identity` and calling",
3397
+ "`useIdentityPlugin(cachePersistencePlugin)` before using `tokenCachePersistenceOptions`.",
3398
+ ].join(" "));
3399
+ }
3400
+ // If broker has not been configured
3401
+ if (!hasNativeBroker() && this.enableBroker) {
3402
+ throw new Error([
3403
+ "Broker for WAM was requested to be enabled, but no native broker was configured.",
3404
+ "You must install the identity-broker plugin package (`npm install --save @azure/identity-broker`)",
3405
+ "and enable it by importing `useIdentityPlugin` from `@azure/identity` and calling",
3406
+ "`useIdentityPlugin(createNativeBrokerPlugin())` before using `enableBroker`.",
3407
+ ].join(" "));
3408
+ }
3409
+ this.azureRegion = calculateRegionalAuthority(options.regionalAuthority);
3410
+ }
3411
+ /**
3412
+ * Generates a MSAL configuration that generally works for Node.js
3413
+ */
3414
+ defaultNodeMsalConfig(options) {
3415
+ var _a;
3416
+ const clientId = options.clientId || DeveloperSignOnClientId;
3417
+ const tenantId = resolveTenantId(options.logger, options.tenantId, options.clientId);
3418
+ this.authorityHost = options.authorityHost || process.env.AZURE_AUTHORITY_HOST;
3419
+ const authority = getAuthority(tenantId, this.authorityHost);
3420
+ this.identityClient = new IdentityClient(Object.assign(Object.assign({}, options.tokenCredentialOptions), { authorityHost: authority, loggingOptions: options.loggingOptions }));
3421
+ const clientCapabilities = [];
3422
+ return {
3423
+ auth: {
3424
+ clientId,
3425
+ authority,
3426
+ knownAuthorities: getKnownAuthorities(tenantId, authority, options.disableInstanceDiscovery),
3427
+ clientCapabilities,
3428
+ },
3429
+ // Cache is defined in this.prepare();
3430
+ system: {
3431
+ networkClient: this.identityClient,
3432
+ loggerOptions: {
3433
+ loggerCallback: defaultLoggerCallback(options.logger),
3434
+ logLevel: getMSALLogLevel(logger$q.getLogLevel()),
3435
+ piiLoggingEnabled: (_a = options.loggingOptions) === null || _a === void 0 ? void 0 : _a.enableUnsafeSupportLogging,
3436
+ },
3437
+ },
3438
+ };
3439
+ }
3440
+ getApp(appType, enableCae) {
3441
+ const app = enableCae ? this.caeApp : this.app;
3442
+ if (appType === "publicFirst") {
3443
+ return (app.public || app.confidential);
3444
+ }
3445
+ else if (appType === "confidentialFirst") {
3446
+ return (app.confidential || app.public);
3447
+ }
3448
+ else if (appType === "confidential") {
3449
+ return app.confidential;
3450
+ }
3451
+ else {
3452
+ return app.public;
3453
+ }
3454
+ }
3455
+ /**
3456
+ * Prepares the MSAL applications.
3457
+ */
3458
+ async init(options) {
3459
+ if (options === null || options === void 0 ? void 0 : options.abortSignal) {
3460
+ options.abortSignal.addEventListener("abort", () => {
3461
+ // This will abort any pending request in the IdentityClient,
3462
+ // based on the received or generated correlationId
3463
+ this.identityClient.abortRequests(options.correlationId);
3464
+ });
3465
+ }
3466
+ const app = (options === null || options === void 0 ? void 0 : options.enableCae) ? this.caeApp : this.app;
3467
+ if (options === null || options === void 0 ? void 0 : options.enableCae) {
3468
+ this.msalConfig.auth.clientCapabilities = ["cp1"];
3469
+ }
3470
+ if (app.public || app.confidential) {
3471
+ return;
3472
+ }
3473
+ if ((options === null || options === void 0 ? void 0 : options.enableCae) && this.createCachePluginCae !== undefined) {
3474
+ this.msalConfig.cache = {
3475
+ cachePlugin: await this.createCachePluginCae(),
3476
+ };
3477
+ }
3478
+ if (this.createCachePlugin !== undefined) {
3479
+ this.msalConfig.cache = {
3480
+ cachePlugin: await this.createCachePlugin(),
3481
+ };
3482
+ }
3483
+ if (hasNativeBroker() && this.enableBroker) {
3484
+ this.msalConfig.broker = {
3485
+ nativeBrokerPlugin: nativeBrokerInfo.broker,
3486
+ };
3487
+ if (!this.parentWindowHandle) {
3488
+ // error should have been thrown from within the constructor of InteractiveBrowserCredential
3489
+ this.logger.warning("Parent window handle is not specified for the broker. This may cause unexpected behavior. Please provide the parentWindowHandle.");
3490
+ }
3491
+ }
3492
+ if (options === null || options === void 0 ? void 0 : options.enableCae) {
3493
+ this.caeApp.public = new msalCommon__namespace.PublicClientApplication(this.msalConfig);
3494
+ }
3495
+ else {
3496
+ this.app.public = new msalCommon__namespace.PublicClientApplication(this.msalConfig);
3497
+ }
3498
+ if (this.getAssertion) {
3499
+ this.msalConfig.auth.clientAssertion = await this.getAssertion();
3500
+ }
3501
+ // The confidential client requires either a secret, assertion or certificate.
3502
+ if (this.msalConfig.auth.clientSecret ||
3503
+ this.msalConfig.auth.clientAssertion ||
3504
+ this.msalConfig.auth.clientCertificate) {
3505
+ if (options === null || options === void 0 ? void 0 : options.enableCae) {
3506
+ this.caeApp.confidential = new msalCommon__namespace.ConfidentialClientApplication(this.msalConfig);
3507
+ }
3508
+ else {
3509
+ this.app.confidential = new msalCommon__namespace.ConfidentialClientApplication(this.msalConfig);
3447
3510
  }
3448
- : certificatePathOrConfiguration));
3449
- const certificate = configuration
3450
- .certificate;
3451
- const certificatePath = configuration.certificatePath;
3452
- if (!configuration || !(certificate || certificatePath)) {
3453
- throw new Error(`${credentialName$2}: Provide either a PEM certificate in string form, or the path to that certificate in the filesystem. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`);
3454
3511
  }
3455
- if (certificate && certificatePath) {
3456
- throw new Error(`${credentialName$2}: To avoid unexpected behaviors, providing both the contents of a PEM certificate and the path to a PEM certificate is forbidden. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`);
3512
+ else {
3513
+ if (this.requiresConfidential) {
3514
+ throw new Error("Unable to generate the MSAL confidential client. Missing either the client's secret, certificate or assertion.");
3515
+ }
3457
3516
  }
3458
- this.msalFlow = new MsalClientCertificate(Object.assign(Object.assign({}, options), { configuration,
3459
- logger: logger$8,
3460
- clientId,
3461
- tenantId, sendCertificateChain: options.sendCertificateChain, tokenCredentialOptions: options }));
3462
3517
  }
3463
3518
  /**
3464
- * Authenticates with Microsoft Entra ID and returns an access token if successful.
3465
- * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.
3466
- *
3467
- * @param scopes - The list of scopes for which the token will have access.
3468
- * @param options - The options used to configure any requests this
3469
- * TokenCredential implementation might make.
3519
+ * Allows the cancellation of a MSAL request.
3470
3520
  */
3471
- async getToken(scopes, options = {}) {
3472
- return tracingClient.withSpan(`${credentialName$2}.getToken`, options, async (newOptions) => {
3473
- newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger$8);
3474
- const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];
3475
- return this.msalFlow.getToken(arrayScopes, newOptions);
3521
+ withCancellation(promise, abortSignal, onCancel) {
3522
+ return new Promise((resolve, reject) => {
3523
+ promise
3524
+ .then((msalToken) => {
3525
+ return resolve(msalToken);
3526
+ })
3527
+ .catch(reject);
3528
+ if (abortSignal) {
3529
+ abortSignal.addEventListener("abort", () => {
3530
+ onCancel === null || onCancel === void 0 ? void 0 : onCancel();
3531
+ });
3532
+ }
3476
3533
  });
3477
3534
  }
3478
- }
3479
-
3480
- // Copyright (c) Microsoft Corporation.
3481
- // Licensed under the MIT license.
3482
- /**
3483
- * MSAL client secret client. Calls to MSAL's confidential application's `acquireTokenByClientCredential` during `doGetToken`.
3484
- * @internal
3485
- */
3486
- class MsalClientSecret extends MsalNode {
3487
- constructor(options) {
3488
- super(options);
3489
- this.requiresConfidential = true;
3490
- this.msalConfig.auth.clientSecret = options.clientSecret;
3535
+ /**
3536
+ * Returns the existing account, attempts to load the account from MSAL.
3537
+ */
3538
+ async getActiveAccount(enableCae = false) {
3539
+ if (this.account) {
3540
+ return this.account;
3541
+ }
3542
+ const cache = this.getApp("confidentialFirst", enableCae).getTokenCache();
3543
+ const accountsByTenant = await (cache === null || cache === void 0 ? void 0 : cache.getAllAccounts());
3544
+ if (!accountsByTenant) {
3545
+ return;
3546
+ }
3547
+ if (accountsByTenant.length === 1) {
3548
+ this.account = msalToPublic(this.clientId, accountsByTenant[0]);
3549
+ }
3550
+ else {
3551
+ this.logger
3552
+ .info(`More than one account was found authenticated for this Client ID and Tenant ID.
3553
+ However, no "authenticationRecord" has been provided for this credential,
3554
+ therefore we're unable to pick between these accounts.
3555
+ A new login attempt will be requested, to ensure the correct account is picked.
3556
+ To work with multiple accounts for the same Client ID and Tenant ID, please provide an "authenticationRecord" when initializing a credential to prevent this from happening.`);
3557
+ return;
3558
+ }
3559
+ return this.account;
3491
3560
  }
3492
- async doGetToken(scopes, options = {}) {
3493
- try {
3494
- const result = await this.getApp("confidential", options.enableCae).acquireTokenByClientCredential({
3561
+ /**
3562
+ * Attempts to retrieve a token from cache.
3563
+ */
3564
+ async getTokenSilent(scopes, options) {
3565
+ var _a, _b, _c;
3566
+ await this.getActiveAccount(options === null || options === void 0 ? void 0 : options.enableCae);
3567
+ if (!this.account) {
3568
+ throw new AuthenticationRequiredError({
3495
3569
  scopes,
3496
- correlationId: options.correlationId,
3497
- azureRegion: this.azureRegion,
3498
- authority: options.authority,
3499
- claims: options.claims,
3570
+ getTokenOptions: options,
3571
+ message: "Silent authentication failed. We couldn't retrieve an active account from the cache.",
3500
3572
  });
3501
- // The Client Credential flow does not return an account,
3502
- // so each time getToken gets called, we will have to acquire a new token through the service.
3503
- return this.handleResult(scopes, result || undefined);
3573
+ }
3574
+ const silentRequest = {
3575
+ // To be able to re-use the account, the Token Cache must also have been provided.
3576
+ account: publicToMsal(this.account),
3577
+ correlationId: options === null || options === void 0 ? void 0 : options.correlationId,
3578
+ scopes,
3579
+ authority: options === null || options === void 0 ? void 0 : options.authority,
3580
+ claims: options === null || options === void 0 ? void 0 : options.claims,
3581
+ };
3582
+ if (hasNativeBroker() && this.enableBroker) {
3583
+ if (!silentRequest.tokenQueryParameters) {
3584
+ silentRequest.tokenQueryParameters = {};
3585
+ }
3586
+ if (!this.parentWindowHandle) {
3587
+ // error should have been thrown from within the constructor of InteractiveBrowserCredential
3588
+ this.logger.warning("Parent window handle is not specified for the broker. This may cause unexpected behavior. Please provide the parentWindowHandle.");
3589
+ }
3590
+ if (this.enableMsaPassthrough) {
3591
+ silentRequest.tokenQueryParameters["msal_request_type"] = "consumer_passthrough";
3592
+ }
3593
+ }
3594
+ try {
3595
+ this.logger.info("Attempting to acquire token silently");
3596
+ /**
3597
+ * The following code to retrieve all accounts is done as a workaround in an attempt to force the
3598
+ * refresh of the token cache with the token and the account passed in through the
3599
+ * `authenticationRecord` parameter. See issue - https://github.com/Azure/azure-sdk-for-js/issues/24349#issuecomment-1496715651
3600
+ * This workaround serves as a workaround for silent authentication not happening when authenticationRecord is passed.
3601
+ */
3602
+ await ((_a = this.getApp("publicFirst", options === null || options === void 0 ? void 0 : options.enableCae)) === null || _a === void 0 ? void 0 : _a.getTokenCache().getAllAccounts());
3603
+ const response = (_c = (await ((_b = this.getApp("confidential", options === null || options === void 0 ? void 0 : options.enableCae)) === null || _b === void 0 ? void 0 : _b.acquireTokenSilent(silentRequest)))) !== null && _c !== void 0 ? _c : (await this.getApp("public", options === null || options === void 0 ? void 0 : options.enableCae).acquireTokenSilent(silentRequest));
3604
+ return this.handleResult(scopes, response || undefined);
3504
3605
  }
3505
3606
  catch (err) {
3506
3607
  throw handleMsalError(scopes, err, options);
3507
3608
  }
3508
3609
  }
3509
- }
3510
-
3511
- // Copyright (c) Microsoft Corporation.
3512
- // Licensed under the MIT license.
3513
- const logger$7 = credentialLogger("ClientSecretCredential");
3514
- /**
3515
- * Enables authentication to Microsoft Entra ID using a client secret
3516
- * that was generated for an App Registration. More information on how
3517
- * to configure a client secret can be found here:
3518
- *
3519
- * https://learn.microsoft.com/entra/identity-platform/quickstart-configure-app-access-web-apis#add-credentials-to-your-web-application
3520
- *
3521
- */
3522
- class ClientSecretCredential {
3523
3610
  /**
3524
- * Creates an instance of the ClientSecretCredential with the details
3525
- * needed to authenticate against Microsoft Entra ID with a client
3526
- * secret.
3527
- *
3528
- * @param tenantId - The Microsoft Entra tenant (directory) ID.
3529
- * @param clientId - The client (application) ID of an App Registration in the tenant.
3530
- * @param clientSecret - A client secret that was generated for the App Registration.
3531
- * @param options - Options for configuring the client which makes the authentication request.
3611
+ * Wrapper around each MSAL flow get token operation: doGetToken.
3612
+ * If disableAutomaticAuthentication is sent through the constructor, it will prevent MSAL from requesting the user input.
3532
3613
  */
3533
- constructor(tenantId, clientId, clientSecret, options = {}) {
3534
- if (!tenantId || !clientId || !clientSecret) {
3535
- throw new Error("ClientSecretCredential: tenantId, clientId, and clientSecret are required parameters. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.");
3614
+ async getToken(scopes, options = {}) {
3615
+ const tenantId = processMultiTenantRequest(this.tenantId, options, this.additionallyAllowedTenantIds) ||
3616
+ this.tenantId;
3617
+ options.authority = getAuthority(tenantId, this.authorityHost);
3618
+ options.correlationId = (options === null || options === void 0 ? void 0 : options.correlationId) || randomUUID();
3619
+ await this.init(options);
3620
+ try {
3621
+ // MSAL now caches tokens based on their claims,
3622
+ // so now one has to keep track fo claims in order to retrieve the newer tokens from acquireTokenSilent
3623
+ // This update happened on PR: https://github.com/AzureAD/microsoft-authentication-library-for-js/pull/4533
3624
+ const optionsClaims = options.claims;
3625
+ if (optionsClaims) {
3626
+ this.cachedClaims = optionsClaims;
3627
+ }
3628
+ if (this.cachedClaims && !optionsClaims) {
3629
+ options.claims = this.cachedClaims;
3630
+ }
3631
+ // We don't return the promise since we want to catch errors right here.
3632
+ return await this.getTokenSilent(scopes, options);
3633
+ }
3634
+ catch (err) {
3635
+ if (err.name !== "AuthenticationRequiredError") {
3636
+ throw err;
3637
+ }
3638
+ if (options === null || options === void 0 ? void 0 : options.disableAutomaticAuthentication) {
3639
+ throw new AuthenticationRequiredError({
3640
+ scopes,
3641
+ getTokenOptions: options,
3642
+ message: "Automatic authentication has been disabled. You may call the authentication() method.",
3643
+ });
3644
+ }
3645
+ this.logger.info(`Silent authentication failed, falling back to interactive method.`);
3646
+ return this.doGetToken(scopes, options);
3536
3647
  }
3537
- this.tenantId = tenantId;
3538
- this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants);
3539
- this.msalFlow = new MsalClientSecret(Object.assign(Object.assign({}, options), { logger: logger$7,
3540
- clientId,
3541
- tenantId,
3542
- clientSecret, tokenCredentialOptions: options }));
3543
3648
  }
3544
3649
  /**
3545
- * Authenticates with Microsoft Entra ID and returns an access token if successful.
3546
- * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.
3547
- *
3548
- * @param scopes - The list of scopes for which the token will have access.
3549
- * @param options - The options used to configure any requests this
3550
- * TokenCredential implementation might make.
3650
+ * Handles the MSAL authentication result.
3651
+ * If the result has an account, we update the local account reference.
3652
+ * If the token received is invalid, an error will be thrown depending on what's missing.
3551
3653
  */
3552
- async getToken(scopes, options = {}) {
3553
- return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async (newOptions) => {
3554
- newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger$7);
3555
- const arrayScopes = ensureScopes(scopes);
3556
- return this.msalFlow.getToken(arrayScopes, newOptions);
3557
- });
3654
+ handleResult(scopes, result, getTokenOptions) {
3655
+ if (result === null || result === void 0 ? void 0 : result.account) {
3656
+ this.account = msalToPublic(this.clientId, result.account);
3657
+ }
3658
+ ensureValidMsalToken(scopes, result, getTokenOptions);
3659
+ this.logger.getToken.info(formatSuccess(scopes));
3660
+ return {
3661
+ token: result.accessToken,
3662
+ expiresOnTimestamp: result.expiresOn.getTime(),
3663
+ };
3558
3664
  }
3559
3665
  }
3560
3666
 
@@ -4308,6 +4414,48 @@ class AuthorizationCodeCredential {
4308
4414
  }
4309
4415
  }
4310
4416
 
4417
+ // Copyright (c) Microsoft Corporation.
4418
+ // Licensed under the MIT license.
4419
+ const readFileAsync = util.promisify(fs.readFile);
4420
+ /**
4421
+ * Tries to asynchronously load a certificate from the given path.
4422
+ *
4423
+ * @param configuration - Either the PEM value or the path to the certificate.
4424
+ * @param sendCertificateChain - Option to include x5c header for SubjectName and Issuer name authorization.
4425
+ * @returns - The certificate parts, or `undefined` if the certificate could not be loaded.
4426
+ * @internal
4427
+ */
4428
+ async function parseCertificate(configuration, sendCertificateChain) {
4429
+ const certificateParts = {};
4430
+ const certificate = configuration
4431
+ .certificate;
4432
+ const certificatePath = configuration
4433
+ .certificatePath;
4434
+ certificateParts.certificateContents =
4435
+ certificate || (await readFileAsync(certificatePath, "utf8"));
4436
+ if (sendCertificateChain) {
4437
+ certificateParts.x5c = certificateParts.certificateContents;
4438
+ }
4439
+ const certificatePattern = /(-+BEGIN CERTIFICATE-+)(\n\r?|\r\n?)([A-Za-z0-9+/\n\r]+=*)(\n\r?|\r\n?)(-+END CERTIFICATE-+)/g;
4440
+ const publicKeys = [];
4441
+ // Match all possible certificates, in the order they are in the file. These will form the chain that is used for x5c
4442
+ let match;
4443
+ do {
4444
+ match = certificatePattern.exec(certificateParts.certificateContents);
4445
+ if (match) {
4446
+ publicKeys.push(match[3]);
4447
+ }
4448
+ } while (match);
4449
+ if (publicKeys.length === 0) {
4450
+ throw new Error("The file at the specified path does not contain a PEM-encoded certificate.");
4451
+ }
4452
+ certificateParts.thumbprint = crypto.createHash("sha1")
4453
+ .update(Buffer.from(publicKeys[0], "base64"))
4454
+ .digest("hex")
4455
+ .toUpperCase();
4456
+ return certificateParts;
4457
+ }
4458
+
4311
4459
  // Copyright (c) Microsoft Corporation.
4312
4460
  // Licensed under the MIT license.
4313
4461
  /**