UNPKG

@azure/identity

Version:

Provides credential implementations for Azure SDK libraries that can authenticate with Microsoft Entra ID

476 lines (475 loc) • 20.6 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var msalClient_exports = {}; __export(msalClient_exports, { createMsalClient: () => createMsalClient, generateMsalConfiguration: () => generateMsalConfiguration }); module.exports = __toCommonJS(msalClient_exports); var msal = __toESM(require("@azure/msal-node")); var import_logging = require("../../util/logging.js"); var import_msalPlugins = require("./msalPlugins.js"); var import_utils = require("../utils.js"); var import_errors = require("../../errors.js"); var import_identityClient = require("../../client/identityClient.js"); var import_regionalAuthority = require("../../regionalAuthority.js"); var import_logger = require("@azure/logger"); var import_tenantIdUtils = require("../../util/tenantIdUtils.js"); const msalLogger = (0, import_logging.credentialLogger)("MsalClient"); function generateMsalConfiguration(clientId, tenantId, msalClientOptions = {}) { const resolvedTenant = (0, import_tenantIdUtils.resolveTenantId)( msalClientOptions.logger ?? msalLogger, tenantId, clientId ); const authority = (0, import_utils.getAuthority)(resolvedTenant, (0, import_utils.getAuthorityHost)(msalClientOptions)); const httpClient = new import_identityClient.IdentityClient({ ...msalClientOptions.tokenCredentialOptions, authorityHost: authority, loggingOptions: msalClientOptions.loggingOptions }); const msalConfig = { auth: { clientId, authority, knownAuthorities: (0, import_utils.getKnownAuthorities)( resolvedTenant, authority, msalClientOptions.disableInstanceDiscovery ) }, system: { networkClient: httpClient, loggerOptions: { loggerCallback: (0, import_utils.defaultLoggerCallback)(msalClientOptions.logger ?? msalLogger), logLevel: (0, import_utils.getMSALLogLevel)((0, import_logger.getLogLevel)()), piiLoggingEnabled: msalClientOptions.loggingOptions?.enableUnsafeSupportLogging } } }; return msalConfig; } function createMsalClient(clientId, tenantId, createMsalClientOptions = {}) { const state = { msalConfig: generateMsalConfiguration(clientId, tenantId, createMsalClientOptions), cachedAccount: createMsalClientOptions.authenticationRecord ? (0, import_utils.publicToMsal)(createMsalClientOptions.authenticationRecord) : null, pluginConfiguration: import_msalPlugins.msalPlugins.generatePluginConfiguration(createMsalClientOptions), logger: createMsalClientOptions.logger ?? msalLogger }; const publicApps = /* @__PURE__ */ new Map(); async function getPublicApp(options = {}) { const appKey = options.enableCae ? "CAE" : "default"; let publicClientApp = publicApps.get(appKey); if (publicClientApp) { state.logger.getToken.info("Existing PublicClientApplication found in cache, returning it."); return publicClientApp; } state.logger.getToken.info( `Creating new PublicClientApplication with CAE ${options.enableCae ? "enabled" : "disabled"}.` ); const cachePlugin = options.enableCae ? state.pluginConfiguration.cache.cachePluginCae : state.pluginConfiguration.cache.cachePlugin; state.msalConfig.auth.clientCapabilities = options.enableCae ? ["cp1"] : void 0; publicClientApp = new msal.PublicClientApplication({ ...state.msalConfig, broker: { nativeBrokerPlugin: state.pluginConfiguration.broker.nativeBrokerPlugin }, cache: { cachePlugin: await cachePlugin } }); publicApps.set(appKey, publicClientApp); return publicClientApp; } const confidentialApps = /* @__PURE__ */ new Map(); async function getConfidentialApp(options = {}) { const appKey = options.enableCae ? "CAE" : "default"; let confidentialClientApp = confidentialApps.get(appKey); if (confidentialClientApp) { state.logger.getToken.info( "Existing ConfidentialClientApplication found in cache, returning it." ); return confidentialClientApp; } state.logger.getToken.info( `Creating new ConfidentialClientApplication with CAE ${options.enableCae ? "enabled" : "disabled"}.` ); const cachePlugin = options.enableCae ? state.pluginConfiguration.cache.cachePluginCae : state.pluginConfiguration.cache.cachePlugin; state.msalConfig.auth.clientCapabilities = options.enableCae ? ["cp1"] : void 0; confidentialClientApp = new msal.ConfidentialClientApplication({ ...state.msalConfig, broker: { nativeBrokerPlugin: state.pluginConfiguration.broker.nativeBrokerPlugin }, cache: { cachePlugin: await cachePlugin } }); confidentialApps.set(appKey, confidentialClientApp); return confidentialClientApp; } async function getTokenSilent(app, scopes, options = {}) { if (state.cachedAccount === null) { state.logger.getToken.info("No cached account found in local state."); throw new import_errors.AuthenticationRequiredError({ scopes }); } if (options.claims) { state.cachedClaims = options.claims; } const silentRequest = { account: state.cachedAccount, scopes, claims: state.cachedClaims }; if (state.pluginConfiguration.broker.isEnabled) { silentRequest.extraQueryParameters ||= {}; if (state.pluginConfiguration.broker.enableMsaPassthrough) { silentRequest.extraQueryParameters["msal_request_type"] = "consumer_passthrough"; } } if (options.proofOfPossessionOptions) { silentRequest.shrNonce = options.proofOfPossessionOptions.nonce; silentRequest.authenticationScheme = "pop"; silentRequest.resourceRequestMethod = options.proofOfPossessionOptions.resourceRequestMethod; silentRequest.resourceRequestUri = options.proofOfPossessionOptions.resourceRequestUrl; } state.logger.getToken.info("Attempting to acquire token silently"); try { return await app.acquireTokenSilent(silentRequest); } catch (err) { throw (0, import_utils.handleMsalError)(scopes, err, options); } } function calculateRequestAuthority(options) { if (options?.tenantId) { return (0, import_utils.getAuthority)(options.tenantId, (0, import_utils.getAuthorityHost)(createMsalClientOptions)); } return state.msalConfig.auth.authority; } async function withSilentAuthentication(msalApp, scopes, options, onAuthenticationRequired) { let response = null; try { response = await getTokenSilent(msalApp, scopes, options); } catch (e) { if (e.name !== "AuthenticationRequiredError") { throw e; } if (options.disableAutomaticAuthentication) { throw new import_errors.AuthenticationRequiredError({ scopes, getTokenOptions: options, message: "Automatic authentication has been disabled. You may call the authentication() method." }); } } if (response === null) { try { response = await onAuthenticationRequired(); } catch (err) { throw (0, import_utils.handleMsalError)(scopes, err, options); } } (0, import_utils.ensureValidMsalToken)(scopes, response, options); state.cachedAccount = response?.account ?? null; state.logger.getToken.info((0, import_logging.formatSuccess)(scopes)); return { token: response.accessToken, expiresOnTimestamp: response.expiresOn.getTime(), refreshAfterTimestamp: response.refreshOn?.getTime(), tokenType: response.tokenType }; } async function getTokenByClientSecret(scopes, clientSecret, options = {}) { state.logger.getToken.info(`Attempting to acquire token using client secret`); state.msalConfig.auth.clientSecret = clientSecret; const msalApp = await getConfidentialApp(options); try { const response = await msalApp.acquireTokenByClientCredential({ scopes, authority: calculateRequestAuthority(options), azureRegion: (0, import_regionalAuthority.calculateRegionalAuthority)(), claims: options?.claims }); (0, import_utils.ensureValidMsalToken)(scopes, response, options); state.logger.getToken.info((0, import_logging.formatSuccess)(scopes)); return { token: response.accessToken, expiresOnTimestamp: response.expiresOn.getTime(), refreshAfterTimestamp: response.refreshOn?.getTime(), tokenType: response.tokenType }; } catch (err) { throw (0, import_utils.handleMsalError)(scopes, err, options); } } async function getTokenByClientAssertion(scopes, clientAssertion, options = {}) { state.logger.getToken.info(`Attempting to acquire token using client assertion`); state.msalConfig.auth.clientAssertion = clientAssertion; const msalApp = await getConfidentialApp(options); try { const response = await msalApp.acquireTokenByClientCredential({ scopes, authority: calculateRequestAuthority(options), azureRegion: (0, import_regionalAuthority.calculateRegionalAuthority)(), claims: options?.claims, clientAssertion }); (0, import_utils.ensureValidMsalToken)(scopes, response, options); state.logger.getToken.info((0, import_logging.formatSuccess)(scopes)); return { token: response.accessToken, expiresOnTimestamp: response.expiresOn.getTime(), refreshAfterTimestamp: response.refreshOn?.getTime(), tokenType: response.tokenType }; } catch (err) { throw (0, import_utils.handleMsalError)(scopes, err, options); } } async function getTokenByClientCertificate(scopes, certificate, options = {}) { state.logger.getToken.info(`Attempting to acquire token using client certificate`); state.msalConfig.auth.clientCertificate = certificate; const msalApp = await getConfidentialApp(options); try { const response = await msalApp.acquireTokenByClientCredential({ scopes, authority: calculateRequestAuthority(options), azureRegion: (0, import_regionalAuthority.calculateRegionalAuthority)(), claims: options?.claims }); (0, import_utils.ensureValidMsalToken)(scopes, response, options); state.logger.getToken.info((0, import_logging.formatSuccess)(scopes)); return { token: response.accessToken, expiresOnTimestamp: response.expiresOn.getTime(), refreshAfterTimestamp: response.refreshOn?.getTime(), tokenType: response.tokenType }; } catch (err) { throw (0, import_utils.handleMsalError)(scopes, err, options); } } async function getTokenByDeviceCode(scopes, deviceCodeCallback, options = {}) { state.logger.getToken.info(`Attempting to acquire token using device code`); const msalApp = await getPublicApp(options); return withSilentAuthentication(msalApp, scopes, options, () => { const requestOptions = { scopes, cancel: options?.abortSignal?.aborted ?? false, deviceCodeCallback, authority: calculateRequestAuthority(options), claims: options?.claims }; const deviceCodeRequest = msalApp.acquireTokenByDeviceCode(requestOptions); if (options.abortSignal) { options.abortSignal.addEventListener("abort", () => { requestOptions.cancel = true; }); } return deviceCodeRequest; }); } async function getTokenByUsernamePassword(scopes, username, password, options = {}) { state.logger.getToken.info(`Attempting to acquire token using username and password`); const msalApp = await getPublicApp(options); return withSilentAuthentication(msalApp, scopes, options, () => { const requestOptions = { scopes, username, password, authority: calculateRequestAuthority(options), claims: options?.claims }; return msalApp.acquireTokenByUsernamePassword(requestOptions); }); } function getActiveAccount() { if (!state.cachedAccount) { return void 0; } return (0, import_utils.msalToPublic)(clientId, state.cachedAccount); } async function getTokenByAuthorizationCode(scopes, redirectUri, authorizationCode, clientSecret, options = {}) { state.logger.getToken.info(`Attempting to acquire token using authorization code`); let msalApp; if (clientSecret) { state.msalConfig.auth.clientSecret = clientSecret; msalApp = await getConfidentialApp(options); } else { msalApp = await getPublicApp(options); } return withSilentAuthentication(msalApp, scopes, options, () => { return msalApp.acquireTokenByCode({ scopes, redirectUri, code: authorizationCode, authority: calculateRequestAuthority(options), claims: options?.claims }); }); } async function getTokenOnBehalfOf(scopes, userAssertionToken, clientCredentials, options = {}) { msalLogger.getToken.info(`Attempting to acquire token on behalf of another user`); if (typeof clientCredentials === "string") { msalLogger.getToken.info(`Using client secret for on behalf of flow`); state.msalConfig.auth.clientSecret = clientCredentials; } else if (typeof clientCredentials === "function") { msalLogger.getToken.info(`Using client assertion callback for on behalf of flow`); state.msalConfig.auth.clientAssertion = clientCredentials; } else { msalLogger.getToken.info(`Using client certificate for on behalf of flow`); state.msalConfig.auth.clientCertificate = clientCredentials; } const msalApp = await getConfidentialApp(options); try { const response = await msalApp.acquireTokenOnBehalfOf({ scopes, authority: calculateRequestAuthority(options), claims: options.claims, oboAssertion: userAssertionToken }); (0, import_utils.ensureValidMsalToken)(scopes, response, options); msalLogger.getToken.info((0, import_logging.formatSuccess)(scopes)); return { token: response.accessToken, expiresOnTimestamp: response.expiresOn.getTime(), refreshAfterTimestamp: response.refreshOn?.getTime(), tokenType: response.tokenType }; } catch (err) { throw (0, import_utils.handleMsalError)(scopes, err, options); } } function createBaseInteractiveRequest(scopes, options) { return { openBrowser: async (url) => { const open = await import("open"); await open.default(url, { newInstance: true }); }, scopes, authority: calculateRequestAuthority(options), claims: options?.claims, loginHint: options?.loginHint, errorTemplate: options?.browserCustomizationOptions?.errorMessage, successTemplate: options?.browserCustomizationOptions?.successMessage, prompt: options?.loginHint ? "login" : "select_account" }; } async function getBrokeredTokenInternal(scopes, useDefaultBrokerAccount, options = {}) { msalLogger.verbose("Authentication will resume through the broker"); const app = await getPublicApp(options); const interactiveRequest = createBaseInteractiveRequest(scopes, options); if (state.pluginConfiguration.broker.parentWindowHandle) { interactiveRequest.windowHandle = Buffer.from( state.pluginConfiguration.broker.parentWindowHandle ); } else { msalLogger.warning( "Parent window handle is not specified for the broker. This may cause unexpected behavior. Please provide the parentWindowHandle." ); } if (state.pluginConfiguration.broker.enableMsaPassthrough) { (interactiveRequest.extraQueryParameters ??= {})["msal_request_type"] = "consumer_passthrough"; } if (useDefaultBrokerAccount) { interactiveRequest.prompt = "none"; msalLogger.verbose("Attempting broker authentication using the default broker account"); } else { msalLogger.verbose("Attempting broker authentication without the default broker account"); } if (options.proofOfPossessionOptions) { interactiveRequest.shrNonce = options.proofOfPossessionOptions.nonce; interactiveRequest.authenticationScheme = "pop"; interactiveRequest.resourceRequestMethod = options.proofOfPossessionOptions.resourceRequestMethod; interactiveRequest.resourceRequestUri = options.proofOfPossessionOptions.resourceRequestUrl; } try { return await app.acquireTokenInteractive(interactiveRequest); } catch (e) { msalLogger.verbose(`Failed to authenticate through the broker: ${e.message}`); if (options.disableAutomaticAuthentication) { throw new import_errors.AuthenticationRequiredError({ scopes, getTokenOptions: options, message: "Cannot silently authenticate with default broker account." }); } if (useDefaultBrokerAccount) { return getBrokeredTokenInternal(scopes, false, options); } else { throw e; } } } async function getBrokeredToken(scopes, useDefaultBrokerAccount, options = {}) { msalLogger.getToken.info( `Attempting to acquire token using brokered authentication with useDefaultBrokerAccount: ${useDefaultBrokerAccount}` ); const response = await getBrokeredTokenInternal(scopes, useDefaultBrokerAccount, options); (0, import_utils.ensureValidMsalToken)(scopes, response, options); state.cachedAccount = response?.account ?? null; state.logger.getToken.info((0, import_logging.formatSuccess)(scopes)); return { token: response.accessToken, expiresOnTimestamp: response.expiresOn.getTime(), refreshAfterTimestamp: response.refreshOn?.getTime(), tokenType: response.tokenType }; } async function getTokenByInteractiveRequest(scopes, options = {}) { msalLogger.getToken.info(`Attempting to acquire token interactively`); const app = await getPublicApp(options); return withSilentAuthentication(app, scopes, options, async () => { const interactiveRequest = createBaseInteractiveRequest(scopes, options); if (state.pluginConfiguration.broker.isEnabled) { return getBrokeredTokenInternal( scopes, state.pluginConfiguration.broker.useDefaultBrokerAccount ?? false, options ); } if (options.proofOfPossessionOptions) { interactiveRequest.shrNonce = options.proofOfPossessionOptions.nonce; interactiveRequest.authenticationScheme = "pop"; interactiveRequest.resourceRequestMethod = options.proofOfPossessionOptions.resourceRequestMethod; interactiveRequest.resourceRequestUri = options.proofOfPossessionOptions.resourceRequestUrl; } return app.acquireTokenInteractive(interactiveRequest); }); } return { getActiveAccount, getBrokeredToken, getTokenByClientSecret, getTokenByClientAssertion, getTokenByClientCertificate, getTokenByDeviceCode, getTokenByUsernamePassword, getTokenByAuthorizationCode, getTokenOnBehalfOf, getTokenByInteractiveRequest }; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { createMsalClient, generateMsalConfiguration }); //# sourceMappingURL=msalClient.js.map