import 'reflect-metadata'; /** * OAuth 2.1 Module Configuration * * Compliant with: * - OAuth 2.1 (draft-ietf-oauth-v2-1-13) * - RFC 9728 - Protected Resource Metadata * - RFC 8414 - Authorization Server Metadata * - RFC 7591 - Dynamic Client Registration * - RFC 8707 - Resource Indicators (Token Audience Binding) * - RFC 7636 - PKCE * - RFC 7662 - Token Introspection */ export interface OAuthModuleConfig { /** * Resource URI - The MCP server's public URL * Used for token audience validation (RFC 8707) */ resourceUri: string; /** * Authorization Server(s) * The OAuth 2.1 authorization server URLs */ authorizationServers: string[]; /** * Supported scopes for this MCP server * Example: ['mcp:read', 'mcp:write', 'tools:execute'] */ scopesSupported?: string[]; /** * HTTP server configuration * OAuth requires HTTP transport - port will be extracted from resourceUri or use this */ http?: { port?: number; host?: string; basePath?: string; }; /** * Token Introspection Endpoint (RFC 7662) * Required for validating opaque tokens */ tokenIntrospectionEndpoint?: string; /** * Client ID for token introspection */ tokenIntrospectionClientId?: string; /** * Client Secret for token introspection * Should be stored in environment variable */ tokenIntrospectionClientSecret?: string; /** * Expected audience for tokens (RFC 8707) * If not provided, defaults to resourceUri */ audience?: string; /** * Issuer validation * If provided, tokens must be from this issuer */ issuer?: string; /** * Custom token validation * Additional validation logic beyond spec requirements */ customValidation?: (token: unknown) => Promise | boolean; /** * JWKS URI (RFC 7517) * The authorization server's JWKS endpoint for signature verification */ jwksUri?: string; /** * Token Cache Seconds * In-memory cache expiration for token introspection (defaults to 300) */ tokenCacheSeconds?: number; /** * Enable the Dynamic Client Registration endpoint (RFC 7591) at /oauth/v2/register. * Disabled by default. When disabled, the endpoint responds 404 and * `registration_endpoint` is omitted from advertised metadata. * Can also be enabled via the OAUTH_ENABLE_CLIENT_REGISTRATION=true env var. * * @deprecated on MCP 2026-07-28: the final authorization spec deprecates DCR * in favor of Client ID Metadata Documents (CIMD, see `auth/cimd.ts`). DCR * remains supported on the legacy path and as an explicit opt-in; prefer CIMD * for new 2026-07-28 deployments. */ enableClientRegistration?: boolean; /** * Static client id returned by the registration endpoint. * Falls back to the OAUTH_CLIENT_ID environment variable. No literal default. */ staticClientId?: string; /** * Static client secret returned by the registration endpoint. * Falls back to the OAUTH_CLIENT_SECRET environment variable. No literal default. */ staticClientSecret?: string; /** * Allow the insecure, signature-less JWT decode fallback in `validateToken` * when neither `tokenIntrospectionEndpoint` nor `jwksUri` is configured. * * Disabled by default: without a configured verifier, tokens are rejected * (fail closed). Only enable for local development or tests where unsigned * tokens are intentionally used. NEVER enable in production. */ allowInsecureTokenDecode?: boolean; /** * Whether OAuth authentication is enforced. * * Resolved from the `OAUTH_REQUIRED` environment variable when not set * explicitly, and defaults to `false` (dev-friendly). When `false`, the OAuth * module and its discovery endpoints stay configured, but requests are NOT * required to carry a valid token (protected endpoints are reachable openly). * * When `true`, auth is enforced (fail-closed). If no token verifier * (`jwksUri` or `tokenIntrospectionEndpoint`) is configured, the server still * starts and logs a warning, but all protected requests are rejected until a * verifier is configured. */ required?: boolean; } import { NitroStackServer } from './server.js'; import { Logger } from './types.js'; /** * OAuth discovery info that can be communicated to clients */ export interface OAuthDiscoveryInfo { /** Whether OAuth is enabled */ enabled: boolean; /** The port the discovery server is running on */ discoveryPort: number; /** Resource URI for token audience validation */ resourceUri: string; /** Authorization server URLs */ authorizationServers: string[]; /** Supported scopes */ scopesSupported?: string[]; } export declare class OAuthModule { private config; private server; private logger; private static config; private static discoveryInfo; private discoveryServer; private static discoveryMetadataCache; private static discoveryMetadataInflight; /** Max time to wait for an upstream metadata document before giving up. */ private static readonly UPSTREAM_FETCH_TIMEOUT_MS; /** How long to remember that an upstream lookup failed, to avoid refetch storms. */ private static readonly NEGATIVE_CACHE_TTL_MS; private fetchUpstreamMetadata; private buildBaseUrl; private wellKnownHandler; /** * Whether the static Dynamic Client Registration endpoint is enabled. * Requires explicit opt-in AND a configured client id (never a literal default). */ private isClientRegistrationEnabled; private registrationHandler; private resourceMetadataHandler; constructor(config: OAuthModuleConfig, server: NitroStackServer, logger: Logger); onModuleInit(): void; /** * Get the preferred port for the OAuth discovery server * Priority: OAUTH_DISCOVERY_PORT > MCP_SERVER_PORT > PORT > config > 3005 */ private getPreferredPort; /** * Emit a clear, one-time startup log describing the current enforcement mode, * so a misconfigured or intentionally-open server is obvious in the logs. */ private logEnforcementMode; start(): Promise; /** * Update the static discovery info */ private updateDiscoveryInfo; /** * Notify the client about OAuth configuration via stderr * This uses a JSON format that clients can parse from stderr */ private notifyClientAboutOAuth; stop(): Promise; private registerDiscoveryHandlers; /** * Get the current OAuth discovery info * Returns null if OAuth is not configured or not started */ static getDiscoveryInfo(): OAuthDiscoveryInfo | null; /** * Configure OAuth module for the application */ static forRoot(config: OAuthModuleConfig): { module: typeof OAuthModule; providers: { provide: string; useValue: OAuthModuleConfig; }[]; }; /** * Get current OAuth configuration */ static getConfig(): OAuthModuleConfig | null; /** * Whether OAuth authentication is enforced. * * Returns `false` when the module is unconfigured or `required` is not `true`, * in which case protected endpoints are reachable without a token. */ static isAuthRequired(): boolean; /** * Validate an access token * * Performs: * 1. Token introspection (if endpoint configured) * 2. Audience validation (RFC 8807) * 3. Issuer validation (if configured) * 4. Custom validation (if configured) */ static validateToken(token: string): Promise<{ valid: boolean; payload?: Record; error?: string; }>; /** * Decode JWT token (without validation) * @private */ private static decodeToken; } //# sourceMappingURL=oauth-module.d.ts.map