UNPKG

okta-mcp-server

Version:

Model Context Protocol (MCP) server for Okta API operations with support for bulk operations and caching

82 lines 3.2 kB
/** * Simple MCP OAuth middleware for validating bearer tokens * This allows the MCP server to be protected by OAuth if desired */ import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js'; import { protocolSafeLogger as logger } from '../../utils/protocol-safe-logger.js'; import * as jwt from 'jsonwebtoken'; export class SimpleAuthMiddleware { config; constructor(config) { this.config = config; } /** * Extract bearer token from MCP request metadata */ extractBearerToken(request) { // Check Authorization header in metadata const metadata = request.metadata || {}; const authHeader = metadata.authorization || metadata.Authorization; if (authHeader && typeof authHeader === 'string') { const match = authHeader.match(/^Bearer\s+(.+)$/i); if (match) { return match[1]; } } return undefined; } /** * Validate bearer token and authenticate request */ async authenticate(request) { // If auth is not required, skip if (!this.config.required) { return; } // Special case: allow oauth/metadata endpoint without auth if (request.method === 'oauth/metadata') { return; } // Extract and validate token const token = this.extractBearerToken(request); if (!token) { throw new McpError(ErrorCode.InvalidRequest, 'Authentication required. Please provide a valid Bearer token.'); } try { // Basic JWT validation - just check structure and expiry // In production, you'd verify signature with the issuer's public key const decoded = jwt.decode(token, { complete: true }); if (!decoded || typeof decoded.payload !== 'object') { throw new Error('Invalid token format'); } const payload = decoded.payload; // Check expiry if (payload.exp && payload.exp < Math.floor(Date.now() / 1000)) { throw new Error('Token expired'); } // Check audience if configured if (this.config.audience) { const aud = Array.isArray(payload.aud) ? payload.aud : [payload.aud]; if (!aud.includes(this.config.audience)) { throw new Error('Invalid audience'); } } // Check issuer if configured if (this.config.issuer && payload.iss !== this.config.issuer) { throw new Error('Invalid issuer'); } logger.debug('Authentication successful', { method: request.method, sub: payload.sub, }); } catch (error) { logger.error('Authentication failed', { method: request.method, error: error instanceof Error ? error.message : 'Unknown error', }); throw new McpError(ErrorCode.InvalidRequest, 'Invalid or expired token. Please authenticate again.'); } } } //# sourceMappingURL=oauth-middleware.js.map