UNPKG

mcp-framework

Version:

Framework for building Model Context Protocol (MCP) servers in Typescript

65 lines (64 loc) 3.02 kB
import { APIKeyAuthProvider } from '../../auth/providers/apikey.js'; import { OAuthAuthProvider } from '../../auth/providers/oauth.js'; import { DEFAULT_AUTH_ERROR } from '../../auth/types.js'; import { getRequestHeader } from '../../utils/headers.js'; import { logger } from '../../core/Logger.js'; /** * Shared authentication handler for transport layers. * Handles both API Key and OAuth authentication with proper error responses. * * @param req - Incoming HTTP request * @param res - HTTP response object * @param authConfig - Authentication configuration from transport * @param context - Description of the context (e.g., "initialize", "message", "SSE connection") * @returns True if authenticated, false if authentication failed (response already sent) */ export async function handleAuthentication(req, res, authConfig, context) { if (!authConfig?.provider) { return true; } const isApiKey = authConfig.provider instanceof APIKeyAuthProvider; // Special handling for API Key - check header exists before authenticate if (isApiKey) { const provider = authConfig.provider; const headerValue = getRequestHeader(req.headers, provider.getHeaderName()); if (!headerValue) { const error = provider.getAuthError?.() || DEFAULT_AUTH_ERROR; res.setHeader('WWW-Authenticate', `ApiKey realm="MCP Server", header="${provider.getHeaderName()}"`); res.writeHead(error.status).end(JSON.stringify({ error: error.message, status: error.status, type: 'authentication_error', })); return false; } } // Perform authentication const authResult = await authConfig.provider.authenticate(req); if (!authResult) { const error = authConfig.provider.getAuthError?.() || DEFAULT_AUTH_ERROR; logger.warn(`Authentication failed for ${context}:`); logger.warn(`- Client IP: ${req.socket.remoteAddress}`); logger.warn(`- Error: ${error.message}`); // Set appropriate WWW-Authenticate header if (isApiKey) { const provider = authConfig.provider; res.setHeader('WWW-Authenticate', `ApiKey realm="MCP Server", header="${provider.getHeaderName()}"`); } else if (authConfig.provider instanceof OAuthAuthProvider) { const provider = authConfig.provider; res.setHeader('WWW-Authenticate', provider.getWWWAuthenticateHeader('invalid_token', 'Missing or invalid authentication token')); } res.writeHead(error.status).end(JSON.stringify({ error: error.message, status: error.status, type: 'authentication_error', })); return false; } // Authentication successful logger.info(`Authentication successful for ${context}:`); logger.info(`- Client IP: ${req.socket.remoteAddress}`); logger.info(`- Auth Type: ${authConfig.provider.constructor.name}`); return true; }