UNPKG

@microsoft/agents-hosting

Version:

Microsoft 365 Agents SDK for JavaScript

269 lines 12.9 kB
"use strict"; /** * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.loadPrevAuthConfigFromEnv = exports.loadAuthConfigFromEnv = void 0; exports.getAuthConfigWithDefaults = getAuthConfigWithDefaults; const logger_1 = require("@microsoft/agents-activity/logger"); const object_path_1 = __importDefault(require("object-path")); const logger = (0, logger_1.debug)('agents:authConfiguration'); const DEFAULT_CONNECTION = 'serviceConnection'; /** * Loads the authentication configuration from environment variables. * * @returns The authentication configuration. * @throws Will throw an error if clientId is not provided in production. * * @remarks * - `clientId` is required * * @example * ``` * tenantId=your-tenant-id * clientId=your-client-id * clientSecret=your-client-secret * * certPemFile=your-cert-pem-file * certKeyFile=your-cert-key-file * * FICClientId=your-FIC-client-id * * connectionName=your-connection-name * authority=your-authority-endpoint * ``` * */ const loadAuthConfigFromEnv = (cnxName) => { var _a, _b, _c; const envConnections = loadConnectionsMapFromEnv(); let authConfig; if (envConnections.connectionsMap.length === 0) { // No connections provided, we need to populate the connections map with the old config settings authConfig = buildLegacyAuthConfig(cnxName); envConnections.connections.set(DEFAULT_CONNECTION, authConfig); envConnections.connectionsMap.push({ serviceUrl: '*', connection: DEFAULT_CONNECTION, }); } else { // There are connections provided, use the default or specified connection if (cnxName) { const entry = envConnections.connections.get(cnxName); if (entry) { authConfig = entry; } else { throw new Error(`Connection "${cnxName}" not found in environment.`); } } else { const defaultItem = envConnections.connectionsMap.find((item) => item.serviceUrl === '*'); const defaultConn = defaultItem ? envConnections.connections.get(defaultItem.connection) : undefined; if (!defaultConn) { throw new Error('No default connection found in environment connections.'); } authConfig = defaultConn; } (_a = authConfig.authority) !== null && _a !== void 0 ? _a : (authConfig.authority = 'https://login.microsoftonline.com'); (_b = authConfig.issuers) !== null && _b !== void 0 ? _b : (authConfig.issuers = getDefaultIssuers((_c = authConfig.tenantId) !== null && _c !== void 0 ? _c : '', authConfig.authority)); } return { ...authConfig, ...envConnections, }; }; exports.loadAuthConfigFromEnv = loadAuthConfigFromEnv; /** * Loads the agent authentication configuration from previous version environment variables. * * @returns The agent authentication configuration. * @throws Will throw an error if MicrosoftAppId is not provided in production. * * @example * ``` * MicrosoftAppId=your-client-id * MicrosoftAppPassword=your-client-secret * MicrosoftAppTenantId=your-tenant-id * ``` * */ const loadPrevAuthConfigFromEnv = () => { var _a, _b, _c, _d, _e; const envConnections = loadConnectionsMapFromEnv(); let authConfig = {}; if (envConnections.connectionsMap.length === 0) { // No connections provided, we need to populate the connection map with the old config settings if (process.env.MicrosoftAppId === undefined && process.env.NODE_ENV === 'production') { throw new Error('ClientId required in production'); } const authority = (_a = process.env.authorityEndpoint) !== null && _a !== void 0 ? _a : 'https://login.microsoftonline.com'; authConfig = { tenantId: process.env.MicrosoftAppTenantId, clientId: process.env.MicrosoftAppId, clientSecret: process.env.MicrosoftAppPassword, certPemFile: process.env.certPemFile, certKeyFile: process.env.certKeyFile, connectionName: process.env.connectionName, FICClientId: process.env.MicrosoftAppClientId, authority, scope: process.env.scope, issuers: getDefaultIssuers((_b = process.env.MicrosoftAppTenantId) !== null && _b !== void 0 ? _b : '', authority), altBlueprintConnectionName: process.env.altBlueprintConnectionName, WIDAssertionFile: process.env.WIDAssertionFile, }; envConnections.connections.set(DEFAULT_CONNECTION, authConfig); envConnections.connectionsMap.push({ serviceUrl: '*', connection: DEFAULT_CONNECTION, }); } else { // There are connections provided, use the default one. const defaultItem = envConnections.connectionsMap.find((item) => item.serviceUrl === '*'); const defaultConn = defaultItem ? envConnections.connections.get(defaultItem.connection) : undefined; if (!defaultConn) { throw new Error('No default connection found in environment connections.'); } authConfig = defaultConn; } (_c = authConfig.authority) !== null && _c !== void 0 ? _c : (authConfig.authority = 'https://login.microsoftonline.com'); (_d = authConfig.issuers) !== null && _d !== void 0 ? _d : (authConfig.issuers = getDefaultIssuers((_e = authConfig.tenantId) !== null && _e !== void 0 ? _e : '', authConfig.authority)); return { ...authConfig, ...envConnections }; }; exports.loadPrevAuthConfigFromEnv = loadPrevAuthConfigFromEnv; function loadConnectionsMapFromEnv() { const envVars = process.env; const connectionsObj = {}; const connectionsMap = []; const CONNECTIONS_PREFIX = 'connections__'; const CONNECTIONS_MAP_PREFIX = 'connectionsMap__'; for (const [key, value] of Object.entries(envVars)) { if (key.startsWith(CONNECTIONS_PREFIX)) { // Convert to dot notation let path = key.substring(CONNECTIONS_PREFIX.length).replace(/__/g, '.'); // Remove ".settings." from the path path = path.replace('.settings.', '.'); object_path_1.default.set(connectionsObj, path, value); } else if (key.startsWith(CONNECTIONS_MAP_PREFIX)) { const path = key.substring(CONNECTIONS_MAP_PREFIX.length).replace(/__/g, '.'); object_path_1.default.set(connectionsMap, path, value); } } // Convert connectionsObj to Map<string, AuthConfiguration> const connections = new Map(Object.entries(connectionsObj)); if (connections.size === 0) { logger.warn('No connections found in configuration.'); } if (connectionsMap.length === 0) { logger.warn('No connections map found in configuration.'); if (connections.size > 0) { const firstEntry = connections.entries().next().value; if (firstEntry) { const [firstKey] = firstEntry; // Provide a default connection map if none is specified connectionsMap.push({ serviceUrl: '*', connection: firstKey, }); } } } return { connections, connectionsMap, }; } /** * Loads the authentication configuration from the provided config or from the environment variables * providing default values for authority and issuers. * * @returns The authentication configuration. * @throws Will throw an error if clientId is not provided in production. * * @example * ``` * tenantId=your-tenant-id * clientId=your-client-id * clientSecret=your-client-secret * * certPemFile=your-cert-pem-file * certKeyFile=your-cert-key-file * * FICClientId=your-FIC-client-id * * connectionName=your-connection-name * authority=your-authority-endpoint * ``` * */ function getAuthConfigWithDefaults(config) { var _a, _b, _c, _d; if (!config) return (0, exports.loadAuthConfigFromEnv)(); const providedConnections = config.connections && config.connectionsMap ? { connections: config.connections, connectionsMap: config.connectionsMap } : undefined; const connections = providedConnections !== null && providedConnections !== void 0 ? providedConnections : loadConnectionsMapFromEnv(); let mergedConfig; if (connections && ((_a = connections.connectionsMap) === null || _a === void 0 ? void 0 : _a.length) === 0) { // No connections provided, we need to populate the connections map with the old config settings mergedConfig = buildLegacyAuthConfig(undefined, config); (_b = connections.connections) === null || _b === void 0 ? void 0 : _b.set(DEFAULT_CONNECTION, mergedConfig); connections.connectionsMap.push({ serviceUrl: '*', connection: DEFAULT_CONNECTION }); } else { // There are connections provided, use the default connection const defaultItem = (_c = connections.connectionsMap) === null || _c === void 0 ? void 0 : _c.find((item) => item.serviceUrl === '*'); const defaultConn = defaultItem ? (_d = connections.connections) === null || _d === void 0 ? void 0 : _d.get(defaultItem.connection) : undefined; if (!defaultConn) { throw new Error('No default connection found in environment connections.'); } mergedConfig = buildLegacyAuthConfig(undefined, defaultConn); } return { ...mergedConfig, ...connections, }; } function buildLegacyAuthConfig(envPrefix = '', customConfig) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o; const prefix = envPrefix ? `${envPrefix}_` : ''; const authority = (_b = (_a = customConfig === null || customConfig === void 0 ? void 0 : customConfig.authority) !== null && _a !== void 0 ? _a : process.env[`${prefix}authorityEndpoint`]) !== null && _b !== void 0 ? _b : 'https://login.microsoftonline.com'; const clientId = (_c = customConfig === null || customConfig === void 0 ? void 0 : customConfig.clientId) !== null && _c !== void 0 ? _c : process.env[`${prefix}clientId`]; if (!clientId && !envPrefix && process.env.NODE_ENV === 'production') { throw new Error('ClientId required in production'); } if (!clientId && envPrefix) { throw new Error(`ClientId not found for connection: ${envPrefix}`); } const tenantId = (_d = customConfig === null || customConfig === void 0 ? void 0 : customConfig.tenantId) !== null && _d !== void 0 ? _d : process.env[`${prefix}tenantId`]; return { tenantId, clientId: clientId, clientSecret: (_e = customConfig === null || customConfig === void 0 ? void 0 : customConfig.clientSecret) !== null && _e !== void 0 ? _e : process.env[`${prefix}clientSecret`], certPemFile: (_f = customConfig === null || customConfig === void 0 ? void 0 : customConfig.certPemFile) !== null && _f !== void 0 ? _f : process.env[`${prefix}certPemFile`], certKeyFile: (_g = customConfig === null || customConfig === void 0 ? void 0 : customConfig.certKeyFile) !== null && _g !== void 0 ? _g : process.env[`${prefix}certKeyFile`], connectionName: (_h = customConfig === null || customConfig === void 0 ? void 0 : customConfig.connectionName) !== null && _h !== void 0 ? _h : process.env[`${prefix}connectionName`], FICClientId: (_j = customConfig === null || customConfig === void 0 ? void 0 : customConfig.FICClientId) !== null && _j !== void 0 ? _j : process.env[`${prefix}FICClientId`], authority, scope: (_k = customConfig === null || customConfig === void 0 ? void 0 : customConfig.scope) !== null && _k !== void 0 ? _k : process.env[`${prefix}scope`], issuers: (_l = customConfig === null || customConfig === void 0 ? void 0 : customConfig.issuers) !== null && _l !== void 0 ? _l : getDefaultIssuers(tenantId, authority), altBlueprintConnectionName: (_m = customConfig === null || customConfig === void 0 ? void 0 : customConfig.altBlueprintConnectionName) !== null && _m !== void 0 ? _m : process.env[`${prefix}altBlueprintConnectionName`], WIDAssertionFile: (_o = customConfig === null || customConfig === void 0 ? void 0 : customConfig.WIDAssertionFile) !== null && _o !== void 0 ? _o : process.env[`${prefix}WIDAssertionFile`] }; } function getDefaultIssuers(tenantId, authority) { return [ 'https://api.botframework.com', `https://sts.windows.net/${tenantId}/`, `${authority}/${tenantId}/v2.0` ]; } //# sourceMappingURL=authConfiguration.js.map