UNPKG

@vfarcic/dot-ai

Version:

AI-powered development productivity platform that enhances software development workflows through intelligent automation and AI-driven assistance

115 lines 5.43 kB
/** * MCP SDK OAuth Server Provider for PRD #380. * * Implements the SDK's OAuthServerProvider interface with: * - In-memory client store (clients re-register on restart per MCP spec) * - Dual-mode token verification (JWT + legacy DOT_AI_AUTH_TOKEN) * - Dex OIDC integration for authorize/callback/token flow (Task 2.3) */ import type { Request, Response } from 'express'; import type { OAuthRegisteredClientsStore } from '@modelcontextprotocol/sdk/server/auth/clients.js'; import type { OAuthServerProvider, AuthorizationParams } from '@modelcontextprotocol/sdk/server/auth/provider.js'; import type { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js'; import type { OAuthClientInformationFull, OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth.js'; /** * In-memory client store for OAuth registered clients. * Clients re-register on server restart per the MCP Authorization spec. */ export declare class DotAIClientsStore implements OAuthRegisteredClientsStore { private clients; getClient(clientId: string): OAuthClientInformationFull | undefined; registerClient(client: Omit<OAuthClientInformationFull, 'client_id' | 'client_id_issued_at'>): OAuthClientInformationFull; /** Clear all registered clients. For testing only. @internal */ _clearClients(): void; } /** * OAuth Server Provider for dot-ai. * * Acts as the OAuth Authorization Server for MCP clients. On authorize, * redirects the browser to Dex for authentication, then exchanges the * Dex code for an ID token and issues a dot-ai JWT. * * Token verification supports dual-mode: JWT first, legacy token fallback. */ export declare class DotAIOAuthProvider implements OAuthServerProvider { readonly clientsStore: DotAIClientsStore; private pendingRequests; private authCodes; private requestedExpiries; private dexConfig; private dotAiExternalUrl; private pruneTimer; constructor(); /** * Periodically remove expired entries from pendingRequests and authCodes * to prevent unbounded memory growth from abandoned OAuth flows. */ private startPruning; /** Remove expired pending requests and authorization codes. */ private pruneExpired; /** Stop the pruning timer. For testing only. @internal */ _stopPruning(): void; /** * Store a client-requested token expiry for an upcoming token exchange. * Called by middleware that intercepts POST /token before the SDK handler. * * @param authorizationCode - The authorization code from the token request * @param requestedExpiry - Requested expiry in seconds */ setRequestedExpiry(authorizationCode: string, requestedExpiry: number): void; /** * Calculate token expiry based on client request, defaults, and limits. * * Priority: * 1. Client-requested expiry (if valid and within max limit) * 2. OAUTH_DEFAULT_TOKEN_TTL_SECONDS env var * 3. Built-in default (1 day) * * @param authorizationCode - The authorization code being exchanged * @returns Expiry time in seconds */ private getTokenExpiry; private loadDexConfig; /** * Start the authorization flow by redirecting the browser to Dex. * * Stores the pending auth request (PKCE challenge, redirect URI, state) * keyed by a random session ID, then encodes sessionId|originalState * in the Dex state param so the callback can recover the pending request. */ authorize(client: OAuthClientInformationFull, params: AuthorizationParams, res: Response): Promise<void>; /** * Return the PKCE code challenge for a given authorization code. * * Called by the SDK's tokenHandler BEFORE exchangeAuthorizationCode. * Do NOT delete the code here — it is consumed in exchangeAuthorizationCode. */ challengeForAuthorizationCode(client: OAuthClientInformationFull, authorizationCode: string): Promise<string>; /** * Exchange a dot-ai authorization code for a JWT access token. * * Called by the SDK's tokenHandler AFTER PKCE verification passes. * Consumes the authorization code (one-time use) and signs a JWT * containing the user's identity from the Dex ID token. */ exchangeAuthorizationCode(client: OAuthClientInformationFull, authorizationCode: string, _codeVerifier?: string, redirectUri?: string, _resource?: URL): Promise<OAuthTokens>; exchangeRefreshToken(_client: OAuthClientInformationFull, _refreshToken: string, _scopes?: string[], _resource?: URL): Promise<OAuthTokens>; /** * Handle the Dex OIDC callback after user authenticates. * * Receives the redirect from Dex with ?code=DEX_CODE&state=sessionId|originalState. * Exchanges the Dex code for an ID token, extracts user identity, * creates a dot-ai authorization code, and redirects to the MCP client. */ handleCallback(req: Request, res: Response): Promise<void>; /** * Verify an access token (dual-mode: JWT + legacy token). * * 1. If no auth configured → anonymous access (backward compatible) * 2. Try JWT verification → returns AuthInfo with identity in `extra` * 3. Fall back to legacy DOT_AI_AUTH_TOKEN → returns AuthInfo without identity * 4. Throw InvalidTokenError on failure */ verifyAccessToken(token: string): Promise<AuthInfo>; } //# sourceMappingURL=provider.d.ts.map