/** * OAuth 2.1 token endpoint — three grants: * * 1. grant_type=client_credentials (RFC 6749 §4.4) * Server-to-server. ChatGPT Apps SDK track. Unchanged from the * original ChatGPT-only implementation. * * 2. grant_type=authorization_code (RFC 6749 §4.1 + RFC 7636 PKCE) * Required by Anthropic Claude.ai connectors. Redeems a single-use * code issued by /oauth/authorize. PKCE S256 mandatory. Issues an * access_token AND a refresh_token. * * 3. grant_type=refresh_token (RFC 6749 §6) * Rotates refresh tokens — every successful refresh revokes the * previous token and issues a new one. Replay of a revoked token * revokes the entire chain (RFC 6749 §10.4). * * Flow: * POST /oauth/token * Content-Type: application/x-www-form-urlencoded * * client_credentials: grant_type=client_credentials&client_id=...&client_secret=... * authorization_code: grant_type=authorization_code&code=...&redirect_uri=... * &code_verifier=...&client_id=...[&client_secret=...] * refresh_token: grant_type=refresh_token&refresh_token=...&client_id=... * [&client_secret=...] * * Tokens are stored in Supabase. Access tokens: opaque 64-char hex, 1h TTL. * Refresh tokens: opaque 64-char hex returned once, SHA-256 hashed at rest, * 30d TTL, single-use, rotation chain via mcp_refresh_tokens.rotated_to. * * Public PKCE clients (token_endpoint_auth_method=none) may omit client_secret * on authorization_code and refresh_token grants — RFC 8252 §8.4. PKCE is the * authentication factor in that case. */ import type { VercelRequest, VercelResponse } from "./_types.js"; export default function handler(req: VercelRequest, res: VercelResponse): Promise;