kavachos 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/a2a/index.d.ts +2 -2
- package/dist/agent/index.d.ts +3 -3
- package/dist/agent/index.js +4 -0
- package/dist/agent/index.js.map +1 -1
- package/dist/audit/index.d.ts +2 -2
- package/dist/audit/index.js +4 -0
- package/dist/audit/index.js.map +1 -1
- package/dist/auth/index.d.ts +64 -3
- package/dist/auth/index.js +91 -2
- package/dist/auth/index.js.map +1 -1
- package/dist/index.d.ts +32 -4
- package/dist/index.js +851 -67
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.d.ts +2 -2
- package/dist/mcp/index.js +38 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/permission/index.d.ts +8 -3
- package/dist/permission/index.js +68 -59
- package/dist/permission/index.js.map +1 -1
- package/dist/{types-BuHrZcjE.d.ts → types-BiUe9e8u.d.ts} +24 -0
- package/dist/{types-B02D3kZy.d.ts → types-RJPOU4un.d.ts} +114 -2
- package/dist/vc/index.d.ts +254 -65
- package/dist/vc/index.js +160 -12
- package/dist/vc/index.js.map +1 -1
- package/package.json +2 -1
package/dist/mcp/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/mcp/types.ts","../../src/crypto/web-crypto.ts","../../src/mcp/utils.ts","../../src/mcp/authorize.ts","../../src/mcp/consent.ts","../../src/mcp/metadata.ts","../../src/mcp/registration.ts","../../src/mcp/step-up.ts","../../src/mcp/validate.ts","../../src/mcp/require-scopes.ts","../../src/mcp/token.ts","../../src/mcp/server.ts"],"names":["parsed"],"mappings":"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","file":"index.js","sourcesContent":["import { z } from \"zod\";\n\n// ─── Result Type ────────────────────────────────────────────────────────────\n\nexport interface KavachError {\n\tcode: string;\n\tmessage: string;\n\tdetails?: Record<string, unknown>;\n}\n\nexport type Result<T> = { success: true; data: T } | { success: false; error: KavachError };\n\n// ─── MCP Module Configuration ───────────────────────────────────────────────\n\nexport interface McpConfig {\n\t/** Enable MCP authorization server */\n\tenabled: boolean;\n\t/** Enforce auth on all MCP requests */\n\tenforceAuth?: boolean;\n\t/** Custom scopes supported by this server */\n\tscopes?: string[];\n\t/** Issuer URL (typically your base URL) */\n\tissuer?: string;\n\t/** Base URL for MCP endpoints */\n\tbaseUrl?: string;\n\t/** Secret key for signing JWTs (must be >= 32 chars) */\n\tsigningSecret?: string;\n\t/** Access token TTL in seconds (default: 3600) */\n\taccessTokenTtl?: number;\n\t/** Refresh token TTL in seconds (default: 604800 = 7 days) */\n\trefreshTokenTtl?: number;\n\t/** Authorization code TTL in seconds (default: 600 = 10 minutes) */\n\tcodeTtl?: number;\n\t/** Allowed resource URIs for RFC 8707 */\n\tallowedResources?: string[];\n\t/** Login page URL - where users are redirected to authenticate */\n\tloginPage?: string;\n\t/** Consent page URL - where users approve scopes */\n\tconsentPage?: string;\n\t/**\n\t * Clients that are pre-registered at startup.\n\t *\n\t * These are stored via `storeClient` when the module is created,\n\t * so they behave identically to dynamically-registered clients.\n\t * Useful for first-party apps, CLIs, or test fixtures that should\n\t * always exist without a prior registration call.\n\t */\n\tpreRegisteredClients?: Array<{\n\t\tclientId: string;\n\t\tclientSecret?: string;\n\t\tredirectUris: string[];\n\t\tclientName?: string;\n\t\tscope?: string;\n\t}>;\n\t/** Custom token claims generator */\n\tgetAdditionalClaims?: (userId: string, scopes: string[]) => Promise<Record<string, unknown>>;\n}\n\n// ─── OAuth 2.0 Authorization Server Metadata (RFC 8414) ─────────────────────\n\nexport interface McpServerMetadata {\n\tissuer: string;\n\tauthorization_endpoint: string;\n\ttoken_endpoint: string;\n\tregistration_endpoint: string;\n\tjwks_uri?: string;\n\tscopes_supported: string[];\n\tresponse_types_supported: string[];\n\tresponse_modes_supported: string[];\n\tgrant_types_supported: string[];\n\ttoken_endpoint_auth_methods_supported: string[];\n\tcode_challenge_methods_supported: string[];\n\tservice_documentation?: string;\n\trevocation_endpoint?: string;\n}\n\n// ─── Protected Resource Metadata (RFC 9728) ─────────────────────────────────\n\nexport interface McpProtectedResourceMetadata {\n\tresource: string;\n\tauthorization_servers: string[];\n\tjwks_uri?: string;\n\tscopes_supported: string[];\n\tbearer_methods_supported: string[];\n\tresource_signing_alg_values_supported?: string[];\n}\n\n// ─── OAuth Client (RFC 7591 Dynamic Client Registration) ────────────────────\n\nexport interface McpClient {\n\tclientId: string;\n\tclientSecret: string | null;\n\tclientName: string | null;\n\tclientUri: string | null;\n\tlogoUri: string | null;\n\tredirectUris: string[];\n\tgrantTypes: string[];\n\tresponseTypes: string[];\n\ttokenEndpointAuthMethod: string;\n\tscope: string | null;\n\tcontacts: string[] | null;\n\ttosUri: string | null;\n\tpolicyUri: string | null;\n\tsoftwareId: string | null;\n\tsoftwareVersion: string | null;\n\tclientType: \"public\" | \"confidential\";\n\tdisabled: boolean;\n\tuserId: string | null;\n\tcreatedAt: Date;\n\tupdatedAt: Date;\n}\n\nexport interface McpClientRegistrationRequest {\n\tredirect_uris: string[];\n\ttoken_endpoint_auth_method?: string;\n\tgrant_types?: string[];\n\tresponse_types?: string[];\n\tclient_name?: string;\n\tclient_uri?: string;\n\tlogo_uri?: string;\n\tscope?: string;\n\tcontacts?: string[];\n\ttos_uri?: string;\n\tpolicy_uri?: string;\n\tsoftware_id?: string;\n\tsoftware_version?: string;\n}\n\nexport interface McpClientRegistrationResponse {\n\tclient_id: string;\n\tclient_secret?: string;\n\tclient_id_issued_at: number;\n\tclient_secret_expires_at?: number;\n\tredirect_uris: string[];\n\ttoken_endpoint_auth_method: string;\n\tgrant_types: string[];\n\tresponse_types: string[];\n\tclient_name?: string;\n\tclient_uri?: string;\n\tlogo_uri?: string;\n\tscope?: string;\n\tcontacts?: string[];\n\ttos_uri?: string;\n\tpolicy_uri?: string;\n\tsoftware_id?: string;\n\tsoftware_version?: string;\n}\n\n// ─── Authorization Code ─────────────────────────────────────────────────────\n\nexport interface McpAuthorizationCode {\n\tcode: string;\n\tclientId: string;\n\tuserId: string;\n\tredirectUri: string;\n\tscope: string[];\n\tcodeChallenge: string;\n\tcodeChallengeMethod: \"S256\";\n\tresource: string | null;\n\texpiresAt: Date;\n\tcreatedAt: Date;\n}\n\n// ─── Authorization Request ──────────────────────────────────────────────────\n\nexport interface McpAuthorizeRequest {\n\tresponse_type: string;\n\tclient_id: string;\n\tredirect_uri: string;\n\tscope?: string;\n\tstate?: string;\n\tcode_challenge: string;\n\tcode_challenge_method: string;\n\tresource?: string;\n}\n\nexport interface McpAuthorizeResult {\n\tredirectUri: string;\n\tcode: string;\n\tstate: string | null;\n}\n\n// ─── Access Token ───────────────────────────────────────────────────────────\n\nexport interface McpAccessToken {\n\taccessToken: string;\n\trefreshToken: string | null;\n\ttokenType: \"Bearer\";\n\texpiresIn: number;\n\tscope: string[];\n\tclientId: string;\n\tuserId: string;\n\tresource: string | null;\n\texpiresAt: Date;\n\tcreatedAt: Date;\n}\n\n// ─── Token Request / Response ───────────────────────────────────────────────\n\nexport interface McpTokenRequest {\n\tgrant_type: string;\n\tcode?: string;\n\tredirect_uri?: string;\n\tclient_id?: string;\n\tclient_secret?: string;\n\tcode_verifier?: string;\n\trefresh_token?: string;\n\tresource?: string;\n\tscope?: string;\n}\n\nexport interface McpTokenResponse {\n\taccess_token: string;\n\ttoken_type: \"Bearer\";\n\texpires_in: number;\n\trefresh_token?: string;\n\tscope: string;\n}\n\n// ─── Token Validation ───────────────────────────────────────────────────────\n\nexport interface McpTokenPayload {\n\tsub: string;\n\tiss: string;\n\taud: string | string[];\n\texp: number;\n\tiat: number;\n\tjti: string;\n\tscope: string;\n\tclient_id: string;\n}\n\nexport interface McpSession {\n\tuserId: string;\n\tclientId: string;\n\tscopes: string[];\n\tresource: string | null;\n\texpiresAt: Date;\n\ttokenId: string;\n}\n\n// ─── MCP Auth Context (passed to all handler functions) ─────────────────────\n\nexport interface McpAuthContext {\n\tconfig: Required<\n\t\tPick<McpConfig, \"issuer\" | \"baseUrl\" | \"accessTokenTtl\" | \"refreshTokenTtl\" | \"codeTtl\">\n\t> &\n\t\tMcpConfig;\n\t/** Store a client registration */\n\tstoreClient: (client: McpClient) => Promise<void>;\n\t/** Find a client by ID */\n\tfindClient: (clientId: string) => Promise<McpClient | null>;\n\t/** Store an authorization code */\n\tstoreAuthorizationCode: (code: McpAuthorizationCode) => Promise<void>;\n\t/** Find and consume an authorization code (must delete after finding) */\n\tconsumeAuthorizationCode: (code: string) => Promise<McpAuthorizationCode | null>;\n\t/** Store an access token record */\n\tstoreToken: (token: McpAccessToken) => Promise<void>;\n\t/** Find a token by refresh token value */\n\tfindTokenByRefreshToken: (refreshToken: string) => Promise<McpAccessToken | null>;\n\t/** Revoke a token (by access token value) */\n\trevokeToken: (accessToken: string) => Promise<void>;\n\t/** Resolve the authenticated user ID (e.g., from session cookie) */\n\tresolveUserId: (request: Request) => Promise<string | null>;\n}\n\n// ─── MCP Module (public API shape) ──────────────────────────────────────────\n\nexport interface ApproveConsentParams {\n\t/** Authenticated user who approved the consent */\n\tuserId: string;\n\tclientId: string;\n\t/** Space-separated scope string or array */\n\tscope: string | string[];\n\tstate?: string;\n\tredirectUri: string;\n\tcodeChallenge: string;\n\tcodeChallengeMethod: \"S256\";\n\tresource?: string;\n}\n\nexport interface McpAuthModule {\n\t/** Get OAuth 2.0 Authorization Server Metadata */\n\tgetMetadata: () => McpServerMetadata;\n\t/** Get Protected Resource Metadata (RFC 9728) */\n\tgetProtectedResourceMetadata: () => McpProtectedResourceMetadata;\n\t/** Register a new OAuth client (RFC 7591) */\n\tregisterClient: (\n\t\tbody: McpClientRegistrationRequest,\n\t) => Promise<Result<McpClientRegistrationResponse>>;\n\t/** Handle authorization request */\n\tauthorize: (request: Request) => Promise<Result<McpAuthorizeResult>>;\n\t/**\n\t * Issue an authorization code after a user has explicitly approved consent.\n\t *\n\t * When `config.consentPage` is set, `authorize` redirects to that page\n\t * instead of issuing a code directly. The consent page must call this\n\t * method after the user clicks \"Allow\".\n\t */\n\tapproveConsent: (params: ApproveConsentParams) => Promise<Result<{ redirectUri: string }>>;\n\t/** Handle token exchange */\n\ttoken: (request: Request) => Promise<Result<McpTokenResponse>>;\n\t/** Validate an access token */\n\tvalidateToken: (token: string, requiredScopes?: string[]) => Promise<Result<McpSession>>;\n\t/** Middleware that validates Bearer tokens and returns session */\n\tmiddleware: (request: Request) => Promise<Result<McpSession>>;\n\t/** Build a step-up challenge response (403) indicating required scopes */\n\tbuildStepUpResponse: (options: {\n\t\tcurrentScopes: string[];\n\t\trequiredScopes: string[];\n\t\tresource?: string;\n\t}) => Response;\n\t/** Validate token and check scopes. Returns session if valid, or a Response to send back */\n\trequireScopes: (\n\t\trequest: Request,\n\t\trequiredScopes: string[],\n\t) => Promise<\n\t\t{ authorized: true; session: McpSession } | { authorized: false; response: Response }\n\t>;\n}\n\n// ─── Zod Schemas ────────────────────────────────────────────────────────────\n\nexport const McpClientRegistrationSchema = z.object({\n\tredirect_uris: z.array(z.string().url()),\n\ttoken_endpoint_auth_method: z\n\t\t.enum([\"none\", \"client_secret_basic\", \"client_secret_post\"])\n\t\t.default(\"client_secret_basic\")\n\t\t.optional(),\n\tgrant_types: z\n\t\t.array(z.enum([\"authorization_code\", \"refresh_token\"]))\n\t\t.default([\"authorization_code\"])\n\t\t.optional(),\n\tresponse_types: z\n\t\t.array(z.enum([\"code\"]))\n\t\t.default([\"code\"])\n\t\t.optional(),\n\tclient_name: z.string().optional(),\n\tclient_uri: z.string().url().optional(),\n\tlogo_uri: z.string().url().optional(),\n\tscope: z.string().optional(),\n\tcontacts: z.array(z.string()).optional(),\n\ttos_uri: z.string().url().optional(),\n\tpolicy_uri: z.string().url().optional(),\n\tsoftware_id: z.string().optional(),\n\tsoftware_version: z.string().optional(),\n});\n\nexport const McpAuthorizeRequestSchema = z.object({\n\tresponse_type: z.literal(\"code\"),\n\tclient_id: z.string().min(1),\n\tredirect_uri: z.string().min(1),\n\tscope: z.string().optional(),\n\tstate: z.string().optional(),\n\tcode_challenge: z.string().min(43).max(128),\n\tcode_challenge_method: z.literal(\"S256\"),\n\tresource: z.string().url().optional(),\n});\n\nexport const McpTokenRequestSchema = z.discriminatedUnion(\"grant_type\", [\n\tz.object({\n\t\tgrant_type: z.literal(\"authorization_code\"),\n\t\tcode: z.string().min(1),\n\t\tredirect_uri: z.string().min(1),\n\t\tclient_id: z.string().min(1),\n\t\tclient_secret: z.string().optional(),\n\t\tcode_verifier: z.string().min(43).max(128),\n\t\tresource: z.string().url().optional(),\n\t}),\n\tz.object({\n\t\tgrant_type: z.literal(\"refresh_token\"),\n\t\trefresh_token: z.string().min(1),\n\t\tclient_id: z.string().min(1),\n\t\tclient_secret: z.string().optional(),\n\t\tscope: z.string().optional(),\n\t\tresource: z.string().url().optional(),\n\t}),\n]);\n\nexport type McpTokenRequestParsed = z.infer<typeof McpTokenRequestSchema>;\n","/**\n * Web Crypto API utilities for KavachOS.\n *\n * This module uses ONLY the Web Crypto API (globalThis.crypto) which is\n * available natively in Cloudflare Workers, Deno, Bun, and Node 20+.\n * No `node:crypto` imports are used, making the core package edge-compatible.\n */\n\n// ---------------------------------------------------------------------------\n// Encoding helpers\n// ---------------------------------------------------------------------------\n\nconst HEX_CHARS = \"0123456789abcdef\";\n\n/** Encode a Uint8Array as a lowercase hex string. */\nexport function toHex(bytes: Uint8Array): string {\n\tlet hex = \"\";\n\tfor (let i = 0; i < bytes.length; i++) {\n\t\tconst b = bytes[i] as number;\n\t\thex += HEX_CHARS[b >> 4] as string;\n\t\thex += HEX_CHARS[b & 0x0f] as string;\n\t}\n\treturn hex;\n}\n\n/** Decode a hex string into a Uint8Array. */\nexport function fromHex(hex: string): Uint8Array {\n\tif (hex.length % 2 !== 0) {\n\t\tthrow new Error(\"fromHex: hex string must have even length\");\n\t}\n\tconst bytes = new Uint8Array(hex.length / 2);\n\tfor (let i = 0; i < bytes.length; i++) {\n\t\tconst hi = parseInt(hex[i * 2] as string, 16);\n\t\tconst lo = parseInt(hex[i * 2 + 1] as string, 16);\n\t\tif (Number.isNaN(hi) || Number.isNaN(lo)) {\n\t\t\tthrow new Error(`fromHex: invalid hex character at position ${i * 2}`);\n\t\t}\n\t\tbytes[i] = (hi << 4) | lo;\n\t}\n\treturn bytes;\n}\n\n/** Encode a Uint8Array as a base64url string (no padding). */\nexport function toBase64Url(bytes: Uint8Array): string {\n\tlet binary = \"\";\n\tfor (let i = 0; i < bytes.length; i++) {\n\t\tbinary += String.fromCharCode(bytes[i] as number);\n\t}\n\treturn btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n/** Decode a base64url string into a Uint8Array. */\nexport function fromBase64Url(b64: string): Uint8Array {\n\t// Restore standard base64\n\tlet base64 = b64.replace(/-/g, \"+\").replace(/_/g, \"/\");\n\t// Add padding\n\twhile (base64.length % 4 !== 0) {\n\t\tbase64 += \"=\";\n\t}\n\tconst binary = atob(base64);\n\tconst bytes = new Uint8Array(binary.length);\n\tfor (let i = 0; i < binary.length; i++) {\n\t\tbytes[i] = binary.charCodeAt(i);\n\t}\n\treturn bytes;\n}\n\n// ---------------------------------------------------------------------------\n// Random generation\n// ---------------------------------------------------------------------------\n\n/** Generate a v4 UUID using the globally available crypto.randomUUID(). */\nexport function generateId(): string {\n\treturn globalThis.crypto.randomUUID();\n}\n\n/** Generate cryptographically secure random bytes as a Uint8Array. */\nexport function randomBytes(length: number): Uint8Array {\n\tconst bytes = new Uint8Array(length);\n\tglobalThis.crypto.getRandomValues(bytes);\n\treturn bytes;\n}\n\n/** Generate cryptographically secure random bytes as a hex string. */\nexport function randomBytesHex(length: number): string {\n\treturn toHex(randomBytes(length));\n}\n\n// ---------------------------------------------------------------------------\n// Text encoding helper (internal)\n// ---------------------------------------------------------------------------\n\nconst TEXT_ENCODER = new TextEncoder();\n\nfunction toBytes(data: string | Uint8Array): ArrayBuffer {\n\tif (typeof data === \"string\") {\n\t\tconst encoded = TEXT_ENCODER.encode(data);\n\t\treturn (encoded.buffer as ArrayBuffer).slice(\n\t\t\tencoded.byteOffset,\n\t\t\tencoded.byteOffset + encoded.byteLength,\n\t\t);\n\t}\n\treturn (data.buffer as ArrayBuffer).slice(data.byteOffset, data.byteOffset + data.byteLength);\n}\n\n// ---------------------------------------------------------------------------\n// Hashing\n// ---------------------------------------------------------------------------\n\n/** SHA-256 hash, returns hex string. */\nexport async function sha256(data: string | Uint8Array): Promise<string> {\n\tconst digest = await globalThis.crypto.subtle.digest(\"SHA-256\", toBytes(data));\n\treturn toHex(new Uint8Array(digest));\n}\n\n/** SHA-256 hash, returns Uint8Array. */\nexport async function sha256Raw(data: string | Uint8Array): Promise<Uint8Array> {\n\tconst digest = await globalThis.crypto.subtle.digest(\"SHA-256\", toBytes(data));\n\treturn new Uint8Array(digest);\n}\n\n/** SHA-1 hash, returns hex string. Needed for HIBP k-anonymity. */\nexport async function sha1(data: string | Uint8Array): Promise<string> {\n\tconst digest = await globalThis.crypto.subtle.digest(\"SHA-1\", toBytes(data));\n\treturn toHex(new Uint8Array(digest));\n}\n\n// ---------------------------------------------------------------------------\n// HMAC\n// ---------------------------------------------------------------------------\n\n/** Import a secret key for HMAC operations. */\nexport async function importHmacKey(\n\tkey: string | Uint8Array,\n\thash: \"SHA-256\" | \"SHA-1\" = \"SHA-256\",\n): Promise<CryptoKey> {\n\tconst keyData = typeof key === \"string\" ? TEXT_ENCODER.encode(key) : key;\n\treturn globalThis.crypto.subtle.importKey(\n\t\t\"raw\",\n\t\t(keyData.buffer as ArrayBuffer).slice(\n\t\t\tkeyData.byteOffset,\n\t\t\tkeyData.byteOffset + keyData.byteLength,\n\t\t),\n\t\t{ name: \"HMAC\", hash: { name: hash } },\n\t\tfalse,\n\t\t[\"sign\", \"verify\"],\n\t);\n}\n\n/** HMAC-SHA256 sign, returns hex string. */\nexport async function hmacSha256(\n\tkey: string | Uint8Array,\n\tdata: string | Uint8Array,\n): Promise<string> {\n\tconst cryptoKey = await importHmacKey(key, \"SHA-256\");\n\tconst signature = await globalThis.crypto.subtle.sign(\"HMAC\", cryptoKey, toBytes(data));\n\treturn toHex(new Uint8Array(signature));\n}\n\n/** HMAC-SHA256 sign, returns Uint8Array. */\nexport async function hmacSha256Raw(\n\tkey: string | Uint8Array,\n\tdata: string | Uint8Array,\n): Promise<Uint8Array> {\n\tconst cryptoKey = await importHmacKey(key, \"SHA-256\");\n\tconst signature = await globalThis.crypto.subtle.sign(\"HMAC\", cryptoKey, toBytes(data));\n\treturn new Uint8Array(signature);\n}\n\n/** HMAC-SHA1 sign, returns Uint8Array (needed for TOTP per RFC 6238). */\nexport async function hmacSha1Raw(key: Uint8Array, data: Uint8Array): Promise<Uint8Array> {\n\tconst cryptoKey = await importHmacKey(key, \"SHA-1\");\n\tconst buf = (data.buffer as ArrayBuffer).slice(\n\t\tdata.byteOffset,\n\t\tdata.byteOffset + data.byteLength,\n\t);\n\tconst signature = await globalThis.crypto.subtle.sign(\"HMAC\", cryptoKey, buf);\n\treturn new Uint8Array(signature);\n}\n\n// ---------------------------------------------------------------------------\n// PBKDF2 password hashing\n// ---------------------------------------------------------------------------\n\nconst PBKDF2_ITERATIONS = 100_000; // CF Workers caps at 100K; OWASP recommends 600K for Node.js\nconst PBKDF2_KEY_LENGTH = 64; // bytes\nconst PBKDF2_SALT_LENGTH = 32; // bytes\n\n/**\n * Hash a password using PBKDF2-SHA256.\n *\n * Returns a string in the format: `pbkdf2:iterations:salt_hex:hash_hex`\n * which is safe to store in the database.\n */\nexport async function pbkdf2Hash(\n\tpassword: string,\n\tsalt?: Uint8Array,\n\titerations?: number,\n): Promise<string> {\n\tconst actualSalt = salt ?? randomBytes(PBKDF2_SALT_LENGTH);\n\tconst actualIterations = iterations ?? PBKDF2_ITERATIONS;\n\n\tconst keyMaterial = await globalThis.crypto.subtle.importKey(\n\t\t\"raw\",\n\t\tTEXT_ENCODER.encode(password),\n\t\t\"PBKDF2\",\n\t\tfalse,\n\t\t[\"deriveBits\"],\n\t);\n\n\tconst saltBuf = (actualSalt.buffer as ArrayBuffer).slice(\n\t\tactualSalt.byteOffset,\n\t\tactualSalt.byteOffset + actualSalt.byteLength,\n\t);\n\tconst derived = await globalThis.crypto.subtle.deriveBits(\n\t\t{\n\t\t\tname: \"PBKDF2\",\n\t\t\tsalt: saltBuf,\n\t\t\titerations: actualIterations,\n\t\t\thash: \"SHA-256\",\n\t\t},\n\t\tkeyMaterial,\n\t\tPBKDF2_KEY_LENGTH * 8,\n\t);\n\n\treturn `pbkdf2:${actualIterations}:${toHex(actualSalt)}:${toHex(new Uint8Array(derived))}`;\n}\n\n/**\n * Verify a password against a stored PBKDF2 hash.\n *\n * Supports the `pbkdf2:iterations:salt:hash` format produced by `pbkdf2Hash`.\n */\nexport async function pbkdf2Verify(password: string, stored: string): Promise<boolean> {\n\tconst parts = stored.split(\":\");\n\tif (parts.length !== 4 || parts[0] !== \"pbkdf2\") {\n\t\treturn false;\n\t}\n\n\tconst iterations = parseInt(parts[1] as string, 10);\n\tconst salt = fromHex(parts[2] as string);\n\tconst storedHash = fromHex(parts[3] as string);\n\n\tif (Number.isNaN(iterations)) return false;\n\n\tconst keyMaterial = await globalThis.crypto.subtle.importKey(\n\t\t\"raw\",\n\t\tTEXT_ENCODER.encode(password),\n\t\t\"PBKDF2\",\n\t\tfalse,\n\t\t[\"deriveBits\"],\n\t);\n\n\tconst saltBuf = (salt.buffer as ArrayBuffer).slice(\n\t\tsalt.byteOffset,\n\t\tsalt.byteOffset + salt.byteLength,\n\t);\n\tconst derived = await globalThis.crypto.subtle.deriveBits(\n\t\t{\n\t\t\tname: \"PBKDF2\",\n\t\t\tsalt: saltBuf,\n\t\t\titerations,\n\t\t\thash: \"SHA-256\",\n\t\t},\n\t\tkeyMaterial,\n\t\tstoredHash.length * 8,\n\t);\n\n\treturn constantTimeEqual(new Uint8Array(derived), storedHash);\n}\n\n// ---------------------------------------------------------------------------\n// Constant-time comparison\n// ---------------------------------------------------------------------------\n\n/**\n * Constant-time comparison of two Uint8Arrays.\n * Returns false immediately if lengths differ (length is not secret).\n */\nexport function constantTimeEqual(a: Uint8Array, b: Uint8Array): boolean {\n\tif (a.byteLength !== b.byteLength) {\n\t\treturn false;\n\t}\n\tlet diff = 0;\n\tfor (let i = 0; i < a.byteLength; i++) {\n\t\tdiff |= (a[i] as number) ^ (b[i] as number);\n\t}\n\treturn diff === 0;\n}\n","import { generateId, randomBytes, toBase64Url } from \"../crypto/web-crypto.js\";\n\n/**\n * Generate a cryptographically secure random token string.\n *\n * Uses `crypto.getRandomValues()` (Web Crypto API compatible) to produce\n * a URL-safe base64 string of the requested byte length.\n */\nexport function generateSecureToken(byteLength: number): string {\n\tconst bytes = randomBytes(byteLength);\n\treturn toBase64Url(bytes);\n}\n\n/**\n * Generate a new authorization code.\n * Returns a UUID v4 string (compact, unique, unpredictable enough when\n * combined with PKCE code_verifier for security).\n */\nexport function generateAuthorizationCode(): string {\n\treturn generateId();\n}\n\n/**\n * Compute the S256 code challenge from a code verifier.\n *\n * S256: BASE64URL(SHA256(ASCII(code_verifier)))\n *\n * Uses Web Crypto (SubtleCrypto) for cross-runtime compatibility.\n */\nexport async function computeS256Challenge(codeVerifier: string): Promise<string> {\n\tconst encoder = new TextEncoder();\n\tconst data = encoder.encode(codeVerifier);\n\tconst digest = await globalThis.crypto.subtle.digest(\"SHA-256\", data);\n\treturn toBase64Url(new Uint8Array(digest));\n}\n\n/**\n * Verify a PKCE S256 code_verifier against a stored code_challenge.\n */\nexport async function verifyS256(codeVerifier: string, codeChallenge: string): Promise<boolean> {\n\tconst computed = await computeS256Challenge(codeVerifier);\n\treturn timingSafeEqual(computed, codeChallenge);\n}\n\n/**\n * Constant-time string comparison to prevent timing attacks.\n */\nfunction timingSafeEqual(a: string, b: string): boolean {\n\tif (a.length !== b.length) {\n\t\treturn false;\n\t}\n\tconst encoder = new TextEncoder();\n\tconst bufA = encoder.encode(a);\n\tconst bufB = encoder.encode(b);\n\n\tlet diff = 0;\n\tfor (let i = 0; i < bufA.length; i++) {\n\t\t// biome-ignore lint/style/noNonNullAssertion: length checked above\n\t\tdiff |= bufA[i]! ^ bufB[i]!;\n\t}\n\treturn diff === 0;\n}\n\n/**\n * Parse a URL search params or form body into a plain object.\n *\n * Handles both `application/x-www-form-urlencoded` and `application/json`\n * content types, as required by OAuth 2.1 token endpoint.\n */\nexport async function parseRequestBody(request: Request): Promise<Record<string, string>> {\n\tconst contentType = request.headers.get(\"content-type\") ?? \"\";\n\n\tif (contentType.includes(\"application/x-www-form-urlencoded\")) {\n\t\tconst text = await request.text();\n\t\tconst params = new URLSearchParams(text);\n\t\tconst result: Record<string, string> = {};\n\t\tfor (const [key, value] of params.entries()) {\n\t\t\tresult[key] = value;\n\t\t}\n\t\treturn result;\n\t}\n\n\tif (contentType.includes(\"application/json\")) {\n\t\tconst json = await request.json();\n\t\tif (typeof json === \"object\" && json !== null) {\n\t\t\tconst result: Record<string, string> = {};\n\t\t\tfor (const [key, value] of Object.entries(json as Record<string, unknown>)) {\n\t\t\t\tif (typeof value === \"string\") {\n\t\t\t\t\tresult[key] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\t}\n\n\treturn {};\n}\n\n/**\n * Extract client credentials from the Authorization header (Basic auth).\n *\n * Returns [client_id, client_secret] or null if not present.\n */\nexport function extractBasicAuth(request: Request): [string, string] | null {\n\tconst authorization = request.headers.get(\"authorization\");\n\tif (!authorization?.startsWith(\"Basic \")) {\n\t\treturn null;\n\t}\n\ttry {\n\t\tconst encoded = authorization.slice(6);\n\t\tconst decoded = atob(encoded);\n\t\tconst colonIndex = decoded.indexOf(\":\");\n\t\tif (colonIndex === -1) {\n\t\t\treturn null;\n\t\t}\n\t\tconst id = decoded.slice(0, colonIndex);\n\t\tconst secret = decoded.slice(colonIndex + 1);\n\t\tif (!id || !secret) {\n\t\t\treturn null;\n\t\t}\n\t\treturn [id, secret];\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Extract a Bearer token from the Authorization header.\n */\nexport function extractBearerToken(request: Request): string | null {\n\tconst authorization = request.headers.get(\"authorization\");\n\tif (!authorization?.startsWith(\"Bearer \")) {\n\t\treturn null;\n\t}\n\treturn authorization.slice(7);\n}\n","import type { McpAuthContext, McpAuthorizationCode, McpAuthorizeResult, Result } from \"./types.js\";\nimport { McpAuthorizeRequestSchema } from \"./types.js\";\nimport { generateAuthorizationCode } from \"./utils.js\";\n\n/**\n * Handle the OAuth 2.1 authorization endpoint.\n *\n * GET /mcp/authorize\n *\n * Validates the request parameters, checks the client, enforces PKCE S256,\n * validates Resource Indicators (RFC 8707), and issues an authorization code.\n *\n * The caller is responsible for authenticating the user before calling this\n * function. The `ctx.resolveUserId(request)` hook must return a non-null\n * user ID for the currently authenticated user.\n */\nexport async function handleAuthorize(\n\tctx: McpAuthContext,\n\trequest: Request,\n): Promise<Result<McpAuthorizeResult>> {\n\t// ── Parse query parameters ──────────────────────────────────────\n\tconst url = new URL(request.url);\n\tconst params: Record<string, string> = {};\n\tfor (const [key, value] of url.searchParams.entries()) {\n\t\tparams[key] = value;\n\t}\n\n\tconst parsed = McpAuthorizeRequestSchema.safeParse(params);\n\tif (!parsed.success) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_REQUEST\",\n\t\t\t\tmessage: \"Invalid authorization request parameters\",\n\t\t\t\tdetails: { issues: parsed.error.flatten().fieldErrors },\n\t\t\t},\n\t\t};\n\t}\n\n\tconst {\n\t\tclient_id: clientId,\n\t\tredirect_uri: redirectUri,\n\t\tscope: scopeParam,\n\t\tstate,\n\t\tcode_challenge: codeChallenge,\n\t\tcode_challenge_method: codeChallengeMethod,\n\t\tresource,\n\t} = parsed.data;\n\n\t// ── Validate client ─────────────────────────────────────────────\n\tconst client = await ctx.findClient(clientId);\n\tif (!client) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_CLIENT\",\n\t\t\t\tmessage: `Unknown client_id: ${clientId}`,\n\t\t\t},\n\t\t};\n\t}\n\n\tif (client.disabled) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_CLIENT\",\n\t\t\t\tmessage: \"Client is disabled\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Validate redirect_uri ───────────────────────────────────────\n\tif (!client.redirectUris.includes(redirectUri)) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_REDIRECT_URI\",\n\t\t\t\tmessage: \"redirect_uri does not match any registered redirect URI\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── PKCE validation: S256 only ──────────────────────────────────\n\tif (codeChallengeMethod !== \"S256\") {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_REQUEST\",\n\t\t\t\tmessage: \"Only S256 code_challenge_method is supported\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Validate resource parameter (RFC 8707) ──────────────────────\n\tif (resource !== undefined) {\n\t\tconst allowedResources = ctx.config.allowedResources;\n\t\tif (allowedResources && allowedResources.length > 0) {\n\t\t\tif (!allowedResources.includes(resource)) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: \"INVALID_TARGET\",\n\t\t\t\t\t\tmessage: `Resource '${resource}' is not a recognized MCP server`,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── Validate scopes ─────────────────────────────────────────────\n\tconst requestedScopes = scopeParam ? scopeParam.split(\" \").filter(Boolean) : [];\n\tconst supportedScopes = new Set(ctx.config.scopes ?? []);\n\tconst defaultScopes = new Set([\"openid\", \"profile\", \"email\", \"offline_access\"]);\n\tconst allSupported = new Set([...supportedScopes, ...defaultScopes]);\n\n\tfor (const scope of requestedScopes) {\n\t\tif (!allSupported.has(scope)) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"INVALID_SCOPE\",\n\t\t\t\t\tmessage: `Unsupported scope: ${scope}`,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t}\n\n\tconst effectiveScopes = requestedScopes.length > 0 ? requestedScopes : [\"openid\"];\n\n\t// ── Resolve authenticated user ──────────────────────────────────\n\tconst userId = await ctx.resolveUserId(request);\n\tif (!userId) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"LOGIN_REQUIRED\",\n\t\t\t\tmessage: \"User must be authenticated before authorization\",\n\t\t\t\tdetails: {\n\t\t\t\t\tloginPage: ctx.config.loginPage,\n\t\t\t\t\t// Pass all original query params so the login page can redirect back\n\t\t\t\t\treturnTo: request.url,\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Consent page redirect ───────────────────────────────────────\n\t// When a consent page is configured, redirect the user to it instead\n\t// of issuing an authorization code immediately. The consent page\n\t// collects explicit user approval and then calls approveConsent().\n\tif (ctx.config.consentPage) {\n\t\tconst consentUrl = new URL(ctx.config.consentPage);\n\t\tconsentUrl.searchParams.set(\"client_id\", clientId);\n\t\tconsentUrl.searchParams.set(\"redirect_uri\", redirectUri);\n\t\tconsentUrl.searchParams.set(\"scope\", effectiveScopes.join(\" \"));\n\t\tif (state) {\n\t\t\tconsentUrl.searchParams.set(\"state\", state);\n\t\t}\n\t\tconsentUrl.searchParams.set(\"code_challenge\", codeChallenge);\n\t\tconsentUrl.searchParams.set(\"code_challenge_method\", codeChallengeMethod);\n\t\tif (resource) {\n\t\t\tconsentUrl.searchParams.set(\"resource\", resource);\n\t\t}\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: {\n\t\t\t\tredirectUri: consentUrl.toString(),\n\t\t\t\tcode: \"\",\n\t\t\t\tstate: state ?? null,\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Generate authorization code ─────────────────────────────────\n\tconst code = generateAuthorizationCode();\n\tconst now = new Date();\n\tconst expiresAt = new Date(now.getTime() + ctx.config.codeTtl * 1000);\n\n\tconst authCode: McpAuthorizationCode = {\n\t\tcode,\n\t\tclientId,\n\t\tuserId,\n\t\tredirectUri,\n\t\tscope: effectiveScopes,\n\t\tcodeChallenge,\n\t\tcodeChallengeMethod: \"S256\",\n\t\tresource: resource ?? null,\n\t\texpiresAt,\n\t\tcreatedAt: now,\n\t};\n\n\tawait ctx.storeAuthorizationCode(authCode);\n\n\t// ── Build redirect ──────────────────────────────────────────────\n\tconst redirectUrl = new URL(redirectUri);\n\tredirectUrl.searchParams.set(\"code\", code);\n\tif (state) {\n\t\tredirectUrl.searchParams.set(\"state\", state);\n\t}\n\n\treturn {\n\t\tsuccess: true,\n\t\tdata: {\n\t\t\tredirectUri: redirectUrl.toString(),\n\t\t\tcode,\n\t\t\tstate: state ?? null,\n\t\t},\n\t};\n}\n","import type {\n\tApproveConsentParams,\n\tMcpAuthContext,\n\tMcpAuthorizationCode,\n\tResult,\n} from \"./types.js\";\nimport { generateAuthorizationCode } from \"./utils.js\";\n\nexport type { ApproveConsentParams };\n\n/**\n * Issue an authorization code after a user has explicitly approved consent.\n *\n * Call this from your consent page handler after the user clicks \"Allow\".\n * The params should match what was passed to the consent page as query params\n * by `handleAuthorize`.\n */\nexport async function approveConsent(\n\tctx: McpAuthContext,\n\tparams: ApproveConsentParams,\n): Promise<Result<{ redirectUri: string }>> {\n\tconst {\n\t\tuserId,\n\t\tclientId,\n\t\tscope,\n\t\tstate,\n\t\tredirectUri,\n\t\tcodeChallenge,\n\t\tcodeChallengeMethod,\n\t\tresource,\n\t} = params;\n\n\t// ── Validate client still exists and is enabled ─────────────────\n\tconst client = await ctx.findClient(clientId);\n\tif (!client) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_CLIENT\",\n\t\t\t\tmessage: `Unknown client_id: ${clientId}`,\n\t\t\t},\n\t\t};\n\t}\n\n\tif (client.disabled) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_CLIENT\",\n\t\t\t\tmessage: \"Client is disabled\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Validate redirect_uri ────────────────────────────────────────\n\tif (!client.redirectUris.includes(redirectUri)) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_REDIRECT_URI\",\n\t\t\t\tmessage: \"redirect_uri does not match any registered redirect URI\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Normalise scopes ─────────────────────────────────────────────\n\tconst effectiveScopes =\n\t\ttypeof scope === \"string\" ? scope.split(\" \").filter(Boolean) : scope.filter(Boolean);\n\n\tif (effectiveScopes.length === 0) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_SCOPE\",\n\t\t\t\tmessage: \"At least one scope is required\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Generate and store authorization code ────────────────────────\n\tconst code = generateAuthorizationCode();\n\tconst now = new Date();\n\tconst expiresAt = new Date(now.getTime() + ctx.config.codeTtl * 1000);\n\n\tconst authCode: McpAuthorizationCode = {\n\t\tcode,\n\t\tclientId,\n\t\tuserId,\n\t\tredirectUri,\n\t\tscope: effectiveScopes,\n\t\tcodeChallenge,\n\t\tcodeChallengeMethod,\n\t\tresource: resource ?? null,\n\t\texpiresAt,\n\t\tcreatedAt: now,\n\t};\n\n\tawait ctx.storeAuthorizationCode(authCode);\n\n\t// ── Build redirect back to client ────────────────────────────────\n\tconst redirectUrl = new URL(redirectUri);\n\tredirectUrl.searchParams.set(\"code\", code);\n\tif (state) {\n\t\tredirectUrl.searchParams.set(\"state\", state);\n\t}\n\n\treturn {\n\t\tsuccess: true,\n\t\tdata: {\n\t\t\tredirectUri: redirectUrl.toString(),\n\t\t},\n\t};\n}\n","import type { McpAuthContext, McpProtectedResourceMetadata, McpServerMetadata } from \"./types.js\";\n\n/**\n * Build OAuth 2.0 Authorization Server Metadata (RFC 8414).\n *\n * Returned at: GET /.well-known/oauth-authorization-server\n */\nexport function getAuthorizationServerMetadata(ctx: McpAuthContext): McpServerMetadata {\n\tconst { issuer, baseUrl, scopes } = ctx.config;\n\tconst defaultScopes = [\"openid\", \"profile\", \"email\", \"offline_access\"];\n\tconst allScopes = [...new Set([...defaultScopes, ...(scopes ?? [])])];\n\n\treturn {\n\t\tissuer,\n\t\tauthorization_endpoint: `${baseUrl}/mcp/authorize`,\n\t\ttoken_endpoint: `${baseUrl}/mcp/token`,\n\t\tregistration_endpoint: `${baseUrl}/mcp/register`,\n\t\tjwks_uri: `${baseUrl}/mcp/jwks`,\n\t\tscopes_supported: allScopes,\n\t\tresponse_types_supported: [\"code\"],\n\t\tresponse_modes_supported: [\"query\"],\n\t\tgrant_types_supported: [\"authorization_code\", \"refresh_token\"],\n\t\ttoken_endpoint_auth_methods_supported: [\"client_secret_basic\", \"client_secret_post\", \"none\"],\n\t\tcode_challenge_methods_supported: [\"S256\"],\n\t\trevocation_endpoint: `${baseUrl}/mcp/revoke`,\n\t};\n}\n\n/**\n * Build Protected Resource Metadata (RFC 9728).\n *\n * Returned at: GET /.well-known/oauth-protected-resource\n *\n * An MCP resource server (tool server) publishes this so clients can\n * discover which authorization server to use.\n */\nexport function getProtectedResourceMetadata(ctx: McpAuthContext): McpProtectedResourceMetadata {\n\tconst { issuer, baseUrl, scopes } = ctx.config;\n\tconst defaultScopes = [\"openid\", \"profile\", \"email\", \"offline_access\"];\n\tconst allScopes = [...new Set([...defaultScopes, ...(scopes ?? [])])];\n\n\treturn {\n\t\tresource: issuer,\n\t\tauthorization_servers: [issuer],\n\t\tjwks_uri: `${baseUrl}/mcp/jwks`,\n\t\tscopes_supported: allScopes,\n\t\tbearer_methods_supported: [\"header\"],\n\t\tresource_signing_alg_values_supported: [\"HS256\"],\n\t};\n}\n","import { generateId } from \"../crypto/web-crypto.js\";\nimport type { McpAuthContext, McpClient, McpClientRegistrationResponse, Result } from \"./types.js\";\nimport { McpClientRegistrationSchema } from \"./types.js\";\nimport { generateSecureToken } from \"./utils.js\";\n\n/**\n * Validate whether a client_id that is an HTTPS URL points to a valid\n * Client ID Metadata Document. Per the MCP spec, when a client_id is\n * an HTTPS URL the authorization server SHOULD fetch the document and\n * verify that the redirect_uris in the registration request match those\n * in the metadata document.\n *\n * Returns the resolved redirect URIs from the metadata document, or null\n * if the client_id is not a URL.\n */\nasync function resolveClientIdMetadataDocument(clientId: string): Promise<string[] | null> {\n\ttry {\n\t\tconst url = new URL(clientId);\n\t\tif (url.protocol !== \"https:\") {\n\t\t\treturn null;\n\t\t}\n\t\tconst response = await fetch(clientId, {\n\t\t\theaders: { Accept: \"application/json\" },\n\t\t\tsignal: AbortSignal.timeout(5_000),\n\t\t});\n\t\tif (!response.ok) {\n\t\t\treturn null;\n\t\t}\n\t\tconst metadata = (await response.json()) as {\n\t\t\tredirect_uris?: string[];\n\t\t\tclient_name?: string;\n\t\t\tclient_uri?: string;\n\t\t};\n\t\tif (Array.isArray(metadata.redirect_uris)) {\n\t\t\treturn metadata.redirect_uris;\n\t\t}\n\t\treturn null;\n\t} catch {\n\t\t// Not a URL or fetch failed -- treat as opaque client_id\n\t\treturn null;\n\t}\n}\n\n/**\n * Dynamic Client Registration (RFC 7591).\n *\n * Endpoint logic for: POST /mcp/register\n *\n * Validates the registration request, generates client credentials,\n * persists the client via the context store, and returns the\n * RFC 7591-compliant registration response.\n */\nexport async function registerClient(\n\tctx: McpAuthContext,\n\tbody: unknown,\n): Promise<Result<McpClientRegistrationResponse>> {\n\t// ── Validate input ──────────────────────────────────────────────────\n\tconst parsed = McpClientRegistrationSchema.safeParse(body);\n\tif (!parsed.success) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_CLIENT_METADATA\",\n\t\t\t\tmessage: \"Invalid client registration request\",\n\t\t\t\tdetails: { issues: parsed.error.flatten().fieldErrors },\n\t\t\t},\n\t\t};\n\t}\n\n\tconst data = parsed.data;\n\tconst redirectUris = data.redirect_uris;\n\tconst grantTypes = data.grant_types ?? [\"authorization_code\"];\n\tconst responseTypes = data.response_types ?? [\"code\"];\n\tconst authMethod = data.token_endpoint_auth_method ?? \"client_secret_basic\";\n\n\t// ── Validate redirect_uris are required for authorization_code ────\n\tif (grantTypes.includes(\"authorization_code\") && redirectUris.length === 0) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_REDIRECT_URI\",\n\t\t\t\tmessage: \"redirect_uris are required when grant_types includes authorization_code\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Validate grant_type / response_type consistency ──────────────\n\tif (grantTypes.includes(\"authorization_code\") && !responseTypes.includes(\"code\")) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_CLIENT_METADATA\",\n\t\t\t\tmessage:\n\t\t\t\t\t\"response_types must include 'code' when grant_types includes 'authorization_code'\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Validate redirect URIs ──────────────────────────────────────\n\tfor (const uri of redirectUris) {\n\t\ttry {\n\t\t\tconst parsed = new URL(uri);\n\t\t\t// Localhost is allowed for development; production requires HTTPS\n\t\t\tif (\n\t\t\t\tparsed.protocol !== \"https:\" &&\n\t\t\t\tparsed.hostname !== \"localhost\" &&\n\t\t\t\tparsed.hostname !== \"127.0.0.1\" &&\n\t\t\t\tparsed.hostname !== \"[::1]\"\n\t\t\t) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: \"INVALID_REDIRECT_URI\",\n\t\t\t\t\t\tmessage: `redirect_uri must use HTTPS (or localhost for development): ${uri}`,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\t// Fragment not allowed per OAuth 2.1\n\t\t\tif (parsed.hash) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: \"INVALID_REDIRECT_URI\",\n\t\t\t\t\t\tmessage: `redirect_uri must not contain a fragment: ${uri}`,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t} catch {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"INVALID_REDIRECT_URI\",\n\t\t\t\t\tmessage: `redirect_uri is not a valid URL: ${uri}`,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t}\n\n\t// ── Generate credentials ────────────────────────────────────────\n\tconst clientId = generateId();\n\tconst isPublic = authMethod === \"none\";\n\tconst clientSecret = isPublic ? null : generateSecureToken(48);\n\n\t// ── Client ID Metadata Document support ─────────────────────────\n\t// If the caller provides a client_uri that is an HTTPS URL, we\n\t// attempt to fetch the metadata document. If it exists and contains\n\t// redirect_uris, we verify they match the request.\n\tif (data.client_uri) {\n\t\tconst metadataUris = await resolveClientIdMetadataDocument(data.client_uri);\n\t\tif (metadataUris !== null) {\n\t\t\tconst metadataSet = new Set(metadataUris);\n\t\t\tconst mismatched = redirectUris.filter((u) => !metadataSet.has(u));\n\t\t\tif (mismatched.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: \"INVALID_REDIRECT_URI\",\n\t\t\t\t\t\tmessage: \"redirect_uris do not match those in the Client ID Metadata Document\",\n\t\t\t\t\t\tdetails: { mismatched },\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── Persist ─────────────────────────────────────────────────────\n\tconst now = new Date();\n\tconst client: McpClient = {\n\t\tclientId,\n\t\tclientSecret,\n\t\tclientName: data.client_name ?? null,\n\t\tclientUri: data.client_uri ?? null,\n\t\tlogoUri: data.logo_uri ?? null,\n\t\tredirectUris,\n\t\tgrantTypes,\n\t\tresponseTypes,\n\t\ttokenEndpointAuthMethod: authMethod,\n\t\tscope: data.scope ?? null,\n\t\tcontacts: data.contacts ?? null,\n\t\ttosUri: data.tos_uri ?? null,\n\t\tpolicyUri: data.policy_uri ?? null,\n\t\tsoftwareId: data.software_id ?? null,\n\t\tsoftwareVersion: data.software_version ?? null,\n\t\tclientType: isPublic ? \"public\" : \"confidential\",\n\t\tdisabled: false,\n\t\tuserId: null,\n\t\tcreatedAt: now,\n\t\tupdatedAt: now,\n\t};\n\n\tawait ctx.storeClient(client);\n\n\t// ── Build response ──────────────────────────────────────────────\n\tconst response: McpClientRegistrationResponse = {\n\t\tclient_id: clientId,\n\t\tclient_id_issued_at: Math.floor(now.getTime() / 1000),\n\t\tredirect_uris: redirectUris,\n\t\ttoken_endpoint_auth_method: authMethod,\n\t\tgrant_types: grantTypes,\n\t\tresponse_types: responseTypes,\n\t\t...(data.client_name ? { client_name: data.client_name } : {}),\n\t\t...(data.client_uri ? { client_uri: data.client_uri } : {}),\n\t\t...(data.logo_uri ? { logo_uri: data.logo_uri } : {}),\n\t\t...(data.scope ? { scope: data.scope } : {}),\n\t\t...(data.contacts ? { contacts: data.contacts } : {}),\n\t\t...(data.tos_uri ? { tos_uri: data.tos_uri } : {}),\n\t\t...(data.policy_uri ? { policy_uri: data.policy_uri } : {}),\n\t\t...(data.software_id ? { software_id: data.software_id } : {}),\n\t\t...(data.software_version ? { software_version: data.software_version } : {}),\n\t\t...(clientSecret !== null ? { client_secret: clientSecret, client_secret_expires_at: 0 } : {}),\n\t};\n\n\treturn { success: true, data: response };\n}\n","import type { McpAuthContext } from \"./types.js\";\n\n// ─── CORS headers (same as other MCP endpoints) ──────────────────────────────\n\nconst CORS_HEADERS = {\n\t\"Access-Control-Allow-Origin\": \"*\",\n\t\"Access-Control-Allow-Methods\": \"GET, POST, OPTIONS\",\n\t\"Access-Control-Allow-Headers\": \"Content-Type, Authorization\",\n\t\"Access-Control-Max-Age\": \"86400\",\n} as const;\n\n/**\n * Build a step-up challenge response (403) indicating required scopes.\n *\n * When a token has valid scopes but lacks a specific scope needed for an\n * operation, return this response so the client knows it must re-authorize\n * with the additional scopes.\n *\n * Per RFC 6750 §3.1 the WWW-Authenticate header uses the\n * `error=\"insufficient_scope\"` challenge to signal the exact upgrade path.\n */\nexport function buildStepUpResponse(\n\tctx: McpAuthContext,\n\toptions: {\n\t\tcurrentScopes: string[];\n\t\trequiredScopes: string[];\n\t\tresource?: string;\n\t},\n): Response {\n\tconst { currentScopes, requiredScopes, resource } = options;\n\n\t// Build upgrade URL pointing at the authorization endpoint\n\tconst authorizationEndpoint = `${ctx.config.baseUrl}/authorize`;\n\tconst upgradeUrl = new URL(authorizationEndpoint);\n\tupgradeUrl.searchParams.set(\"scope\", requiredScopes.join(\" \"));\n\tif (resource) {\n\t\tupgradeUrl.searchParams.set(\"resource\", resource);\n\t}\n\n\t// WWW-Authenticate per RFC 6750 §3 + insufficient_scope challenge\n\tconst scopeList = requiredScopes.join(\" \");\n\tconst wwwAuthenticate = `Bearer error=\"insufficient_scope\", scope=\"${scopeList}\"`;\n\n\tconst body = {\n\t\terror: \"insufficient_scope\",\n\t\terror_description: \"Token lacks required scopes\",\n\t\trequired_scopes: requiredScopes,\n\t\tcurrent_scopes: currentScopes,\n\t\tupgrade_url: upgradeUrl.toString(),\n\t};\n\n\treturn new Response(JSON.stringify(body), {\n\t\tstatus: 403,\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\"WWW-Authenticate\": wwwAuthenticate,\n\t\t\t\"Access-Control-Expose-Headers\": \"WWW-Authenticate\",\n\t\t\t...CORS_HEADERS,\n\t\t},\n\t});\n}\n","import { jwtVerify } from \"jose\";\nimport type { McpAuthContext, McpSession, McpTokenPayload, Result } from \"./types.js\";\nimport { extractBearerToken } from \"./utils.js\";\n\n/**\n * Derive the HMAC verification key from the config's signing secret.\n */\nasync function getVerificationKey(secret: string): Promise<CryptoKey> {\n\tconst encoder = new TextEncoder();\n\treturn globalThis.crypto.subtle.importKey(\n\t\t\"raw\",\n\t\tencoder.encode(secret),\n\t\t{ name: \"HMAC\", hash: \"SHA-256\" },\n\t\tfalse,\n\t\t[\"verify\"],\n\t);\n}\n\n/**\n * Validate an MCP access token (JWT).\n *\n * Performs:\n * 1. JWT signature verification (HS256)\n * 2. Expiry check\n * 3. Issuer validation\n * 4. Audience validation (token must be bound to the expected resource)\n * 5. Scope validation (optional - checks all required scopes are present)\n *\n * Target: < 5ms with cached keys (per CLAUDE.md performance rule).\n */\nexport async function validateAccessToken(\n\tctx: McpAuthContext,\n\ttoken: string,\n\toptions?: {\n\t\trequiredScopes?: string[];\n\t\texpectedAudience?: string;\n\t},\n): Promise<Result<McpSession>> {\n\tconst secret = ctx.config.signingSecret;\n\tif (!secret) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"SERVER_ERROR\",\n\t\t\t\tmessage: \"MCP signingSecret is not configured\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Verify JWT ──────────────────────────────────────────────────\n\tlet payload: McpTokenPayload;\n\ttry {\n\t\tconst key = await getVerificationKey(secret);\n\t\tconst result = await jwtVerify(token, key, {\n\t\t\tissuer: ctx.config.issuer,\n\t\t\talgorithms: [\"HS256\"],\n\t\t\t...(options?.expectedAudience ? { audience: options.expectedAudience } : {}),\n\t\t});\n\t\tpayload = result.payload as unknown as McpTokenPayload;\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : \"Token verification failed\";\n\n\t\t// Map jose errors to meaningful error codes\n\t\tlet code = \"INVALID_TOKEN\";\n\t\tif (message.includes(\"expired\")) {\n\t\t\tcode = \"TOKEN_EXPIRED\";\n\t\t} else if (message.includes(\"audience\")) {\n\t\t\tcode = \"INVALID_AUDIENCE\";\n\t\t} else if (message.includes(\"issuer\")) {\n\t\t\tcode = \"INVALID_ISSUER\";\n\t\t}\n\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code, message },\n\t\t};\n\t}\n\n\t// ── Validate required fields exist ──────────────────────────────\n\tif (!payload.sub || !payload.client_id || !payload.jti) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_TOKEN\",\n\t\t\t\tmessage: \"Token is missing required claims (sub, client_id, jti)\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Audience validation (mandatory per MCP spec) ────────────────\n\t// If no explicit audience was provided to check, we still verify\n\t// the token has an audience claim.\n\tconst audience = payload.aud;\n\tif (!audience) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_AUDIENCE\",\n\t\t\t\tmessage: \"Token has no audience claim. Tokens must be bound to a resource.\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Scope validation ────────────────────────────────────────────\n\tconst tokenScopes = payload.scope ? payload.scope.split(\" \") : [];\n\tconst requiredScopes = options?.requiredScopes ?? [];\n\n\tfor (const required of requiredScopes) {\n\t\tif (!tokenScopes.includes(required)) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"INSUFFICIENT_SCOPE\",\n\t\t\t\t\tmessage: `Token is missing required scope: ${required}`,\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\trequired: requiredScopes,\n\t\t\t\t\t\tpresent: tokenScopes,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t}\n\n\t// ── Determine resource from audience ────────────────────────────\n\tconst resource = Array.isArray(audience) ? (audience[0] ?? null) : audience;\n\n\t// ── Build session ───────────────────────────────────────────────\n\tconst session: McpSession = {\n\t\tuserId: payload.sub,\n\t\tclientId: payload.client_id,\n\t\tscopes: tokenScopes,\n\t\tresource,\n\t\texpiresAt: new Date(payload.exp * 1000),\n\t\ttokenId: payload.jti,\n\t};\n\n\treturn { success: true, data: session };\n}\n\n/**\n * MCP auth middleware.\n *\n * Extracts the Bearer token from the Authorization header, validates it,\n * and returns the session. This is the primary entry point for protecting\n * MCP resource server endpoints.\n *\n * Pattern inspired by better-auth's `withMcpAuth()`, adapted to KavachOS's\n * functional Result-based API.\n *\n * Usage:\n * ```typescript\n * const result = await withMcpAuth(ctx, request, { requiredScopes: ['read'] });\n * if (!result.success) {\n * return new Response(JSON.stringify(result.error), { status: 401 });\n * }\n * const session = result.data;\n * ```\n */\nexport async function withMcpAuth(\n\tctx: McpAuthContext,\n\trequest: Request,\n\toptions?: {\n\t\trequiredScopes?: string[];\n\t\texpectedAudience?: string;\n\t},\n): Promise<Result<McpSession>> {\n\tconst token = extractBearerToken(request);\n\n\tif (!token) {\n\t\tconst resourceMetadataUrl = `${ctx.config.baseUrl}/.well-known/oauth-protected-resource`;\n\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"UNAUTHORIZED\",\n\t\t\t\tmessage: \"Bearer token required\",\n\t\t\t\tdetails: {\n\t\t\t\t\t\"www-authenticate\": `Bearer resource_metadata=\"${resourceMetadataUrl}\"`,\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\n\treturn validateAccessToken(ctx, token, options);\n}\n\n/**\n * Build a 401 Unauthorized response in the JSON-RPC format expected\n * by MCP clients.\n *\n * Includes the WWW-Authenticate header pointing to the protected\n * resource metadata document, as required by the MCP spec.\n */\nexport function buildUnauthorizedResponse(\n\tctx: McpAuthContext,\n\terror: { code: string; message: string },\n): Response {\n\tconst resourceMetadataUrl = `${ctx.config.baseUrl}/.well-known/oauth-protected-resource`;\n\n\tconst wwwAuthenticate = `Bearer resource_metadata=\"${resourceMetadataUrl}\"`;\n\n\treturn new Response(\n\t\tJSON.stringify({\n\t\t\tjsonrpc: \"2.0\",\n\t\t\terror: {\n\t\t\t\tcode: -32000,\n\t\t\t\tmessage: error.message,\n\t\t\t\t\"www-authenticate\": wwwAuthenticate,\n\t\t\t},\n\t\t\tid: null,\n\t\t}),\n\t\t{\n\t\t\tstatus: 401,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\"WWW-Authenticate\": wwwAuthenticate,\n\t\t\t\t\"Access-Control-Expose-Headers\": \"WWW-Authenticate\",\n\t\t\t},\n\t\t},\n\t);\n}\n","import { buildStepUpResponse } from \"./step-up.js\";\nimport type { McpAuthContext, McpSession } from \"./types.js\";\nimport { extractBearerToken } from \"./utils.js\";\nimport { buildUnauthorizedResponse, validateAccessToken } from \"./validate.js\";\n\n// ─── Scope challenge helper ───────────────────────────────────────────────────\n\n/**\n * Validate the Bearer token on a request and assert that it carries all of\n * the `requiredScopes`.\n *\n * Encapsulates the three-branch decision MCP resource servers need to make:\n *\n * 1. No token (or malformed token) → 401 Unauthorized\n * 2. Valid token, missing scopes → 403 with step-up challenge\n * 3. Valid token, all scopes present → session returned to the caller\n *\n * Usage:\n * ```typescript\n * const check = await requireScopes(ctx, request, ['mcp:write']);\n * if (!check.authorized) return check.response;\n * // check.session is available here\n * ```\n */\nexport async function requireScopes(\n\tctx: McpAuthContext,\n\trequest: Request,\n\trequiredScopes: string[],\n): Promise<{ authorized: true; session: McpSession } | { authorized: false; response: Response }> {\n\t// ── Step 1: Extract Bearer token ────────────────────────────────\n\tconst token = extractBearerToken(request);\n\n\tif (!token) {\n\t\treturn {\n\t\t\tauthorized: false,\n\t\t\tresponse: buildUnauthorizedResponse(ctx, {\n\t\t\t\tcode: \"UNAUTHORIZED\",\n\t\t\t\tmessage: \"Bearer token required\",\n\t\t\t}),\n\t\t};\n\t}\n\n\t// ── Step 2: Validate the token (without scope enforcement yet) ──\n\t// We validate first without requiredScopes so we can distinguish\n\t// \"bad token\" (401) from \"valid token but wrong scopes\" (403).\n\tconst tokenResult = await validateAccessToken(ctx, token);\n\n\tif (!tokenResult.success) {\n\t\treturn {\n\t\t\tauthorized: false,\n\t\t\tresponse: buildUnauthorizedResponse(ctx, {\n\t\t\t\tcode: tokenResult.error.code,\n\t\t\t\tmessage: tokenResult.error.message,\n\t\t\t}),\n\t\t};\n\t}\n\n\tconst session = tokenResult.data;\n\n\t// ── Step 3: Check required scopes ───────────────────────────────\n\tif (requiredScopes.length > 0) {\n\t\tconst missingScopes = requiredScopes.filter((s) => !session.scopes.includes(s));\n\n\t\tif (missingScopes.length > 0) {\n\t\t\treturn {\n\t\t\t\tauthorized: false,\n\t\t\t\tresponse: buildStepUpResponse(ctx, {\n\t\t\t\t\tcurrentScopes: session.scopes,\n\t\t\t\t\trequiredScopes,\n\t\t\t\t\tresource: session.resource ?? undefined,\n\t\t\t\t}),\n\t\t\t};\n\t\t}\n\t}\n\n\t// ── Step 4: All checks passed ────────────────────────────────────\n\treturn { authorized: true, session };\n}\n","import { SignJWT } from \"jose\";\nimport { generateId } from \"../crypto/web-crypto.js\";\nimport type {\n\tMcpAccessToken,\n\tMcpAuthContext,\n\tMcpTokenRequestParsed,\n\tMcpTokenResponse,\n\tResult,\n} from \"./types.js\";\nimport { McpTokenRequestSchema } from \"./types.js\";\nimport { extractBasicAuth, generateSecureToken, parseRequestBody, verifyS256 } from \"./utils.js\";\n\n/**\n * Derive the HMAC signing key from the config's signing secret.\n *\n * Uses the Web Crypto API so this works in Node, Deno, Bun, CF Workers.\n */\nasync function getSigningKey(secret: string): Promise<CryptoKey> {\n\tconst encoder = new TextEncoder();\n\treturn globalThis.crypto.subtle.importKey(\n\t\t\"raw\",\n\t\tencoder.encode(secret),\n\t\t{ name: \"HMAC\", hash: \"SHA-256\" },\n\t\tfalse,\n\t\t[\"sign\", \"verify\"],\n\t);\n}\n\n/**\n * Issue a signed JWT access token.\n */\nasync function issueAccessTokenJwt(\n\tctx: McpAuthContext,\n\tuserId: string,\n\tclientId: string,\n\tscopes: string[],\n\tresource: string | null,\n): Promise<{ jwt: string; jti: string; expiresAt: Date }> {\n\tconst secret = ctx.config.signingSecret;\n\tif (!secret) {\n\t\tthrow new Error(\"MCP signingSecret is required to issue tokens\");\n\t}\n\tconst key = await getSigningKey(secret);\n\tconst jti = generateId();\n\tconst now = Math.floor(Date.now() / 1000);\n\tconst exp = now + ctx.config.accessTokenTtl;\n\tconst expiresAt = new Date(exp * 1000);\n\n\t// Audience: either the specific resource (RFC 8707) or the issuer\n\tconst audience = resource ?? ctx.config.issuer;\n\n\tconst jwt = await new SignJWT({\n\t\tsub: userId,\n\t\tclient_id: clientId,\n\t\tscope: scopes.join(\" \"),\n\t\tjti,\n\t})\n\t\t.setProtectedHeader({ alg: \"HS256\", typ: \"at+jwt\" })\n\t\t.setIssuer(ctx.config.issuer)\n\t\t.setAudience(audience)\n\t\t.setIssuedAt(now)\n\t\t.setExpirationTime(exp)\n\t\t.sign(key);\n\n\treturn { jwt, jti, expiresAt };\n}\n\n/**\n * Resolve client credentials from the request.\n *\n * Supports:\n * - HTTP Basic Authentication (client_secret_basic)\n * - Body parameters (client_secret_post)\n * - No auth (public clients, token_endpoint_auth_method = \"none\")\n */\nfunction resolveClientCredentials(\n\trequest: Request,\n\tbody: Record<string, string>,\n): { clientId: string; clientSecret: string | null } | null {\n\t// Try Basic auth first\n\tconst basicAuth = extractBasicAuth(request);\n\tif (basicAuth) {\n\t\treturn { clientId: basicAuth[0], clientSecret: basicAuth[1] };\n\t}\n\n\t// Fall back to body params\n\tconst clientId = body.client_id;\n\tif (!clientId) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tclientId,\n\t\tclientSecret: body.client_secret ?? null,\n\t};\n}\n\n/**\n * Handle the OAuth 2.1 token endpoint.\n *\n * POST /mcp/token\n *\n * Supports two grant types:\n * 1. authorization_code - Exchange auth code + PKCE verifier for tokens\n * 2. refresh_token - Refresh an expired access token\n */\nexport async function handleTokenExchange(\n\tctx: McpAuthContext,\n\trequest: Request,\n): Promise<Result<McpTokenResponse>> {\n\t// ── Parse body ──────────────────────────────────────────────────\n\tconst body = await parseRequestBody(request);\n\n\t// ── Resolve client credentials ──────────────────────────────────\n\tconst credentials = resolveClientCredentials(request, body);\n\tif (!credentials) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_CLIENT\",\n\t\t\t\tmessage: \"client_id is required\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// Override body client_id with the resolved one\n\tbody.client_id = credentials.clientId;\n\tif (credentials.clientSecret) {\n\t\tbody.client_secret = credentials.clientSecret;\n\t}\n\n\t// ── Validate request body against schema ────────────────────────\n\tconst parsed = McpTokenRequestSchema.safeParse(body);\n\tif (!parsed.success) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_REQUEST\",\n\t\t\t\tmessage: \"Invalid token request\",\n\t\t\t\tdetails: { issues: parsed.error.flatten().fieldErrors },\n\t\t\t},\n\t\t};\n\t}\n\n\tconst data = parsed.data;\n\n\tif (data.grant_type === \"authorization_code\") {\n\t\treturn handleAuthorizationCodeGrant(ctx, data, credentials.clientSecret);\n\t}\n\n\treturn handleRefreshTokenGrant(ctx, data, credentials.clientSecret);\n}\n\n/**\n * authorization_code grant: exchange code + PKCE verifier for tokens.\n */\nasync function handleAuthorizationCodeGrant(\n\tctx: McpAuthContext,\n\tdata: Extract<McpTokenRequestParsed, { grant_type: \"authorization_code\" }>,\n\tclientSecret: string | null,\n): Promise<Result<McpTokenResponse>> {\n\t// ── Look up the client ──────────────────────────────────────────\n\tconst client = await ctx.findClient(data.client_id);\n\tif (!client) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_CLIENT\", message: \"Unknown client_id\" },\n\t\t};\n\t}\n\n\tif (client.disabled) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_CLIENT\", message: \"Client is disabled\" },\n\t\t};\n\t}\n\n\t// ── Validate client secret for confidential clients ─────────────\n\tif (client.clientType === \"confidential\") {\n\t\tif (!clientSecret || clientSecret !== client.clientSecret) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"INVALID_CLIENT\", message: \"Invalid client_secret\" },\n\t\t\t};\n\t\t}\n\t}\n\n\t// ── Consume the authorization code (one-time use) ───────────────\n\tconst authCode = await ctx.consumeAuthorizationCode(data.code);\n\tif (!authCode) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_GRANT\", message: \"Invalid or expired authorization code\" },\n\t\t};\n\t}\n\n\t// ── Validate code is not expired ────────────────────────────────\n\tif (authCode.expiresAt < new Date()) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_GRANT\", message: \"Authorization code has expired\" },\n\t\t};\n\t}\n\n\t// ── Validate client_id matches the code ─────────────────────────\n\tif (authCode.clientId !== data.client_id) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_GRANT\", message: \"client_id does not match authorization code\" },\n\t\t};\n\t}\n\n\t// ── Validate redirect_uri matches the code ──────────────────────\n\tif (authCode.redirectUri !== data.redirect_uri) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_GRANT\",\n\t\t\t\tmessage: \"redirect_uri does not match authorization code\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── PKCE: verify code_verifier against stored code_challenge ────\n\tconst pkceValid = await verifyS256(data.code_verifier, authCode.codeChallenge);\n\tif (!pkceValid) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_GRANT\", message: \"PKCE code_verifier verification failed\" },\n\t\t};\n\t}\n\n\t// ── Validate resource parameter (RFC 8707) ──────────────────────\n\t// If the auth code was bound to a resource, the token request must\n\t// either omit the resource parameter or match.\n\tif (data.resource !== undefined && authCode.resource !== null) {\n\t\tif (data.resource !== authCode.resource) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"INVALID_TARGET\",\n\t\t\t\t\tmessage: \"resource parameter does not match authorization code\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t}\n\n\tconst resource = data.resource ?? authCode.resource;\n\n\t// ── Issue tokens ────────────────────────────────────────────────\n\tconst { jwt, expiresAt } = await issueAccessTokenJwt(\n\t\tctx,\n\t\tauthCode.userId,\n\t\tdata.client_id,\n\t\tauthCode.scope,\n\t\tresource,\n\t);\n\n\tconst includeRefreshToken = authCode.scope.includes(\"offline_access\");\n\tconst refreshToken = includeRefreshToken ? generateSecureToken(48) : null;\n\n\tconst tokenRecord: McpAccessToken = {\n\t\taccessToken: jwt,\n\t\trefreshToken,\n\t\ttokenType: \"Bearer\",\n\t\texpiresIn: ctx.config.accessTokenTtl,\n\t\tscope: authCode.scope,\n\t\tclientId: data.client_id,\n\t\tuserId: authCode.userId,\n\t\tresource,\n\t\texpiresAt,\n\t\tcreatedAt: new Date(),\n\t};\n\n\tawait ctx.storeToken(tokenRecord);\n\n\t// ── Build response ──────────────────────────────────────────────\n\tconst response: McpTokenResponse = {\n\t\taccess_token: jwt,\n\t\ttoken_type: \"Bearer\",\n\t\texpires_in: ctx.config.accessTokenTtl,\n\t\tscope: authCode.scope.join(\" \"),\n\t\t...(refreshToken ? { refresh_token: refreshToken } : {}),\n\t};\n\n\treturn { success: true, data: response };\n}\n\n/**\n * refresh_token grant: rotate tokens.\n */\nasync function handleRefreshTokenGrant(\n\tctx: McpAuthContext,\n\tdata: Extract<McpTokenRequestParsed, { grant_type: \"refresh_token\" }>,\n\tclientSecret: string | null,\n): Promise<Result<McpTokenResponse>> {\n\t// ── Look up the client ──────────────────────────────────────────\n\tconst client = await ctx.findClient(data.client_id);\n\tif (!client) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_CLIENT\", message: \"Unknown client_id\" },\n\t\t};\n\t}\n\n\tif (client.disabled) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_CLIENT\", message: \"Client is disabled\" },\n\t\t};\n\t}\n\n\t// ── Validate client secret for confidential clients ─────────────\n\tif (client.clientType === \"confidential\") {\n\t\tif (!clientSecret || clientSecret !== client.clientSecret) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"INVALID_CLIENT\", message: \"Invalid client_secret\" },\n\t\t\t};\n\t\t}\n\t}\n\n\t// ── Find the existing token by refresh_token ────────────────────\n\tconst existingToken = await ctx.findTokenByRefreshToken(data.refresh_token);\n\tif (!existingToken) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_GRANT\", message: \"Invalid refresh token\" },\n\t\t};\n\t}\n\n\t// ── Validate client_id matches ──────────────────────────────────\n\tif (existingToken.clientId !== data.client_id) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_GRANT\", message: \"client_id does not match refresh token\" },\n\t\t};\n\t}\n\n\t// ── Check refresh token expiry ──────────────────────────────────\n\tconst refreshExpiry = new Date(\n\t\texistingToken.createdAt.getTime() + ctx.config.refreshTokenTtl * 1000,\n\t);\n\tif (refreshExpiry < new Date()) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_GRANT\", message: \"Refresh token has expired\" },\n\t\t};\n\t}\n\n\t// ── Determine scopes (may be narrowed in the request) ───────────\n\tconst scopes = data.scope\n\t\t? data.scope.split(\" \").filter((s) => existingToken.scope.includes(s))\n\t\t: existingToken.scope;\n\n\t// ── Determine resource ──────────────────────────────────────────\n\tconst resource = data.resource ?? existingToken.resource;\n\n\t// ── Revoke the old token ────────────────────────────────────────\n\tawait ctx.revokeToken(existingToken.accessToken);\n\n\t// ── Issue new tokens (token rotation for security) ──────────────\n\tconst { jwt, expiresAt } = await issueAccessTokenJwt(\n\t\tctx,\n\t\texistingToken.userId,\n\t\tdata.client_id,\n\t\tscopes,\n\t\tresource,\n\t);\n\n\tconst newRefreshToken = generateSecureToken(48);\n\n\tconst tokenRecord: McpAccessToken = {\n\t\taccessToken: jwt,\n\t\trefreshToken: newRefreshToken,\n\t\ttokenType: \"Bearer\",\n\t\texpiresIn: ctx.config.accessTokenTtl,\n\t\tscope: scopes,\n\t\tclientId: data.client_id,\n\t\tuserId: existingToken.userId,\n\t\tresource,\n\t\texpiresAt,\n\t\tcreatedAt: new Date(),\n\t};\n\n\tawait ctx.storeToken(tokenRecord);\n\n\t// ── Build response ──────────────────────────────────────────────\n\tconst response: McpTokenResponse = {\n\t\taccess_token: jwt,\n\t\ttoken_type: \"Bearer\",\n\t\texpires_in: ctx.config.accessTokenTtl,\n\t\trefresh_token: newRefreshToken,\n\t\tscope: scopes.join(\" \"),\n\t};\n\n\treturn { success: true, data: response };\n}\n","import { handleAuthorize } from \"./authorize.js\";\nimport { approveConsent } from \"./consent.js\";\nimport { getAuthorizationServerMetadata, getProtectedResourceMetadata } from \"./metadata.js\";\nimport { registerClient } from \"./registration.js\";\nimport { requireScopes } from \"./require-scopes.js\";\nimport { buildStepUpResponse } from \"./step-up.js\";\nimport { handleTokenExchange } from \"./token.js\";\nimport type {\n\tApproveConsentParams,\n\tMcpAuthContext,\n\tMcpAuthModule,\n\tMcpClient,\n\tMcpClientRegistrationRequest,\n\tMcpConfig,\n\tResult,\n} from \"./types.js\";\nimport { buildUnauthorizedResponse, validateAccessToken, withMcpAuth } from \"./validate.js\";\n\n// ─── Default Configuration ──────────────────────────────────────────────────\n\nconst DEFAULT_ACCESS_TOKEN_TTL = 3600; // 1 hour\nconst DEFAULT_REFRESH_TOKEN_TTL = 604800; // 7 days\nconst DEFAULT_CODE_TTL = 600; // 10 minutes\n\n/**\n * Create the MCP authorization server module.\n *\n * This is the main factory that wires up all MCP OAuth 2.1 endpoints\n * into a single module. The caller provides storage callbacks (how to\n * persist clients, codes, and tokens) and user resolution (how to identify\n * the currently authenticated user).\n *\n * @example\n * ```typescript\n * const mcp = createMcpModule({\n * config: {\n * enabled: true,\n * issuer: 'https://auth.example.com',\n * baseUrl: 'https://auth.example.com/api/auth',\n * signingSecret: process.env.MCP_SIGNING_SECRET,\n * },\n * storeClient: async (client) => { await db.insert(mcpClients).values(client); },\n * findClient: async (id) => { return db.query.mcpClients.findFirst({ where: eq(mcpClients.clientId, id) }); },\n * storeAuthorizationCode: async (code) => { await db.insert(mcpCodes).values(code); },\n * consumeAuthorizationCode: async (code) => {\n * const found = await db.query.mcpCodes.findFirst({ where: eq(mcpCodes.code, code) });\n * if (found) await db.delete(mcpCodes).where(eq(mcpCodes.code, code));\n * return found ?? null;\n * },\n * storeToken: async (token) => { await db.insert(mcpTokens).values(token); },\n * findTokenByRefreshToken: async (rt) => { ... },\n * revokeToken: async (at) => { ... },\n * resolveUserId: async (request) => {\n * const session = await getSession(request);\n * return session?.userId ?? null;\n * },\n * });\n *\n * // Use in a framework adapter:\n * app.get('/.well-known/oauth-authorization-server', () => mcp.getMetadata());\n * app.get('/.well-known/oauth-protected-resource', () => mcp.getProtectedResourceMetadata());\n * app.post('/mcp/register', (req) => mcp.registerClient(req.body));\n * app.get('/mcp/authorize', (req) => mcp.authorize(req));\n * app.post('/mcp/token', (req) => mcp.token(req));\n * ```\n */\nexport function createMcpModule(params: {\n\tconfig: McpConfig;\n\tstoreClient: McpAuthContext[\"storeClient\"];\n\tfindClient: McpAuthContext[\"findClient\"];\n\tstoreAuthorizationCode: McpAuthContext[\"storeAuthorizationCode\"];\n\tconsumeAuthorizationCode: McpAuthContext[\"consumeAuthorizationCode\"];\n\tstoreToken: McpAuthContext[\"storeToken\"];\n\tfindTokenByRefreshToken: McpAuthContext[\"findTokenByRefreshToken\"];\n\trevokeToken: McpAuthContext[\"revokeToken\"];\n\tresolveUserId: McpAuthContext[\"resolveUserId\"];\n}): McpAuthModule {\n\t// ── Validate required config ────────────────────────────────────\n\tconst config = params.config;\n\tif (!config.issuer) {\n\t\tthrow new Error(\"McpConfig.issuer is required\");\n\t}\n\tif (!config.baseUrl) {\n\t\tthrow new Error(\"McpConfig.baseUrl is required\");\n\t}\n\tif (!config.signingSecret) {\n\t\tthrow new Error(\"McpConfig.signingSecret is required (>= 32 chars)\");\n\t}\n\tif (config.signingSecret.length < 32) {\n\t\tthrow new Error(\"McpConfig.signingSecret must be at least 32 characters\");\n\t}\n\n\t// ── Build resolved config with defaults ─────────────────────────\n\tconst resolvedConfig = {\n\t\t...config,\n\t\tissuer: config.issuer,\n\t\tbaseUrl: config.baseUrl,\n\t\tsigningSecret: config.signingSecret,\n\t\taccessTokenTtl: config.accessTokenTtl ?? DEFAULT_ACCESS_TOKEN_TTL,\n\t\trefreshTokenTtl: config.refreshTokenTtl ?? DEFAULT_REFRESH_TOKEN_TTL,\n\t\tcodeTtl: config.codeTtl ?? DEFAULT_CODE_TTL,\n\t};\n\n\t// ── Build the context shared by all handlers ────────────────────\n\tconst ctx: McpAuthContext = {\n\t\tconfig: resolvedConfig,\n\t\tstoreClient: params.storeClient,\n\t\tfindClient: params.findClient,\n\t\tstoreAuthorizationCode: params.storeAuthorizationCode,\n\t\tconsumeAuthorizationCode: params.consumeAuthorizationCode,\n\t\tstoreToken: params.storeToken,\n\t\tfindTokenByRefreshToken: params.findTokenByRefreshToken,\n\t\trevokeToken: params.revokeToken,\n\t\tresolveUserId: params.resolveUserId,\n\t};\n\n\t// ── Pre-register static clients ─────────────────────────────────\n\t// Store each pre-registered client via storeClient during module\n\t// initialisation. Returns a Promise that callers may await if needed.\n\tconst preRegistrationPromise: Promise<void> = (async () => {\n\t\tconst preClients = resolvedConfig.preRegisteredClients ?? [];\n\t\tconst now = new Date();\n\t\tfor (const preClient of preClients) {\n\t\t\tconst isPublic = preClient.clientSecret === undefined || preClient.clientSecret === null;\n\t\t\tconst client: McpClient = {\n\t\t\t\tclientId: preClient.clientId,\n\t\t\t\tclientSecret: preClient.clientSecret ?? null,\n\t\t\t\tclientName: preClient.clientName ?? null,\n\t\t\t\tclientUri: null,\n\t\t\t\tlogoUri: null,\n\t\t\t\tredirectUris: preClient.redirectUris,\n\t\t\t\tgrantTypes: [\"authorization_code\", \"refresh_token\"],\n\t\t\t\tresponseTypes: [\"code\"],\n\t\t\t\ttokenEndpointAuthMethod: isPublic ? \"none\" : \"client_secret_basic\",\n\t\t\t\tscope: preClient.scope ?? null,\n\t\t\t\tcontacts: null,\n\t\t\t\ttosUri: null,\n\t\t\t\tpolicyUri: null,\n\t\t\t\tsoftwareId: null,\n\t\t\t\tsoftwareVersion: null,\n\t\t\t\tclientType: isPublic ? \"public\" : \"confidential\",\n\t\t\t\tdisabled: false,\n\t\t\t\tuserId: null,\n\t\t\t\tcreatedAt: now,\n\t\t\t\tupdatedAt: now,\n\t\t\t};\n\t\t\tawait params.storeClient(client);\n\t\t}\n\t})();\n\n\t// Expose the promise so tests/callers can await full initialisation.\n\tvoid preRegistrationPromise;\n\n\t// ── Return the public module API ────────────────────────────────\n\treturn {\n\t\tgetMetadata: () => getAuthorizationServerMetadata(ctx),\n\t\tgetProtectedResourceMetadata: () => getProtectedResourceMetadata(ctx),\n\n\t\tregisterClient: (body: McpClientRegistrationRequest) => registerClient(ctx, body),\n\n\t\tauthorize: (request: Request) => handleAuthorize(ctx, request),\n\n\t\tapproveConsent: (p: ApproveConsentParams) => approveConsent(ctx, p),\n\n\t\ttoken: (request: Request) => handleTokenExchange(ctx, request),\n\n\t\tvalidateToken: (token: string, requiredScopes?: string[]) =>\n\t\t\tvalidateAccessToken(ctx, token, { requiredScopes }),\n\n\t\tmiddleware: (request: Request) => withMcpAuth(ctx, request),\n\n\t\tbuildStepUpResponse: (options: {\n\t\t\tcurrentScopes: string[];\n\t\t\trequiredScopes: string[];\n\t\t\tresource?: string;\n\t\t}) => buildStepUpResponse(ctx, options),\n\n\t\trequireScopes: (request: Request, scopes: string[]) => requireScopes(ctx, request, scopes),\n\t};\n}\n\n/**\n * Create HTTP Response helpers for framework adapters.\n *\n * These take Result types and produce standard Response objects\n * with proper status codes, cache-control headers, and CORS.\n */\nexport function createMcpResponseHelpers(ctx: McpAuthContext) {\n\tconst corsHeaders = {\n\t\t\"Access-Control-Allow-Origin\": \"*\",\n\t\t\"Access-Control-Allow-Methods\": \"GET, POST, OPTIONS\",\n\t\t\"Access-Control-Allow-Headers\": \"Content-Type, Authorization\",\n\t\t\"Access-Control-Max-Age\": \"86400\",\n\t};\n\n\treturn {\n\t\t/** Metadata endpoints: 200 with JSON */\n\t\tmetadataResponse: (data: unknown): Response =>\n\t\t\tnew Response(JSON.stringify(data), {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t...corsHeaders,\n\t\t\t\t},\n\t\t\t}),\n\n\t\t/** Registration: 201 with Cache-Control: no-store */\n\t\tregistrationResponse: (result: Result<unknown>): Response => {\n\t\t\tif (!result.success) {\n\t\t\t\treturn new Response(\n\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\terror: \"invalid_client_metadata\",\n\t\t\t\t\t\terror_description: result.error.message,\n\t\t\t\t\t}),\n\t\t\t\t\t{\n\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\theaders: { \"Content-Type\": \"application/json\", ...corsHeaders },\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn new Response(JSON.stringify(result.data), {\n\t\t\t\tstatus: 201,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t\t\tPragma: \"no-cache\",\n\t\t\t\t\t...corsHeaders,\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\n\t\t/** Authorization: 302 redirect or error */\n\t\tauthorizeResponse: (result: Result<{ redirectUri: string }>): Response => {\n\t\t\tif (!result.success) {\n\t\t\t\t// If login is required, the caller should redirect to the login page\n\t\t\t\tif (result.error.code === \"LOGIN_REQUIRED\") {\n\t\t\t\t\tconst details = result.error.details as\n\t\t\t\t\t\t| { loginPage?: string; returnTo?: string }\n\t\t\t\t\t\t| undefined;\n\t\t\t\t\tif (details?.loginPage) {\n\t\t\t\t\t\tconst loginUrl = new URL(details.loginPage);\n\t\t\t\t\t\tif (details.returnTo) {\n\t\t\t\t\t\t\tloginUrl.searchParams.set(\"returnTo\", details.returnTo);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn Response.redirect(loginUrl.toString(), 302);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn new Response(\n\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\terror: result.error.code.toLowerCase(),\n\t\t\t\t\t\terror_description: result.error.message,\n\t\t\t\t\t}),\n\t\t\t\t\t{\n\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn Response.redirect(result.data.redirectUri, 302);\n\t\t},\n\n\t\t/** Token: 200 with Cache-Control: no-store or error */\n\t\ttokenResponse: (result: Result<unknown>): Response => {\n\t\t\tif (!result.success) {\n\t\t\t\tconst status = result.error.code === \"INVALID_CLIENT\" ? 401 : 400;\n\t\t\t\treturn new Response(\n\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\terror: result.error.code.toLowerCase(),\n\t\t\t\t\t\terror_description: result.error.message,\n\t\t\t\t\t}),\n\t\t\t\t\t{\n\t\t\t\t\t\tstatus,\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t\t\t\t\tPragma: \"no-cache\",\n\t\t\t\t\t\t\t...corsHeaders,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn new Response(JSON.stringify(result.data), {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t\t\tPragma: \"no-cache\",\n\t\t\t\t\t...corsHeaders,\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\n\t\t/** Auth failure in JSON-RPC format for MCP resource servers */\n\t\tunauthorizedResponse: (error: { code: string; message: string }): Response =>\n\t\t\tbuildUnauthorizedResponse(ctx, error),\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/mcp/types.ts","../../src/crypto/web-crypto.ts","../../src/mcp/utils.ts","../../src/mcp/authorize.ts","../../src/mcp/consent.ts","../../src/mcp/metadata.ts","../../src/mcp/registration.ts","../../src/mcp/step-up.ts","../../src/mcp/validate.ts","../../src/mcp/require-scopes.ts","../../src/standards/claims.ts","../../src/mcp/token.ts","../../src/mcp/server.ts"],"names":["parsed"],"mappings":"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","file":"index.js","sourcesContent":["import { z } from \"zod\";\n\n// ─── Result Type ────────────────────────────────────────────────────────────\n\nexport interface KavachError {\n\tcode: string;\n\tmessage: string;\n\tdetails?: Record<string, unknown>;\n}\n\nexport type Result<T> = { success: true; data: T } | { success: false; error: KavachError };\n\n// ─── MCP Module Configuration ───────────────────────────────────────────────\n\nexport interface McpConfig {\n\t/** Enable MCP authorization server */\n\tenabled: boolean;\n\t/** Enforce auth on all MCP requests */\n\tenforceAuth?: boolean;\n\t/** Custom scopes supported by this server */\n\tscopes?: string[];\n\t/** Issuer URL (typically your base URL) */\n\tissuer?: string;\n\t/** Base URL for MCP endpoints */\n\tbaseUrl?: string;\n\t/** Secret key for signing JWTs (must be >= 32 chars) */\n\tsigningSecret?: string;\n\t/** Access token TTL in seconds (default: 3600) */\n\taccessTokenTtl?: number;\n\t/** Refresh token TTL in seconds (default: 604800 = 7 days) */\n\trefreshTokenTtl?: number;\n\t/** Authorization code TTL in seconds (default: 600 = 10 minutes) */\n\tcodeTtl?: number;\n\t/** Allowed resource URIs for RFC 8707 */\n\tallowedResources?: string[];\n\t/** Login page URL - where users are redirected to authenticate */\n\tloginPage?: string;\n\t/** Consent page URL - where users approve scopes */\n\tconsentPage?: string;\n\t/**\n\t * Clients that are pre-registered at startup.\n\t *\n\t * These are stored via `storeClient` when the module is created,\n\t * so they behave identically to dynamically-registered clients.\n\t * Useful for first-party apps, CLIs, or test fixtures that should\n\t * always exist without a prior registration call.\n\t */\n\tpreRegisteredClients?: Array<{\n\t\tclientId: string;\n\t\tclientSecret?: string;\n\t\tredirectUris: string[];\n\t\tclientName?: string;\n\t\tscope?: string;\n\t}>;\n\t/** Custom token claims generator */\n\tgetAdditionalClaims?: (userId: string, scopes: string[]) => Promise<Record<string, unknown>>;\n\t/**\n\t * Emit IETF agentic JWT claims on issued access tokens.\n\t *\n\t * When true, any claims returned by `getAgenticContext` are embedded in\n\t * the token payload using the registered draft-goswami-agentic-jwt-00 claim\n\t * names. Claims with no available context value are omitted. Off by default.\n\t *\n\t * @default false\n\t */\n\temitAgenticJwtClaims?: boolean;\n\t/**\n\t * Resolve agentic context for a given user at token issuance time.\n\t *\n\t * Called only when `emitAgenticJwtClaims` is true. Return only the claims\n\t * you can populate; absent fields are skipped rather than fabricated.\n\t *\n\t * TODO(v3): wire this through kavach.ts so the trust module can provide\n\t * trust_tier automatically without requiring the caller to implement it.\n\t */\n\tgetAgenticContext?: (userId: string) => Promise<{\n\t\tagentId?: string;\n\t\tagentType?: \"autonomous\" | \"delegated\" | \"supervised\";\n\t\ttrustTier?: \"unverified\" | \"low\" | \"standard\" | \"elevated\" | \"high\";\n\t}>;\n}\n\n// ─── OAuth 2.0 Authorization Server Metadata (RFC 8414) ─────────────────────\n\nexport interface McpServerMetadata {\n\tissuer: string;\n\tauthorization_endpoint: string;\n\ttoken_endpoint: string;\n\tregistration_endpoint: string;\n\tjwks_uri?: string;\n\tscopes_supported: string[];\n\tresponse_types_supported: string[];\n\tresponse_modes_supported: string[];\n\tgrant_types_supported: string[];\n\ttoken_endpoint_auth_methods_supported: string[];\n\tcode_challenge_methods_supported: string[];\n\tservice_documentation?: string;\n\trevocation_endpoint?: string;\n}\n\n// ─── Protected Resource Metadata (RFC 9728) ─────────────────────────────────\n\nexport interface McpProtectedResourceMetadata {\n\tresource: string;\n\tauthorization_servers: string[];\n\tjwks_uri?: string;\n\tscopes_supported: string[];\n\tbearer_methods_supported: string[];\n\tresource_signing_alg_values_supported?: string[];\n}\n\n// ─── OAuth Client (RFC 7591 Dynamic Client Registration) ────────────────────\n\nexport interface McpClient {\n\tclientId: string;\n\tclientSecret: string | null;\n\tclientName: string | null;\n\tclientUri: string | null;\n\tlogoUri: string | null;\n\tredirectUris: string[];\n\tgrantTypes: string[];\n\tresponseTypes: string[];\n\ttokenEndpointAuthMethod: string;\n\tscope: string | null;\n\tcontacts: string[] | null;\n\ttosUri: string | null;\n\tpolicyUri: string | null;\n\tsoftwareId: string | null;\n\tsoftwareVersion: string | null;\n\tclientType: \"public\" | \"confidential\";\n\tdisabled: boolean;\n\tuserId: string | null;\n\tcreatedAt: Date;\n\tupdatedAt: Date;\n}\n\nexport interface McpClientRegistrationRequest {\n\tredirect_uris: string[];\n\ttoken_endpoint_auth_method?: string;\n\tgrant_types?: string[];\n\tresponse_types?: string[];\n\tclient_name?: string;\n\tclient_uri?: string;\n\tlogo_uri?: string;\n\tscope?: string;\n\tcontacts?: string[];\n\ttos_uri?: string;\n\tpolicy_uri?: string;\n\tsoftware_id?: string;\n\tsoftware_version?: string;\n}\n\nexport interface McpClientRegistrationResponse {\n\tclient_id: string;\n\tclient_secret?: string;\n\tclient_id_issued_at: number;\n\tclient_secret_expires_at?: number;\n\tredirect_uris: string[];\n\ttoken_endpoint_auth_method: string;\n\tgrant_types: string[];\n\tresponse_types: string[];\n\tclient_name?: string;\n\tclient_uri?: string;\n\tlogo_uri?: string;\n\tscope?: string;\n\tcontacts?: string[];\n\ttos_uri?: string;\n\tpolicy_uri?: string;\n\tsoftware_id?: string;\n\tsoftware_version?: string;\n}\n\n// ─── Authorization Code ─────────────────────────────────────────────────────\n\nexport interface McpAuthorizationCode {\n\tcode: string;\n\tclientId: string;\n\tuserId: string;\n\tredirectUri: string;\n\tscope: string[];\n\tcodeChallenge: string;\n\tcodeChallengeMethod: \"S256\";\n\tresource: string | null;\n\texpiresAt: Date;\n\tcreatedAt: Date;\n}\n\n// ─── Authorization Request ──────────────────────────────────────────────────\n\nexport interface McpAuthorizeRequest {\n\tresponse_type: string;\n\tclient_id: string;\n\tredirect_uri: string;\n\tscope?: string;\n\tstate?: string;\n\tcode_challenge: string;\n\tcode_challenge_method: string;\n\tresource?: string;\n}\n\nexport interface McpAuthorizeResult {\n\tredirectUri: string;\n\tcode: string;\n\tstate: string | null;\n}\n\n// ─── Access Token ───────────────────────────────────────────────────────────\n\nexport interface McpAccessToken {\n\taccessToken: string;\n\trefreshToken: string | null;\n\ttokenType: \"Bearer\";\n\texpiresIn: number;\n\tscope: string[];\n\tclientId: string;\n\tuserId: string;\n\tresource: string | null;\n\texpiresAt: Date;\n\tcreatedAt: Date;\n}\n\n// ─── Token Request / Response ───────────────────────────────────────────────\n\nexport interface McpTokenRequest {\n\tgrant_type: string;\n\tcode?: string;\n\tredirect_uri?: string;\n\tclient_id?: string;\n\tclient_secret?: string;\n\tcode_verifier?: string;\n\trefresh_token?: string;\n\tresource?: string;\n\tscope?: string;\n}\n\nexport interface McpTokenResponse {\n\taccess_token: string;\n\ttoken_type: \"Bearer\";\n\texpires_in: number;\n\trefresh_token?: string;\n\tscope: string;\n}\n\n// ─── Token Validation ───────────────────────────────────────────────────────\n\nexport interface McpTokenPayload {\n\tsub: string;\n\tiss: string;\n\taud: string | string[];\n\texp: number;\n\tiat: number;\n\tjti: string;\n\tscope: string;\n\tclient_id: string;\n}\n\nexport interface McpSession {\n\tuserId: string;\n\tclientId: string;\n\tscopes: string[];\n\tresource: string | null;\n\texpiresAt: Date;\n\ttokenId: string;\n}\n\n// ─── MCP Auth Context (passed to all handler functions) ─────────────────────\n\nexport interface McpAuthContext {\n\tconfig: Required<\n\t\tPick<McpConfig, \"issuer\" | \"baseUrl\" | \"accessTokenTtl\" | \"refreshTokenTtl\" | \"codeTtl\">\n\t> &\n\t\tMcpConfig;\n\t/** Store a client registration */\n\tstoreClient: (client: McpClient) => Promise<void>;\n\t/** Find a client by ID */\n\tfindClient: (clientId: string) => Promise<McpClient | null>;\n\t/** Store an authorization code */\n\tstoreAuthorizationCode: (code: McpAuthorizationCode) => Promise<void>;\n\t/** Find and consume an authorization code (must delete after finding) */\n\tconsumeAuthorizationCode: (code: string) => Promise<McpAuthorizationCode | null>;\n\t/** Store an access token record */\n\tstoreToken: (token: McpAccessToken) => Promise<void>;\n\t/** Find a token by refresh token value */\n\tfindTokenByRefreshToken: (refreshToken: string) => Promise<McpAccessToken | null>;\n\t/** Revoke a token (by access token value) */\n\trevokeToken: (accessToken: string) => Promise<void>;\n\t/** Resolve the authenticated user ID (e.g., from session cookie) */\n\tresolveUserId: (request: Request) => Promise<string | null>;\n}\n\n// ─── MCP Module (public API shape) ──────────────────────────────────────────\n\nexport interface ApproveConsentParams {\n\t/** Authenticated user who approved the consent */\n\tuserId: string;\n\tclientId: string;\n\t/** Space-separated scope string or array */\n\tscope: string | string[];\n\tstate?: string;\n\tredirectUri: string;\n\tcodeChallenge: string;\n\tcodeChallengeMethod: \"S256\";\n\tresource?: string;\n}\n\nexport interface McpAuthModule {\n\t/** Get OAuth 2.0 Authorization Server Metadata */\n\tgetMetadata: () => McpServerMetadata;\n\t/** Get Protected Resource Metadata (RFC 9728) */\n\tgetProtectedResourceMetadata: () => McpProtectedResourceMetadata;\n\t/** Register a new OAuth client (RFC 7591) */\n\tregisterClient: (\n\t\tbody: McpClientRegistrationRequest,\n\t) => Promise<Result<McpClientRegistrationResponse>>;\n\t/** Handle authorization request */\n\tauthorize: (request: Request) => Promise<Result<McpAuthorizeResult>>;\n\t/**\n\t * Issue an authorization code after a user has explicitly approved consent.\n\t *\n\t * When `config.consentPage` is set, `authorize` redirects to that page\n\t * instead of issuing a code directly. The consent page must call this\n\t * method after the user clicks \"Allow\".\n\t */\n\tapproveConsent: (params: ApproveConsentParams) => Promise<Result<{ redirectUri: string }>>;\n\t/** Handle token exchange */\n\ttoken: (request: Request) => Promise<Result<McpTokenResponse>>;\n\t/** Validate an access token */\n\tvalidateToken: (token: string, requiredScopes?: string[]) => Promise<Result<McpSession>>;\n\t/** Middleware that validates Bearer tokens and returns session */\n\tmiddleware: (request: Request) => Promise<Result<McpSession>>;\n\t/** Build a step-up challenge response (403) indicating required scopes */\n\tbuildStepUpResponse: (options: {\n\t\tcurrentScopes: string[];\n\t\trequiredScopes: string[];\n\t\tresource?: string;\n\t}) => Response;\n\t/** Validate token and check scopes. Returns session if valid, or a Response to send back */\n\trequireScopes: (\n\t\trequest: Request,\n\t\trequiredScopes: string[],\n\t) => Promise<\n\t\t{ authorized: true; session: McpSession } | { authorized: false; response: Response }\n\t>;\n}\n\n// ─── Zod Schemas ────────────────────────────────────────────────────────────\n\nexport const McpClientRegistrationSchema = z.object({\n\tredirect_uris: z.array(z.string().url()),\n\ttoken_endpoint_auth_method: z\n\t\t.enum([\"none\", \"client_secret_basic\", \"client_secret_post\"])\n\t\t.default(\"client_secret_basic\")\n\t\t.optional(),\n\tgrant_types: z\n\t\t.array(z.enum([\"authorization_code\", \"refresh_token\"]))\n\t\t.default([\"authorization_code\"])\n\t\t.optional(),\n\tresponse_types: z\n\t\t.array(z.enum([\"code\"]))\n\t\t.default([\"code\"])\n\t\t.optional(),\n\tclient_name: z.string().optional(),\n\tclient_uri: z.string().url().optional(),\n\tlogo_uri: z.string().url().optional(),\n\tscope: z.string().optional(),\n\tcontacts: z.array(z.string()).optional(),\n\ttos_uri: z.string().url().optional(),\n\tpolicy_uri: z.string().url().optional(),\n\tsoftware_id: z.string().optional(),\n\tsoftware_version: z.string().optional(),\n});\n\nexport const McpAuthorizeRequestSchema = z.object({\n\tresponse_type: z.literal(\"code\"),\n\tclient_id: z.string().min(1),\n\tredirect_uri: z.string().min(1),\n\tscope: z.string().optional(),\n\tstate: z.string().optional(),\n\tcode_challenge: z.string().min(43).max(128),\n\tcode_challenge_method: z.literal(\"S256\"),\n\tresource: z.string().url().optional(),\n});\n\nexport const McpTokenRequestSchema = z.discriminatedUnion(\"grant_type\", [\n\tz.object({\n\t\tgrant_type: z.literal(\"authorization_code\"),\n\t\tcode: z.string().min(1),\n\t\tredirect_uri: z.string().min(1),\n\t\tclient_id: z.string().min(1),\n\t\tclient_secret: z.string().optional(),\n\t\tcode_verifier: z.string().min(43).max(128),\n\t\tresource: z.string().url().optional(),\n\t}),\n\tz.object({\n\t\tgrant_type: z.literal(\"refresh_token\"),\n\t\trefresh_token: z.string().min(1),\n\t\tclient_id: z.string().min(1),\n\t\tclient_secret: z.string().optional(),\n\t\tscope: z.string().optional(),\n\t\tresource: z.string().url().optional(),\n\t}),\n]);\n\nexport type McpTokenRequestParsed = z.infer<typeof McpTokenRequestSchema>;\n","/**\n * Web Crypto API utilities for KavachOS.\n *\n * This module uses ONLY the Web Crypto API (globalThis.crypto) which is\n * available natively in Cloudflare Workers, Deno, Bun, and Node 20+.\n * No `node:crypto` imports are used, making the core package edge-compatible.\n */\n\n// ---------------------------------------------------------------------------\n// Encoding helpers\n// ---------------------------------------------------------------------------\n\nconst HEX_CHARS = \"0123456789abcdef\";\n\n/** Encode a Uint8Array as a lowercase hex string. */\nexport function toHex(bytes: Uint8Array): string {\n\tlet hex = \"\";\n\tfor (let i = 0; i < bytes.length; i++) {\n\t\tconst b = bytes[i] as number;\n\t\thex += HEX_CHARS[b >> 4] as string;\n\t\thex += HEX_CHARS[b & 0x0f] as string;\n\t}\n\treturn hex;\n}\n\n/** Decode a hex string into a Uint8Array. */\nexport function fromHex(hex: string): Uint8Array {\n\tif (hex.length % 2 !== 0) {\n\t\tthrow new Error(\"fromHex: hex string must have even length\");\n\t}\n\tconst bytes = new Uint8Array(hex.length / 2);\n\tfor (let i = 0; i < bytes.length; i++) {\n\t\tconst hi = parseInt(hex[i * 2] as string, 16);\n\t\tconst lo = parseInt(hex[i * 2 + 1] as string, 16);\n\t\tif (Number.isNaN(hi) || Number.isNaN(lo)) {\n\t\t\tthrow new Error(`fromHex: invalid hex character at position ${i * 2}`);\n\t\t}\n\t\tbytes[i] = (hi << 4) | lo;\n\t}\n\treturn bytes;\n}\n\n/** Encode a Uint8Array as a base64url string (no padding). */\nexport function toBase64Url(bytes: Uint8Array): string {\n\tlet binary = \"\";\n\tfor (let i = 0; i < bytes.length; i++) {\n\t\tbinary += String.fromCharCode(bytes[i] as number);\n\t}\n\treturn btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n/** Decode a base64url string into a Uint8Array. */\nexport function fromBase64Url(b64: string): Uint8Array {\n\t// Restore standard base64\n\tlet base64 = b64.replace(/-/g, \"+\").replace(/_/g, \"/\");\n\t// Add padding\n\twhile (base64.length % 4 !== 0) {\n\t\tbase64 += \"=\";\n\t}\n\tconst binary = atob(base64);\n\tconst bytes = new Uint8Array(binary.length);\n\tfor (let i = 0; i < binary.length; i++) {\n\t\tbytes[i] = binary.charCodeAt(i);\n\t}\n\treturn bytes;\n}\n\n// ---------------------------------------------------------------------------\n// Random generation\n// ---------------------------------------------------------------------------\n\n/** Generate a v4 UUID using the globally available crypto.randomUUID(). */\nexport function generateId(): string {\n\treturn globalThis.crypto.randomUUID();\n}\n\n/** Generate cryptographically secure random bytes as a Uint8Array. */\nexport function randomBytes(length: number): Uint8Array {\n\tconst bytes = new Uint8Array(length);\n\tglobalThis.crypto.getRandomValues(bytes);\n\treturn bytes;\n}\n\n/** Generate cryptographically secure random bytes as a hex string. */\nexport function randomBytesHex(length: number): string {\n\treturn toHex(randomBytes(length));\n}\n\n// ---------------------------------------------------------------------------\n// Text encoding helper (internal)\n// ---------------------------------------------------------------------------\n\nconst TEXT_ENCODER = new TextEncoder();\n\nfunction toBytes(data: string | Uint8Array): ArrayBuffer {\n\tif (typeof data === \"string\") {\n\t\tconst encoded = TEXT_ENCODER.encode(data);\n\t\treturn (encoded.buffer as ArrayBuffer).slice(\n\t\t\tencoded.byteOffset,\n\t\t\tencoded.byteOffset + encoded.byteLength,\n\t\t);\n\t}\n\treturn (data.buffer as ArrayBuffer).slice(data.byteOffset, data.byteOffset + data.byteLength);\n}\n\n// ---------------------------------------------------------------------------\n// Hashing\n// ---------------------------------------------------------------------------\n\n/** SHA-256 hash, returns hex string. */\nexport async function sha256(data: string | Uint8Array): Promise<string> {\n\tconst digest = await globalThis.crypto.subtle.digest(\"SHA-256\", toBytes(data));\n\treturn toHex(new Uint8Array(digest));\n}\n\n/** SHA-256 hash, returns Uint8Array. */\nexport async function sha256Raw(data: string | Uint8Array): Promise<Uint8Array> {\n\tconst digest = await globalThis.crypto.subtle.digest(\"SHA-256\", toBytes(data));\n\treturn new Uint8Array(digest);\n}\n\n/** SHA-1 hash, returns hex string. Needed for HIBP k-anonymity. */\nexport async function sha1(data: string | Uint8Array): Promise<string> {\n\tconst digest = await globalThis.crypto.subtle.digest(\"SHA-1\", toBytes(data));\n\treturn toHex(new Uint8Array(digest));\n}\n\n// ---------------------------------------------------------------------------\n// HMAC\n// ---------------------------------------------------------------------------\n\n/** Import a secret key for HMAC operations. */\nexport async function importHmacKey(\n\tkey: string | Uint8Array,\n\thash: \"SHA-256\" | \"SHA-1\" = \"SHA-256\",\n): Promise<CryptoKey> {\n\tconst keyData = typeof key === \"string\" ? TEXT_ENCODER.encode(key) : key;\n\treturn globalThis.crypto.subtle.importKey(\n\t\t\"raw\",\n\t\t(keyData.buffer as ArrayBuffer).slice(\n\t\t\tkeyData.byteOffset,\n\t\t\tkeyData.byteOffset + keyData.byteLength,\n\t\t),\n\t\t{ name: \"HMAC\", hash: { name: hash } },\n\t\tfalse,\n\t\t[\"sign\", \"verify\"],\n\t);\n}\n\n/** HMAC-SHA256 sign, returns hex string. */\nexport async function hmacSha256(\n\tkey: string | Uint8Array,\n\tdata: string | Uint8Array,\n): Promise<string> {\n\tconst cryptoKey = await importHmacKey(key, \"SHA-256\");\n\tconst signature = await globalThis.crypto.subtle.sign(\"HMAC\", cryptoKey, toBytes(data));\n\treturn toHex(new Uint8Array(signature));\n}\n\n/** HMAC-SHA256 sign, returns Uint8Array. */\nexport async function hmacSha256Raw(\n\tkey: string | Uint8Array,\n\tdata: string | Uint8Array,\n): Promise<Uint8Array> {\n\tconst cryptoKey = await importHmacKey(key, \"SHA-256\");\n\tconst signature = await globalThis.crypto.subtle.sign(\"HMAC\", cryptoKey, toBytes(data));\n\treturn new Uint8Array(signature);\n}\n\n/** HMAC-SHA1 sign, returns Uint8Array (needed for TOTP per RFC 6238). */\nexport async function hmacSha1Raw(key: Uint8Array, data: Uint8Array): Promise<Uint8Array> {\n\tconst cryptoKey = await importHmacKey(key, \"SHA-1\");\n\tconst buf = (data.buffer as ArrayBuffer).slice(\n\t\tdata.byteOffset,\n\t\tdata.byteOffset + data.byteLength,\n\t);\n\tconst signature = await globalThis.crypto.subtle.sign(\"HMAC\", cryptoKey, buf);\n\treturn new Uint8Array(signature);\n}\n\n// ---------------------------------------------------------------------------\n// PBKDF2 password hashing\n// ---------------------------------------------------------------------------\n\nconst PBKDF2_ITERATIONS = 100_000; // CF Workers caps at 100K; OWASP recommends 600K for Node.js\nconst PBKDF2_KEY_LENGTH = 64; // bytes\nconst PBKDF2_SALT_LENGTH = 32; // bytes\n\n/**\n * Hash a password using PBKDF2-SHA256.\n *\n * Returns a string in the format: `pbkdf2:iterations:salt_hex:hash_hex`\n * which is safe to store in the database.\n */\nexport async function pbkdf2Hash(\n\tpassword: string,\n\tsalt?: Uint8Array,\n\titerations?: number,\n): Promise<string> {\n\tconst actualSalt = salt ?? randomBytes(PBKDF2_SALT_LENGTH);\n\tconst actualIterations = iterations ?? PBKDF2_ITERATIONS;\n\n\tconst keyMaterial = await globalThis.crypto.subtle.importKey(\n\t\t\"raw\",\n\t\tTEXT_ENCODER.encode(password),\n\t\t\"PBKDF2\",\n\t\tfalse,\n\t\t[\"deriveBits\"],\n\t);\n\n\tconst saltBuf = (actualSalt.buffer as ArrayBuffer).slice(\n\t\tactualSalt.byteOffset,\n\t\tactualSalt.byteOffset + actualSalt.byteLength,\n\t);\n\tconst derived = await globalThis.crypto.subtle.deriveBits(\n\t\t{\n\t\t\tname: \"PBKDF2\",\n\t\t\tsalt: saltBuf,\n\t\t\titerations: actualIterations,\n\t\t\thash: \"SHA-256\",\n\t\t},\n\t\tkeyMaterial,\n\t\tPBKDF2_KEY_LENGTH * 8,\n\t);\n\n\treturn `pbkdf2:${actualIterations}:${toHex(actualSalt)}:${toHex(new Uint8Array(derived))}`;\n}\n\n/**\n * Verify a password against a stored PBKDF2 hash.\n *\n * Supports the `pbkdf2:iterations:salt:hash` format produced by `pbkdf2Hash`.\n */\nexport async function pbkdf2Verify(password: string, stored: string): Promise<boolean> {\n\tconst parts = stored.split(\":\");\n\tif (parts.length !== 4 || parts[0] !== \"pbkdf2\") {\n\t\treturn false;\n\t}\n\n\tconst iterations = parseInt(parts[1] as string, 10);\n\tconst salt = fromHex(parts[2] as string);\n\tconst storedHash = fromHex(parts[3] as string);\n\n\tif (Number.isNaN(iterations)) return false;\n\n\tconst keyMaterial = await globalThis.crypto.subtle.importKey(\n\t\t\"raw\",\n\t\tTEXT_ENCODER.encode(password),\n\t\t\"PBKDF2\",\n\t\tfalse,\n\t\t[\"deriveBits\"],\n\t);\n\n\tconst saltBuf = (salt.buffer as ArrayBuffer).slice(\n\t\tsalt.byteOffset,\n\t\tsalt.byteOffset + salt.byteLength,\n\t);\n\tconst derived = await globalThis.crypto.subtle.deriveBits(\n\t\t{\n\t\t\tname: \"PBKDF2\",\n\t\t\tsalt: saltBuf,\n\t\t\titerations,\n\t\t\thash: \"SHA-256\",\n\t\t},\n\t\tkeyMaterial,\n\t\tstoredHash.length * 8,\n\t);\n\n\treturn constantTimeEqual(new Uint8Array(derived), storedHash);\n}\n\n// ---------------------------------------------------------------------------\n// Constant-time comparison\n// ---------------------------------------------------------------------------\n\n/**\n * Constant-time comparison of two Uint8Arrays.\n * Returns false immediately if lengths differ (length is not secret).\n */\nexport function constantTimeEqual(a: Uint8Array, b: Uint8Array): boolean {\n\tif (a.byteLength !== b.byteLength) {\n\t\treturn false;\n\t}\n\tlet diff = 0;\n\tfor (let i = 0; i < a.byteLength; i++) {\n\t\tdiff |= (a[i] as number) ^ (b[i] as number);\n\t}\n\treturn diff === 0;\n}\n","import { generateId, randomBytes, toBase64Url } from \"../crypto/web-crypto.js\";\n\n/**\n * Generate a cryptographically secure random token string.\n *\n * Uses `crypto.getRandomValues()` (Web Crypto API compatible) to produce\n * a URL-safe base64 string of the requested byte length.\n */\nexport function generateSecureToken(byteLength: number): string {\n\tconst bytes = randomBytes(byteLength);\n\treturn toBase64Url(bytes);\n}\n\n/**\n * Generate a new authorization code.\n * Returns a UUID v4 string (compact, unique, unpredictable enough when\n * combined with PKCE code_verifier for security).\n */\nexport function generateAuthorizationCode(): string {\n\treturn generateId();\n}\n\n/**\n * Compute the S256 code challenge from a code verifier.\n *\n * S256: BASE64URL(SHA256(ASCII(code_verifier)))\n *\n * Uses Web Crypto (SubtleCrypto) for cross-runtime compatibility.\n */\nexport async function computeS256Challenge(codeVerifier: string): Promise<string> {\n\tconst encoder = new TextEncoder();\n\tconst data = encoder.encode(codeVerifier);\n\tconst digest = await globalThis.crypto.subtle.digest(\"SHA-256\", data);\n\treturn toBase64Url(new Uint8Array(digest));\n}\n\n/**\n * Verify a PKCE S256 code_verifier against a stored code_challenge.\n */\nexport async function verifyS256(codeVerifier: string, codeChallenge: string): Promise<boolean> {\n\tconst computed = await computeS256Challenge(codeVerifier);\n\treturn timingSafeEqual(computed, codeChallenge);\n}\n\n/**\n * Constant-time string comparison to prevent timing attacks.\n */\nfunction timingSafeEqual(a: string, b: string): boolean {\n\tif (a.length !== b.length) {\n\t\treturn false;\n\t}\n\tconst encoder = new TextEncoder();\n\tconst bufA = encoder.encode(a);\n\tconst bufB = encoder.encode(b);\n\n\tlet diff = 0;\n\tfor (let i = 0; i < bufA.length; i++) {\n\t\t// biome-ignore lint/style/noNonNullAssertion: length checked above\n\t\tdiff |= bufA[i]! ^ bufB[i]!;\n\t}\n\treturn diff === 0;\n}\n\n/**\n * Parse a URL search params or form body into a plain object.\n *\n * Handles both `application/x-www-form-urlencoded` and `application/json`\n * content types, as required by OAuth 2.1 token endpoint.\n */\nexport async function parseRequestBody(request: Request): Promise<Record<string, string>> {\n\tconst contentType = request.headers.get(\"content-type\") ?? \"\";\n\n\tif (contentType.includes(\"application/x-www-form-urlencoded\")) {\n\t\tconst text = await request.text();\n\t\tconst params = new URLSearchParams(text);\n\t\tconst result: Record<string, string> = {};\n\t\tfor (const [key, value] of params.entries()) {\n\t\t\tresult[key] = value;\n\t\t}\n\t\treturn result;\n\t}\n\n\tif (contentType.includes(\"application/json\")) {\n\t\tconst json = await request.json();\n\t\tif (typeof json === \"object\" && json !== null) {\n\t\t\tconst result: Record<string, string> = {};\n\t\t\tfor (const [key, value] of Object.entries(json as Record<string, unknown>)) {\n\t\t\t\tif (typeof value === \"string\") {\n\t\t\t\t\tresult[key] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\t}\n\n\treturn {};\n}\n\n/**\n * Extract client credentials from the Authorization header (Basic auth).\n *\n * Returns [client_id, client_secret] or null if not present.\n */\nexport function extractBasicAuth(request: Request): [string, string] | null {\n\tconst authorization = request.headers.get(\"authorization\");\n\tif (!authorization?.startsWith(\"Basic \")) {\n\t\treturn null;\n\t}\n\ttry {\n\t\tconst encoded = authorization.slice(6);\n\t\tconst decoded = atob(encoded);\n\t\tconst colonIndex = decoded.indexOf(\":\");\n\t\tif (colonIndex === -1) {\n\t\t\treturn null;\n\t\t}\n\t\tconst id = decoded.slice(0, colonIndex);\n\t\tconst secret = decoded.slice(colonIndex + 1);\n\t\tif (!id || !secret) {\n\t\t\treturn null;\n\t\t}\n\t\treturn [id, secret];\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Extract a Bearer token from the Authorization header.\n */\nexport function extractBearerToken(request: Request): string | null {\n\tconst authorization = request.headers.get(\"authorization\");\n\tif (!authorization?.startsWith(\"Bearer \")) {\n\t\treturn null;\n\t}\n\treturn authorization.slice(7);\n}\n","import type { McpAuthContext, McpAuthorizationCode, McpAuthorizeResult, Result } from \"./types.js\";\nimport { McpAuthorizeRequestSchema } from \"./types.js\";\nimport { generateAuthorizationCode } from \"./utils.js\";\n\n/**\n * Handle the OAuth 2.1 authorization endpoint.\n *\n * GET /mcp/authorize\n *\n * Validates the request parameters, checks the client, enforces PKCE S256,\n * validates Resource Indicators (RFC 8707), and issues an authorization code.\n *\n * The caller is responsible for authenticating the user before calling this\n * function. The `ctx.resolveUserId(request)` hook must return a non-null\n * user ID for the currently authenticated user.\n */\nexport async function handleAuthorize(\n\tctx: McpAuthContext,\n\trequest: Request,\n): Promise<Result<McpAuthorizeResult>> {\n\t// ── Parse query parameters ──────────────────────────────────────\n\tconst url = new URL(request.url);\n\tconst params: Record<string, string> = {};\n\tfor (const [key, value] of url.searchParams.entries()) {\n\t\tparams[key] = value;\n\t}\n\n\tconst parsed = McpAuthorizeRequestSchema.safeParse(params);\n\tif (!parsed.success) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_REQUEST\",\n\t\t\t\tmessage: \"Invalid authorization request parameters\",\n\t\t\t\tdetails: { issues: parsed.error.flatten().fieldErrors },\n\t\t\t},\n\t\t};\n\t}\n\n\tconst {\n\t\tclient_id: clientId,\n\t\tredirect_uri: redirectUri,\n\t\tscope: scopeParam,\n\t\tstate,\n\t\tcode_challenge: codeChallenge,\n\t\tcode_challenge_method: codeChallengeMethod,\n\t\tresource,\n\t} = parsed.data;\n\n\t// ── Validate client ─────────────────────────────────────────────\n\tconst client = await ctx.findClient(clientId);\n\tif (!client) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_CLIENT\",\n\t\t\t\tmessage: `Unknown client_id: ${clientId}`,\n\t\t\t},\n\t\t};\n\t}\n\n\tif (client.disabled) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_CLIENT\",\n\t\t\t\tmessage: \"Client is disabled\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Validate redirect_uri ───────────────────────────────────────\n\tif (!client.redirectUris.includes(redirectUri)) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_REDIRECT_URI\",\n\t\t\t\tmessage: \"redirect_uri does not match any registered redirect URI\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── PKCE validation: S256 only ──────────────────────────────────\n\tif (codeChallengeMethod !== \"S256\") {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_REQUEST\",\n\t\t\t\tmessage: \"Only S256 code_challenge_method is supported\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Validate resource parameter (RFC 8707) ──────────────────────\n\tif (resource !== undefined) {\n\t\tconst allowedResources = ctx.config.allowedResources;\n\t\tif (allowedResources && allowedResources.length > 0) {\n\t\t\tif (!allowedResources.includes(resource)) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: \"INVALID_TARGET\",\n\t\t\t\t\t\tmessage: `Resource '${resource}' is not a recognized MCP server`,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── Validate scopes ─────────────────────────────────────────────\n\tconst requestedScopes = scopeParam ? scopeParam.split(\" \").filter(Boolean) : [];\n\tconst supportedScopes = new Set(ctx.config.scopes ?? []);\n\tconst defaultScopes = new Set([\"openid\", \"profile\", \"email\", \"offline_access\"]);\n\tconst allSupported = new Set([...supportedScopes, ...defaultScopes]);\n\n\tfor (const scope of requestedScopes) {\n\t\tif (!allSupported.has(scope)) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"INVALID_SCOPE\",\n\t\t\t\t\tmessage: `Unsupported scope: ${scope}`,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t}\n\n\tconst effectiveScopes = requestedScopes.length > 0 ? requestedScopes : [\"openid\"];\n\n\t// ── Resolve authenticated user ──────────────────────────────────\n\tconst userId = await ctx.resolveUserId(request);\n\tif (!userId) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"LOGIN_REQUIRED\",\n\t\t\t\tmessage: \"User must be authenticated before authorization\",\n\t\t\t\tdetails: {\n\t\t\t\t\tloginPage: ctx.config.loginPage,\n\t\t\t\t\t// Pass all original query params so the login page can redirect back\n\t\t\t\t\treturnTo: request.url,\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Consent page redirect ───────────────────────────────────────\n\t// When a consent page is configured, redirect the user to it instead\n\t// of issuing an authorization code immediately. The consent page\n\t// collects explicit user approval and then calls approveConsent().\n\tif (ctx.config.consentPage) {\n\t\tconst consentUrl = new URL(ctx.config.consentPage);\n\t\tconsentUrl.searchParams.set(\"client_id\", clientId);\n\t\tconsentUrl.searchParams.set(\"redirect_uri\", redirectUri);\n\t\tconsentUrl.searchParams.set(\"scope\", effectiveScopes.join(\" \"));\n\t\tif (state) {\n\t\t\tconsentUrl.searchParams.set(\"state\", state);\n\t\t}\n\t\tconsentUrl.searchParams.set(\"code_challenge\", codeChallenge);\n\t\tconsentUrl.searchParams.set(\"code_challenge_method\", codeChallengeMethod);\n\t\tif (resource) {\n\t\t\tconsentUrl.searchParams.set(\"resource\", resource);\n\t\t}\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: {\n\t\t\t\tredirectUri: consentUrl.toString(),\n\t\t\t\tcode: \"\",\n\t\t\t\tstate: state ?? null,\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Generate authorization code ─────────────────────────────────\n\tconst code = generateAuthorizationCode();\n\tconst now = new Date();\n\tconst expiresAt = new Date(now.getTime() + ctx.config.codeTtl * 1000);\n\n\tconst authCode: McpAuthorizationCode = {\n\t\tcode,\n\t\tclientId,\n\t\tuserId,\n\t\tredirectUri,\n\t\tscope: effectiveScopes,\n\t\tcodeChallenge,\n\t\tcodeChallengeMethod: \"S256\",\n\t\tresource: resource ?? null,\n\t\texpiresAt,\n\t\tcreatedAt: now,\n\t};\n\n\tawait ctx.storeAuthorizationCode(authCode);\n\n\t// ── Build redirect ──────────────────────────────────────────────\n\tconst redirectUrl = new URL(redirectUri);\n\tredirectUrl.searchParams.set(\"code\", code);\n\tif (state) {\n\t\tredirectUrl.searchParams.set(\"state\", state);\n\t}\n\n\treturn {\n\t\tsuccess: true,\n\t\tdata: {\n\t\t\tredirectUri: redirectUrl.toString(),\n\t\t\tcode,\n\t\t\tstate: state ?? null,\n\t\t},\n\t};\n}\n","import type {\n\tApproveConsentParams,\n\tMcpAuthContext,\n\tMcpAuthorizationCode,\n\tResult,\n} from \"./types.js\";\nimport { generateAuthorizationCode } from \"./utils.js\";\n\nexport type { ApproveConsentParams };\n\n/**\n * Issue an authorization code after a user has explicitly approved consent.\n *\n * Call this from your consent page handler after the user clicks \"Allow\".\n * The params should match what was passed to the consent page as query params\n * by `handleAuthorize`.\n */\nexport async function approveConsent(\n\tctx: McpAuthContext,\n\tparams: ApproveConsentParams,\n): Promise<Result<{ redirectUri: string }>> {\n\tconst {\n\t\tuserId,\n\t\tclientId,\n\t\tscope,\n\t\tstate,\n\t\tredirectUri,\n\t\tcodeChallenge,\n\t\tcodeChallengeMethod,\n\t\tresource,\n\t} = params;\n\n\t// ── Validate client still exists and is enabled ─────────────────\n\tconst client = await ctx.findClient(clientId);\n\tif (!client) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_CLIENT\",\n\t\t\t\tmessage: `Unknown client_id: ${clientId}`,\n\t\t\t},\n\t\t};\n\t}\n\n\tif (client.disabled) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_CLIENT\",\n\t\t\t\tmessage: \"Client is disabled\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Validate redirect_uri ────────────────────────────────────────\n\tif (!client.redirectUris.includes(redirectUri)) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_REDIRECT_URI\",\n\t\t\t\tmessage: \"redirect_uri does not match any registered redirect URI\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Normalise scopes ─────────────────────────────────────────────\n\tconst effectiveScopes =\n\t\ttypeof scope === \"string\" ? scope.split(\" \").filter(Boolean) : scope.filter(Boolean);\n\n\tif (effectiveScopes.length === 0) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_SCOPE\",\n\t\t\t\tmessage: \"At least one scope is required\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Generate and store authorization code ────────────────────────\n\tconst code = generateAuthorizationCode();\n\tconst now = new Date();\n\tconst expiresAt = new Date(now.getTime() + ctx.config.codeTtl * 1000);\n\n\tconst authCode: McpAuthorizationCode = {\n\t\tcode,\n\t\tclientId,\n\t\tuserId,\n\t\tredirectUri,\n\t\tscope: effectiveScopes,\n\t\tcodeChallenge,\n\t\tcodeChallengeMethod,\n\t\tresource: resource ?? null,\n\t\texpiresAt,\n\t\tcreatedAt: now,\n\t};\n\n\tawait ctx.storeAuthorizationCode(authCode);\n\n\t// ── Build redirect back to client ────────────────────────────────\n\tconst redirectUrl = new URL(redirectUri);\n\tredirectUrl.searchParams.set(\"code\", code);\n\tif (state) {\n\t\tredirectUrl.searchParams.set(\"state\", state);\n\t}\n\n\treturn {\n\t\tsuccess: true,\n\t\tdata: {\n\t\t\tredirectUri: redirectUrl.toString(),\n\t\t},\n\t};\n}\n","import type { McpAuthContext, McpProtectedResourceMetadata, McpServerMetadata } from \"./types.js\";\n\n/**\n * Build OAuth 2.0 Authorization Server Metadata (RFC 8414).\n *\n * Returned at: GET /.well-known/oauth-authorization-server\n */\nexport function getAuthorizationServerMetadata(ctx: McpAuthContext): McpServerMetadata {\n\tconst { issuer, baseUrl, scopes } = ctx.config;\n\tconst defaultScopes = [\"openid\", \"profile\", \"email\", \"offline_access\"];\n\tconst allScopes = [...new Set([...defaultScopes, ...(scopes ?? [])])];\n\n\treturn {\n\t\tissuer,\n\t\tauthorization_endpoint: `${baseUrl}/mcp/authorize`,\n\t\ttoken_endpoint: `${baseUrl}/mcp/token`,\n\t\tregistration_endpoint: `${baseUrl}/mcp/register`,\n\t\tjwks_uri: `${baseUrl}/mcp/jwks`,\n\t\tscopes_supported: allScopes,\n\t\tresponse_types_supported: [\"code\"],\n\t\tresponse_modes_supported: [\"query\"],\n\t\tgrant_types_supported: [\"authorization_code\", \"refresh_token\"],\n\t\ttoken_endpoint_auth_methods_supported: [\"client_secret_basic\", \"client_secret_post\", \"none\"],\n\t\tcode_challenge_methods_supported: [\"S256\"],\n\t\trevocation_endpoint: `${baseUrl}/mcp/revoke`,\n\t};\n}\n\n/**\n * Build Protected Resource Metadata (RFC 9728).\n *\n * Returned at: GET /.well-known/oauth-protected-resource\n *\n * An MCP resource server (tool server) publishes this so clients can\n * discover which authorization server to use.\n */\nexport function getProtectedResourceMetadata(ctx: McpAuthContext): McpProtectedResourceMetadata {\n\tconst { issuer, baseUrl, scopes } = ctx.config;\n\tconst defaultScopes = [\"openid\", \"profile\", \"email\", \"offline_access\"];\n\tconst allScopes = [...new Set([...defaultScopes, ...(scopes ?? [])])];\n\n\treturn {\n\t\tresource: issuer,\n\t\tauthorization_servers: [issuer],\n\t\tjwks_uri: `${baseUrl}/mcp/jwks`,\n\t\tscopes_supported: allScopes,\n\t\tbearer_methods_supported: [\"header\"],\n\t\tresource_signing_alg_values_supported: [\"HS256\"],\n\t};\n}\n","import { generateId } from \"../crypto/web-crypto.js\";\nimport type { McpAuthContext, McpClient, McpClientRegistrationResponse, Result } from \"./types.js\";\nimport { McpClientRegistrationSchema } from \"./types.js\";\nimport { generateSecureToken } from \"./utils.js\";\n\n/**\n * Validate whether a client_id that is an HTTPS URL points to a valid\n * Client ID Metadata Document. Per the MCP spec, when a client_id is\n * an HTTPS URL the authorization server SHOULD fetch the document and\n * verify that the redirect_uris in the registration request match those\n * in the metadata document.\n *\n * Returns the resolved redirect URIs from the metadata document, or null\n * if the client_id is not a URL.\n */\nasync function resolveClientIdMetadataDocument(clientId: string): Promise<string[] | null> {\n\ttry {\n\t\tconst url = new URL(clientId);\n\t\tif (url.protocol !== \"https:\") {\n\t\t\treturn null;\n\t\t}\n\t\tconst response = await fetch(clientId, {\n\t\t\theaders: { Accept: \"application/json\" },\n\t\t\tsignal: AbortSignal.timeout(5_000),\n\t\t});\n\t\tif (!response.ok) {\n\t\t\treturn null;\n\t\t}\n\t\tconst metadata = (await response.json()) as {\n\t\t\tredirect_uris?: string[];\n\t\t\tclient_name?: string;\n\t\t\tclient_uri?: string;\n\t\t};\n\t\tif (Array.isArray(metadata.redirect_uris)) {\n\t\t\treturn metadata.redirect_uris;\n\t\t}\n\t\treturn null;\n\t} catch {\n\t\t// Not a URL or fetch failed -- treat as opaque client_id\n\t\treturn null;\n\t}\n}\n\n/**\n * Dynamic Client Registration (RFC 7591).\n *\n * Endpoint logic for: POST /mcp/register\n *\n * Validates the registration request, generates client credentials,\n * persists the client via the context store, and returns the\n * RFC 7591-compliant registration response.\n */\nexport async function registerClient(\n\tctx: McpAuthContext,\n\tbody: unknown,\n): Promise<Result<McpClientRegistrationResponse>> {\n\t// ── Validate input ──────────────────────────────────────────────────\n\tconst parsed = McpClientRegistrationSchema.safeParse(body);\n\tif (!parsed.success) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_CLIENT_METADATA\",\n\t\t\t\tmessage: \"Invalid client registration request\",\n\t\t\t\tdetails: { issues: parsed.error.flatten().fieldErrors },\n\t\t\t},\n\t\t};\n\t}\n\n\tconst data = parsed.data;\n\tconst redirectUris = data.redirect_uris;\n\tconst grantTypes = data.grant_types ?? [\"authorization_code\"];\n\tconst responseTypes = data.response_types ?? [\"code\"];\n\tconst authMethod = data.token_endpoint_auth_method ?? \"client_secret_basic\";\n\n\t// ── Validate redirect_uris are required for authorization_code ────\n\tif (grantTypes.includes(\"authorization_code\") && redirectUris.length === 0) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_REDIRECT_URI\",\n\t\t\t\tmessage: \"redirect_uris are required when grant_types includes authorization_code\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Validate grant_type / response_type consistency ──────────────\n\tif (grantTypes.includes(\"authorization_code\") && !responseTypes.includes(\"code\")) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_CLIENT_METADATA\",\n\t\t\t\tmessage:\n\t\t\t\t\t\"response_types must include 'code' when grant_types includes 'authorization_code'\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Validate redirect URIs ──────────────────────────────────────\n\tfor (const uri of redirectUris) {\n\t\ttry {\n\t\t\tconst parsed = new URL(uri);\n\t\t\t// Localhost is allowed for development; production requires HTTPS\n\t\t\tif (\n\t\t\t\tparsed.protocol !== \"https:\" &&\n\t\t\t\tparsed.hostname !== \"localhost\" &&\n\t\t\t\tparsed.hostname !== \"127.0.0.1\" &&\n\t\t\t\tparsed.hostname !== \"[::1]\"\n\t\t\t) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: \"INVALID_REDIRECT_URI\",\n\t\t\t\t\t\tmessage: `redirect_uri must use HTTPS (or localhost for development): ${uri}`,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\t// Fragment not allowed per OAuth 2.1\n\t\t\tif (parsed.hash) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: \"INVALID_REDIRECT_URI\",\n\t\t\t\t\t\tmessage: `redirect_uri must not contain a fragment: ${uri}`,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t} catch {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"INVALID_REDIRECT_URI\",\n\t\t\t\t\tmessage: `redirect_uri is not a valid URL: ${uri}`,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t}\n\n\t// ── Generate credentials ────────────────────────────────────────\n\tconst clientId = generateId();\n\tconst isPublic = authMethod === \"none\";\n\tconst clientSecret = isPublic ? null : generateSecureToken(48);\n\n\t// ── Client ID Metadata Document support ─────────────────────────\n\t// If the caller provides a client_uri that is an HTTPS URL, we\n\t// attempt to fetch the metadata document. If it exists and contains\n\t// redirect_uris, we verify they match the request.\n\tif (data.client_uri) {\n\t\tconst metadataUris = await resolveClientIdMetadataDocument(data.client_uri);\n\t\tif (metadataUris !== null) {\n\t\t\tconst metadataSet = new Set(metadataUris);\n\t\t\tconst mismatched = redirectUris.filter((u) => !metadataSet.has(u));\n\t\t\tif (mismatched.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: \"INVALID_REDIRECT_URI\",\n\t\t\t\t\t\tmessage: \"redirect_uris do not match those in the Client ID Metadata Document\",\n\t\t\t\t\t\tdetails: { mismatched },\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\t// ── Persist ─────────────────────────────────────────────────────\n\tconst now = new Date();\n\tconst client: McpClient = {\n\t\tclientId,\n\t\tclientSecret,\n\t\tclientName: data.client_name ?? null,\n\t\tclientUri: data.client_uri ?? null,\n\t\tlogoUri: data.logo_uri ?? null,\n\t\tredirectUris,\n\t\tgrantTypes,\n\t\tresponseTypes,\n\t\ttokenEndpointAuthMethod: authMethod,\n\t\tscope: data.scope ?? null,\n\t\tcontacts: data.contacts ?? null,\n\t\ttosUri: data.tos_uri ?? null,\n\t\tpolicyUri: data.policy_uri ?? null,\n\t\tsoftwareId: data.software_id ?? null,\n\t\tsoftwareVersion: data.software_version ?? null,\n\t\tclientType: isPublic ? \"public\" : \"confidential\",\n\t\tdisabled: false,\n\t\tuserId: null,\n\t\tcreatedAt: now,\n\t\tupdatedAt: now,\n\t};\n\n\tawait ctx.storeClient(client);\n\n\t// ── Build response ──────────────────────────────────────────────\n\tconst response: McpClientRegistrationResponse = {\n\t\tclient_id: clientId,\n\t\tclient_id_issued_at: Math.floor(now.getTime() / 1000),\n\t\tredirect_uris: redirectUris,\n\t\ttoken_endpoint_auth_method: authMethod,\n\t\tgrant_types: grantTypes,\n\t\tresponse_types: responseTypes,\n\t\t...(data.client_name ? { client_name: data.client_name } : {}),\n\t\t...(data.client_uri ? { client_uri: data.client_uri } : {}),\n\t\t...(data.logo_uri ? { logo_uri: data.logo_uri } : {}),\n\t\t...(data.scope ? { scope: data.scope } : {}),\n\t\t...(data.contacts ? { contacts: data.contacts } : {}),\n\t\t...(data.tos_uri ? { tos_uri: data.tos_uri } : {}),\n\t\t...(data.policy_uri ? { policy_uri: data.policy_uri } : {}),\n\t\t...(data.software_id ? { software_id: data.software_id } : {}),\n\t\t...(data.software_version ? { software_version: data.software_version } : {}),\n\t\t...(clientSecret !== null ? { client_secret: clientSecret, client_secret_expires_at: 0 } : {}),\n\t};\n\n\treturn { success: true, data: response };\n}\n","import type { McpAuthContext } from \"./types.js\";\n\n// ─── CORS headers (same as other MCP endpoints) ──────────────────────────────\n\nconst CORS_HEADERS = {\n\t\"Access-Control-Allow-Origin\": \"*\",\n\t\"Access-Control-Allow-Methods\": \"GET, POST, OPTIONS\",\n\t\"Access-Control-Allow-Headers\": \"Content-Type, Authorization\",\n\t\"Access-Control-Max-Age\": \"86400\",\n} as const;\n\n/**\n * Build a step-up challenge response (403) indicating required scopes.\n *\n * When a token has valid scopes but lacks a specific scope needed for an\n * operation, return this response so the client knows it must re-authorize\n * with the additional scopes.\n *\n * Per RFC 6750 §3.1 the WWW-Authenticate header uses the\n * `error=\"insufficient_scope\"` challenge to signal the exact upgrade path.\n */\nexport function buildStepUpResponse(\n\tctx: McpAuthContext,\n\toptions: {\n\t\tcurrentScopes: string[];\n\t\trequiredScopes: string[];\n\t\tresource?: string;\n\t},\n): Response {\n\tconst { currentScopes, requiredScopes, resource } = options;\n\n\t// Build upgrade URL pointing at the authorization endpoint\n\tconst authorizationEndpoint = `${ctx.config.baseUrl}/authorize`;\n\tconst upgradeUrl = new URL(authorizationEndpoint);\n\tupgradeUrl.searchParams.set(\"scope\", requiredScopes.join(\" \"));\n\tif (resource) {\n\t\tupgradeUrl.searchParams.set(\"resource\", resource);\n\t}\n\n\t// WWW-Authenticate per RFC 6750 §3 + insufficient_scope challenge\n\tconst scopeList = requiredScopes.join(\" \");\n\tconst wwwAuthenticate = `Bearer error=\"insufficient_scope\", scope=\"${scopeList}\"`;\n\n\tconst body = {\n\t\terror: \"insufficient_scope\",\n\t\terror_description: \"Token lacks required scopes\",\n\t\trequired_scopes: requiredScopes,\n\t\tcurrent_scopes: currentScopes,\n\t\tupgrade_url: upgradeUrl.toString(),\n\t};\n\n\treturn new Response(JSON.stringify(body), {\n\t\tstatus: 403,\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\"WWW-Authenticate\": wwwAuthenticate,\n\t\t\t\"Access-Control-Expose-Headers\": \"WWW-Authenticate\",\n\t\t\t...CORS_HEADERS,\n\t\t},\n\t});\n}\n","import { jwtVerify } from \"jose\";\nimport type { McpAuthContext, McpSession, McpTokenPayload, Result } from \"./types.js\";\nimport { extractBearerToken } from \"./utils.js\";\n\n/**\n * Derive the HMAC verification key from the config's signing secret.\n */\nasync function getVerificationKey(secret: string): Promise<CryptoKey> {\n\tconst encoder = new TextEncoder();\n\treturn globalThis.crypto.subtle.importKey(\n\t\t\"raw\",\n\t\tencoder.encode(secret),\n\t\t{ name: \"HMAC\", hash: \"SHA-256\" },\n\t\tfalse,\n\t\t[\"verify\"],\n\t);\n}\n\n/**\n * Validate an MCP access token (JWT).\n *\n * Performs:\n * 1. JWT signature verification (HS256)\n * 2. Expiry check\n * 3. Issuer validation\n * 4. Audience validation (token must be bound to the expected resource)\n * 5. Scope validation (optional - checks all required scopes are present)\n *\n * Target: < 5ms with cached keys (per CLAUDE.md performance rule).\n */\nexport async function validateAccessToken(\n\tctx: McpAuthContext,\n\ttoken: string,\n\toptions?: {\n\t\trequiredScopes?: string[];\n\t\texpectedAudience?: string;\n\t},\n): Promise<Result<McpSession>> {\n\tconst secret = ctx.config.signingSecret;\n\tif (!secret) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"SERVER_ERROR\",\n\t\t\t\tmessage: \"MCP signingSecret is not configured\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Verify JWT ──────────────────────────────────────────────────\n\tlet payload: McpTokenPayload;\n\ttry {\n\t\tconst key = await getVerificationKey(secret);\n\t\tconst result = await jwtVerify(token, key, {\n\t\t\tissuer: ctx.config.issuer,\n\t\t\talgorithms: [\"HS256\"],\n\t\t\t...(options?.expectedAudience ? { audience: options.expectedAudience } : {}),\n\t\t});\n\t\tpayload = result.payload as unknown as McpTokenPayload;\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : \"Token verification failed\";\n\n\t\t// Map jose errors to meaningful error codes\n\t\tlet code = \"INVALID_TOKEN\";\n\t\tif (message.includes(\"expired\")) {\n\t\t\tcode = \"TOKEN_EXPIRED\";\n\t\t} else if (message.includes(\"audience\")) {\n\t\t\tcode = \"INVALID_AUDIENCE\";\n\t\t} else if (message.includes(\"issuer\")) {\n\t\t\tcode = \"INVALID_ISSUER\";\n\t\t}\n\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code, message },\n\t\t};\n\t}\n\n\t// ── Validate required fields exist ──────────────────────────────\n\tif (!payload.sub || !payload.client_id || !payload.jti) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_TOKEN\",\n\t\t\t\tmessage: \"Token is missing required claims (sub, client_id, jti)\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Audience validation (mandatory per MCP spec) ────────────────\n\t// If no explicit audience was provided to check, we still verify\n\t// the token has an audience claim.\n\tconst audience = payload.aud;\n\tif (!audience) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_AUDIENCE\",\n\t\t\t\tmessage: \"Token has no audience claim. Tokens must be bound to a resource.\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── Scope validation ────────────────────────────────────────────\n\tconst tokenScopes = payload.scope ? payload.scope.split(\" \") : [];\n\tconst requiredScopes = options?.requiredScopes ?? [];\n\n\tfor (const required of requiredScopes) {\n\t\tif (!tokenScopes.includes(required)) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"INSUFFICIENT_SCOPE\",\n\t\t\t\t\tmessage: `Token is missing required scope: ${required}`,\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\trequired: requiredScopes,\n\t\t\t\t\t\tpresent: tokenScopes,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t}\n\n\t// ── Determine resource from audience ────────────────────────────\n\tconst resource = Array.isArray(audience) ? (audience[0] ?? null) : audience;\n\n\t// ── Build session ───────────────────────────────────────────────\n\tconst session: McpSession = {\n\t\tuserId: payload.sub,\n\t\tclientId: payload.client_id,\n\t\tscopes: tokenScopes,\n\t\tresource,\n\t\texpiresAt: new Date(payload.exp * 1000),\n\t\ttokenId: payload.jti,\n\t};\n\n\treturn { success: true, data: session };\n}\n\n/**\n * MCP auth middleware.\n *\n * Extracts the Bearer token from the Authorization header, validates it,\n * and returns the session. This is the primary entry point for protecting\n * MCP resource server endpoints.\n *\n * Pattern inspired by better-auth's `withMcpAuth()`, adapted to KavachOS's\n * functional Result-based API.\n *\n * Usage:\n * ```typescript\n * const result = await withMcpAuth(ctx, request, { requiredScopes: ['read'] });\n * if (!result.success) {\n * return new Response(JSON.stringify(result.error), { status: 401 });\n * }\n * const session = result.data;\n * ```\n */\nexport async function withMcpAuth(\n\tctx: McpAuthContext,\n\trequest: Request,\n\toptions?: {\n\t\trequiredScopes?: string[];\n\t\texpectedAudience?: string;\n\t},\n): Promise<Result<McpSession>> {\n\tconst token = extractBearerToken(request);\n\n\tif (!token) {\n\t\tconst resourceMetadataUrl = `${ctx.config.baseUrl}/.well-known/oauth-protected-resource`;\n\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"UNAUTHORIZED\",\n\t\t\t\tmessage: \"Bearer token required\",\n\t\t\t\tdetails: {\n\t\t\t\t\t\"www-authenticate\": `Bearer resource_metadata=\"${resourceMetadataUrl}\"`,\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\n\treturn validateAccessToken(ctx, token, options);\n}\n\n/**\n * Build a 401 Unauthorized response in the JSON-RPC format expected\n * by MCP clients.\n *\n * Includes the WWW-Authenticate header pointing to the protected\n * resource metadata document, as required by the MCP spec.\n */\nexport function buildUnauthorizedResponse(\n\tctx: McpAuthContext,\n\terror: { code: string; message: string },\n): Response {\n\tconst resourceMetadataUrl = `${ctx.config.baseUrl}/.well-known/oauth-protected-resource`;\n\n\tconst wwwAuthenticate = `Bearer resource_metadata=\"${resourceMetadataUrl}\"`;\n\n\treturn new Response(\n\t\tJSON.stringify({\n\t\t\tjsonrpc: \"2.0\",\n\t\t\terror: {\n\t\t\t\tcode: -32000,\n\t\t\t\tmessage: error.message,\n\t\t\t\t\"www-authenticate\": wwwAuthenticate,\n\t\t\t},\n\t\t\tid: null,\n\t\t}),\n\t\t{\n\t\t\tstatus: 401,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\"WWW-Authenticate\": wwwAuthenticate,\n\t\t\t\t\"Access-Control-Expose-Headers\": \"WWW-Authenticate\",\n\t\t\t},\n\t\t},\n\t);\n}\n","import { buildStepUpResponse } from \"./step-up.js\";\nimport type { McpAuthContext, McpSession } from \"./types.js\";\nimport { extractBearerToken } from \"./utils.js\";\nimport { buildUnauthorizedResponse, validateAccessToken } from \"./validate.js\";\n\n// ─── Scope challenge helper ───────────────────────────────────────────────────\n\n/**\n * Validate the Bearer token on a request and assert that it carries all of\n * the `requiredScopes`.\n *\n * Encapsulates the three-branch decision MCP resource servers need to make:\n *\n * 1. No token (or malformed token) → 401 Unauthorized\n * 2. Valid token, missing scopes → 403 with step-up challenge\n * 3. Valid token, all scopes present → session returned to the caller\n *\n * Usage:\n * ```typescript\n * const check = await requireScopes(ctx, request, ['mcp:write']);\n * if (!check.authorized) return check.response;\n * // check.session is available here\n * ```\n */\nexport async function requireScopes(\n\tctx: McpAuthContext,\n\trequest: Request,\n\trequiredScopes: string[],\n): Promise<{ authorized: true; session: McpSession } | { authorized: false; response: Response }> {\n\t// ── Step 1: Extract Bearer token ────────────────────────────────\n\tconst token = extractBearerToken(request);\n\n\tif (!token) {\n\t\treturn {\n\t\t\tauthorized: false,\n\t\t\tresponse: buildUnauthorizedResponse(ctx, {\n\t\t\t\tcode: \"UNAUTHORIZED\",\n\t\t\t\tmessage: \"Bearer token required\",\n\t\t\t}),\n\t\t};\n\t}\n\n\t// ── Step 2: Validate the token (without scope enforcement yet) ──\n\t// We validate first without requiredScopes so we can distinguish\n\t// \"bad token\" (401) from \"valid token but wrong scopes\" (403).\n\tconst tokenResult = await validateAccessToken(ctx, token);\n\n\tif (!tokenResult.success) {\n\t\treturn {\n\t\t\tauthorized: false,\n\t\t\tresponse: buildUnauthorizedResponse(ctx, {\n\t\t\t\tcode: tokenResult.error.code,\n\t\t\t\tmessage: tokenResult.error.message,\n\t\t\t}),\n\t\t};\n\t}\n\n\tconst session = tokenResult.data;\n\n\t// ── Step 3: Check required scopes ───────────────────────────────\n\tif (requiredScopes.length > 0) {\n\t\tconst missingScopes = requiredScopes.filter((s) => !session.scopes.includes(s));\n\n\t\tif (missingScopes.length > 0) {\n\t\t\treturn {\n\t\t\t\tauthorized: false,\n\t\t\t\tresponse: buildStepUpResponse(ctx, {\n\t\t\t\t\tcurrentScopes: session.scopes,\n\t\t\t\t\trequiredScopes,\n\t\t\t\t\tresource: session.resource ?? undefined,\n\t\t\t\t}),\n\t\t\t};\n\t\t}\n\t}\n\n\t// ── Step 4: All checks passed ────────────────────────────────────\n\treturn { authorized: true, session };\n}\n","/**\n * IETF agentic JWT claim name constants.\n *\n * Sources:\n * - draft-goswami-agentic-jwt-00\n * - draft-liu-agent-operation-authorization-01\n *\n * These constants are off by default. Set `emitAgenticJwtClaims: true` in\n * KavachConfig to include them in issued tokens.\n */\n\n// ---------------------------------------------------------------------------\n// Named types\n// ---------------------------------------------------------------------------\n\n/**\n * Operational mode of an agent within a delegation chain.\n *\n * - `autonomous` — no human-in-the-loop; the agent acts on its own behalf.\n * - `delegated` — the agent is acting under explicit delegation from another principal.\n * - `supervised` — the agent acts autonomously but requires human approval for sensitive ops.\n */\nexport type AgentType = \"autonomous\" | \"delegated\" | \"supervised\";\n\n/**\n * Trust tier band assigned at token issuance, derived from the numeric trust\n * score. Matches the five-level model in KavachOS trust scoring.\n *\n * Mapping (inclusive lower bound):\n * score 0–19 → \"unverified\"\n * score 20–39 → \"low\"\n * score 40–59 → \"standard\"\n * score 60–79 → \"elevated\"\n * score 80+ → \"high\"\n */\nexport type TrustTier = \"unverified\" | \"low\" | \"standard\" | \"elevated\" | \"high\";\n\n// ---------------------------------------------------------------------------\n// Claim name constants\n// ---------------------------------------------------------------------------\n\n/**\n * Registered claim names for agentic JWTs.\n *\n * All names are string literals so they can be used directly as JWT payload\n * keys. Consuming code should index into issued token payloads using these\n * constants rather than raw string literals.\n */\nexport const AGENTIC_JWT_CLAIMS = {\n\t/**\n\t * Stable identifier of the agent making the call.\n\t *\n\t * @see draft-goswami-agentic-jwt-00 §3.1\n\t */\n\tAGENT_ID: \"agent_id\",\n\n\t/**\n\t * Operational mode of the agent: `autonomous`, `delegated`, or `supervised`.\n\t *\n\t * @see draft-goswami-agentic-jwt-00 §3.2\n\t */\n\tAGENT_TYPE: \"agent_type\",\n\n\t/**\n\t * Subject principal the agent is acting on behalf of (human user or upstream agent).\n\t *\n\t * @see draft-goswami-agentic-jwt-00 §3.3\n\t */\n\tON_BEHALF_OF: \"on_behalf_of\",\n\n\t/**\n\t * Actor claim per RFC 8693. Identifies the current actor in an\n\t * impersonation or delegation chain.\n\t *\n\t * @see draft-goswami-agentic-jwt-00 §3.4\n\t * @see RFC 8693\n\t */\n\tACT: \"act\",\n\n\t/**\n\t * Authorized future actors for delegation chains (RFC 8693 `may_act`).\n\t *\n\t * @see draft-goswami-agentic-jwt-00 §3.5\n\t * @see RFC 8693\n\t */\n\tMAY_ACT: \"may_act\",\n\n\t/**\n\t * Trust score band at token issuance (e.g. `standard`, `elevated`).\n\t *\n\t * @see draft-goswami-agentic-jwt-00 §3.6\n\t */\n\tTRUST_TIER: \"trust_tier\",\n\n\t/**\n\t * Correlation id for tracing this token back to an entry in the audit log.\n\t *\n\t * @see draft-goswami-agentic-jwt-00 §3.7\n\t */\n\tAUDIT_REF: \"audit_ref\",\n\n\t/**\n\t * Per-tool budget or rate constraints encoded as a structured object.\n\t *\n\t * @see draft-goswami-agentic-jwt-00 §3.8\n\t */\n\tTOOL_CONSTRAINTS: \"tool_constraints\",\n\n\t/**\n\t * Workload Identity Token (WIT). Present only when three-layer cryptographic\n\t * binding is active (draft-liu §4.2). Absent in standard issuance paths.\n\t *\n\t * @see draft-liu-agent-operation-authorization-01 §4.2\n\t * TODO(v3): populate from WIT issuance when three-layer binding is implemented.\n\t */\n\tWORKLOAD_BINDING: \"wit\",\n\n\t/**\n\t * The scoped operation this token authorizes (e.g. `read:documents`).\n\t *\n\t * @see draft-liu-agent-operation-authorization-01 §4.3\n\t */\n\tOPERATION: \"operation\",\n} as const;\n\n// ---------------------------------------------------------------------------\n// Payload shape\n// ---------------------------------------------------------------------------\n\n/**\n * Optional shape of agentic JWT claims within a token payload.\n *\n * All fields are optional because they are only emitted when\n * `emitAgenticJwtClaims` is enabled and the relevant context is available\n * on the issuance path.\n */\nexport interface AgenticJwtClaims {\n\t/** Stable agent identifier. */\n\tagent_id?: string;\n\t/** Operational mode of the agent. */\n\tagent_type?: AgentType;\n\t/** Principal the agent is acting for. */\n\ton_behalf_of?: string;\n\t/** RFC 8693 actor claim (current actor in a delegation chain). */\n\tact?: Record<string, unknown>;\n\t/** RFC 8693 may_act claim (authorized future actors). */\n\tmay_act?: Record<string, unknown>;\n\t/** Trust tier band at issuance time. */\n\ttrust_tier?: TrustTier;\n\t/** Audit log correlation id. */\n\taudit_ref?: string;\n\t/** Per-tool budget or rate constraints. */\n\ttool_constraints?: Record<string, unknown>;\n\t/**\n\t * Workload Identity Token.\n\t * Absent unless three-layer binding is active.\n\t * TODO(v3): populate when draft-liu three-layer binding is implemented.\n\t */\n\twit?: string;\n\t/** Scoped operation this token authorizes. */\n\toperation?: string;\n}\n","import { SignJWT } from \"jose\";\nimport { generateId } from \"../crypto/web-crypto.js\";\nimport { AGENTIC_JWT_CLAIMS } from \"../standards/claims.js\";\nimport type {\n\tMcpAccessToken,\n\tMcpAuthContext,\n\tMcpTokenRequestParsed,\n\tMcpTokenResponse,\n\tResult,\n} from \"./types.js\";\nimport { McpTokenRequestSchema } from \"./types.js\";\nimport { extractBasicAuth, generateSecureToken, parseRequestBody, verifyS256 } from \"./utils.js\";\n\n/**\n * Derive the HMAC signing key from the config's signing secret.\n *\n * Uses the Web Crypto API so this works in Node, Deno, Bun, CF Workers.\n */\nasync function getSigningKey(secret: string): Promise<CryptoKey> {\n\tconst encoder = new TextEncoder();\n\treturn globalThis.crypto.subtle.importKey(\n\t\t\"raw\",\n\t\tencoder.encode(secret),\n\t\t{ name: \"HMAC\", hash: \"SHA-256\" },\n\t\tfalse,\n\t\t[\"sign\", \"verify\"],\n\t);\n}\n\n/**\n * Issue a signed JWT access token.\n */\nasync function issueAccessTokenJwt(\n\tctx: McpAuthContext,\n\tuserId: string,\n\tclientId: string,\n\tscopes: string[],\n\tresource: string | null,\n): Promise<{ jwt: string; jti: string; expiresAt: Date }> {\n\tconst secret = ctx.config.signingSecret;\n\tif (!secret) {\n\t\tthrow new Error(\"MCP signingSecret is required to issue tokens\");\n\t}\n\tconst key = await getSigningKey(secret);\n\tconst jti = generateId();\n\tconst now = Math.floor(Date.now() / 1000);\n\tconst exp = now + ctx.config.accessTokenTtl;\n\tconst expiresAt = new Date(exp * 1000);\n\n\t// Audience: either the specific resource (RFC 8707) or the issuer\n\tconst audience = resource ?? ctx.config.issuer;\n\n\t// Agentic JWT claims (draft-goswami-agentic-jwt-00)\n\tconst agenticClaims: Record<string, unknown> = {};\n\tif (ctx.config.emitAgenticJwtClaims === true && ctx.config.getAgenticContext !== undefined) {\n\t\tconst ac = await ctx.config.getAgenticContext(userId);\n\t\tif (ac.agentId !== undefined) {\n\t\t\tagenticClaims[AGENTIC_JWT_CLAIMS.AGENT_ID] = ac.agentId;\n\t\t}\n\t\tif (ac.agentType !== undefined) {\n\t\t\tagenticClaims[AGENTIC_JWT_CLAIMS.AGENT_TYPE] = ac.agentType;\n\t\t}\n\t\tif (ac.trustTier !== undefined) {\n\t\t\tagenticClaims[AGENTIC_JWT_CLAIMS.TRUST_TIER] = ac.trustTier;\n\t\t}\n\t}\n\n\tconst jwt = await new SignJWT({\n\t\tsub: userId,\n\t\tclient_id: clientId,\n\t\tscope: scopes.join(\" \"),\n\t\tjti,\n\t\t...agenticClaims,\n\t})\n\t\t.setProtectedHeader({ alg: \"HS256\", typ: \"at+jwt\" })\n\t\t.setIssuer(ctx.config.issuer)\n\t\t.setAudience(audience)\n\t\t.setIssuedAt(now)\n\t\t.setExpirationTime(exp)\n\t\t.sign(key);\n\n\treturn { jwt, jti, expiresAt };\n}\n\n/**\n * Resolve client credentials from the request.\n *\n * Supports:\n * - HTTP Basic Authentication (client_secret_basic)\n * - Body parameters (client_secret_post)\n * - No auth (public clients, token_endpoint_auth_method = \"none\")\n */\nfunction resolveClientCredentials(\n\trequest: Request,\n\tbody: Record<string, string>,\n): { clientId: string; clientSecret: string | null } | null {\n\t// Try Basic auth first\n\tconst basicAuth = extractBasicAuth(request);\n\tif (basicAuth) {\n\t\treturn { clientId: basicAuth[0], clientSecret: basicAuth[1] };\n\t}\n\n\t// Fall back to body params\n\tconst clientId = body.client_id;\n\tif (!clientId) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tclientId,\n\t\tclientSecret: body.client_secret ?? null,\n\t};\n}\n\n/**\n * Handle the OAuth 2.1 token endpoint.\n *\n * POST /mcp/token\n *\n * Supports two grant types:\n * 1. authorization_code - Exchange auth code + PKCE verifier for tokens\n * 2. refresh_token - Refresh an expired access token\n */\nexport async function handleTokenExchange(\n\tctx: McpAuthContext,\n\trequest: Request,\n): Promise<Result<McpTokenResponse>> {\n\t// ── Parse body ──────────────────────────────────────────────────\n\tconst body = await parseRequestBody(request);\n\n\t// ── Resolve client credentials ──────────────────────────────────\n\tconst credentials = resolveClientCredentials(request, body);\n\tif (!credentials) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_CLIENT\",\n\t\t\t\tmessage: \"client_id is required\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// Override body client_id with the resolved one\n\tbody.client_id = credentials.clientId;\n\tif (credentials.clientSecret) {\n\t\tbody.client_secret = credentials.clientSecret;\n\t}\n\n\t// ── Validate request body against schema ────────────────────────\n\tconst parsed = McpTokenRequestSchema.safeParse(body);\n\tif (!parsed.success) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_REQUEST\",\n\t\t\t\tmessage: \"Invalid token request\",\n\t\t\t\tdetails: { issues: parsed.error.flatten().fieldErrors },\n\t\t\t},\n\t\t};\n\t}\n\n\tconst data = parsed.data;\n\n\tif (data.grant_type === \"authorization_code\") {\n\t\treturn handleAuthorizationCodeGrant(ctx, data, credentials.clientSecret);\n\t}\n\n\treturn handleRefreshTokenGrant(ctx, data, credentials.clientSecret);\n}\n\n/**\n * authorization_code grant: exchange code + PKCE verifier for tokens.\n */\nasync function handleAuthorizationCodeGrant(\n\tctx: McpAuthContext,\n\tdata: Extract<McpTokenRequestParsed, { grant_type: \"authorization_code\" }>,\n\tclientSecret: string | null,\n): Promise<Result<McpTokenResponse>> {\n\t// ── Look up the client ──────────────────────────────────────────\n\tconst client = await ctx.findClient(data.client_id);\n\tif (!client) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_CLIENT\", message: \"Unknown client_id\" },\n\t\t};\n\t}\n\n\tif (client.disabled) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_CLIENT\", message: \"Client is disabled\" },\n\t\t};\n\t}\n\n\t// ── Validate client secret for confidential clients ─────────────\n\tif (client.clientType === \"confidential\") {\n\t\tif (!clientSecret || clientSecret !== client.clientSecret) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"INVALID_CLIENT\", message: \"Invalid client_secret\" },\n\t\t\t};\n\t\t}\n\t}\n\n\t// ── Consume the authorization code (one-time use) ───────────────\n\tconst authCode = await ctx.consumeAuthorizationCode(data.code);\n\tif (!authCode) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_GRANT\", message: \"Invalid or expired authorization code\" },\n\t\t};\n\t}\n\n\t// ── Validate code is not expired ────────────────────────────────\n\tif (authCode.expiresAt < new Date()) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_GRANT\", message: \"Authorization code has expired\" },\n\t\t};\n\t}\n\n\t// ── Validate client_id matches the code ─────────────────────────\n\tif (authCode.clientId !== data.client_id) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_GRANT\", message: \"client_id does not match authorization code\" },\n\t\t};\n\t}\n\n\t// ── Validate redirect_uri matches the code ──────────────────────\n\tif (authCode.redirectUri !== data.redirect_uri) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"INVALID_GRANT\",\n\t\t\t\tmessage: \"redirect_uri does not match authorization code\",\n\t\t\t},\n\t\t};\n\t}\n\n\t// ── PKCE: verify code_verifier against stored code_challenge ────\n\tconst pkceValid = await verifyS256(data.code_verifier, authCode.codeChallenge);\n\tif (!pkceValid) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_GRANT\", message: \"PKCE code_verifier verification failed\" },\n\t\t};\n\t}\n\n\t// ── Validate resource parameter (RFC 8707) ──────────────────────\n\t// If the auth code was bound to a resource, the token request must\n\t// either omit the resource parameter or match.\n\tif (data.resource !== undefined && authCode.resource !== null) {\n\t\tif (data.resource !== authCode.resource) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"INVALID_TARGET\",\n\t\t\t\t\tmessage: \"resource parameter does not match authorization code\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t}\n\n\tconst resource = data.resource ?? authCode.resource;\n\n\t// ── Issue tokens ────────────────────────────────────────────────\n\tconst { jwt, expiresAt } = await issueAccessTokenJwt(\n\t\tctx,\n\t\tauthCode.userId,\n\t\tdata.client_id,\n\t\tauthCode.scope,\n\t\tresource,\n\t);\n\n\tconst includeRefreshToken = authCode.scope.includes(\"offline_access\");\n\tconst refreshToken = includeRefreshToken ? generateSecureToken(48) : null;\n\n\tconst tokenRecord: McpAccessToken = {\n\t\taccessToken: jwt,\n\t\trefreshToken,\n\t\ttokenType: \"Bearer\",\n\t\texpiresIn: ctx.config.accessTokenTtl,\n\t\tscope: authCode.scope,\n\t\tclientId: data.client_id,\n\t\tuserId: authCode.userId,\n\t\tresource,\n\t\texpiresAt,\n\t\tcreatedAt: new Date(),\n\t};\n\n\tawait ctx.storeToken(tokenRecord);\n\n\t// ── Build response ──────────────────────────────────────────────\n\tconst response: McpTokenResponse = {\n\t\taccess_token: jwt,\n\t\ttoken_type: \"Bearer\",\n\t\texpires_in: ctx.config.accessTokenTtl,\n\t\tscope: authCode.scope.join(\" \"),\n\t\t...(refreshToken ? { refresh_token: refreshToken } : {}),\n\t};\n\n\treturn { success: true, data: response };\n}\n\n/**\n * refresh_token grant: rotate tokens.\n */\nasync function handleRefreshTokenGrant(\n\tctx: McpAuthContext,\n\tdata: Extract<McpTokenRequestParsed, { grant_type: \"refresh_token\" }>,\n\tclientSecret: string | null,\n): Promise<Result<McpTokenResponse>> {\n\t// ── Look up the client ──────────────────────────────────────────\n\tconst client = await ctx.findClient(data.client_id);\n\tif (!client) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_CLIENT\", message: \"Unknown client_id\" },\n\t\t};\n\t}\n\n\tif (client.disabled) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_CLIENT\", message: \"Client is disabled\" },\n\t\t};\n\t}\n\n\t// ── Validate client secret for confidential clients ─────────────\n\tif (client.clientType === \"confidential\") {\n\t\tif (!clientSecret || clientSecret !== client.clientSecret) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"INVALID_CLIENT\", message: \"Invalid client_secret\" },\n\t\t\t};\n\t\t}\n\t}\n\n\t// ── Find the existing token by refresh_token ────────────────────\n\tconst existingToken = await ctx.findTokenByRefreshToken(data.refresh_token);\n\tif (!existingToken) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_GRANT\", message: \"Invalid refresh token\" },\n\t\t};\n\t}\n\n\t// ── Validate client_id matches ──────────────────────────────────\n\tif (existingToken.clientId !== data.client_id) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_GRANT\", message: \"client_id does not match refresh token\" },\n\t\t};\n\t}\n\n\t// ── Check refresh token expiry ──────────────────────────────────\n\tconst refreshExpiry = new Date(\n\t\texistingToken.createdAt.getTime() + ctx.config.refreshTokenTtl * 1000,\n\t);\n\tif (refreshExpiry < new Date()) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"INVALID_GRANT\", message: \"Refresh token has expired\" },\n\t\t};\n\t}\n\n\t// ── Determine scopes (may be narrowed in the request) ───────────\n\tconst scopes = data.scope\n\t\t? data.scope.split(\" \").filter((s) => existingToken.scope.includes(s))\n\t\t: existingToken.scope;\n\n\t// ── Determine resource ──────────────────────────────────────────\n\tconst resource = data.resource ?? existingToken.resource;\n\n\t// ── Revoke the old token ────────────────────────────────────────\n\tawait ctx.revokeToken(existingToken.accessToken);\n\n\t// ── Issue new tokens (token rotation for security) ──────────────\n\tconst { jwt, expiresAt } = await issueAccessTokenJwt(\n\t\tctx,\n\t\texistingToken.userId,\n\t\tdata.client_id,\n\t\tscopes,\n\t\tresource,\n\t);\n\n\tconst newRefreshToken = generateSecureToken(48);\n\n\tconst tokenRecord: McpAccessToken = {\n\t\taccessToken: jwt,\n\t\trefreshToken: newRefreshToken,\n\t\ttokenType: \"Bearer\",\n\t\texpiresIn: ctx.config.accessTokenTtl,\n\t\tscope: scopes,\n\t\tclientId: data.client_id,\n\t\tuserId: existingToken.userId,\n\t\tresource,\n\t\texpiresAt,\n\t\tcreatedAt: new Date(),\n\t};\n\n\tawait ctx.storeToken(tokenRecord);\n\n\t// ── Build response ──────────────────────────────────────────────\n\tconst response: McpTokenResponse = {\n\t\taccess_token: jwt,\n\t\ttoken_type: \"Bearer\",\n\t\texpires_in: ctx.config.accessTokenTtl,\n\t\trefresh_token: newRefreshToken,\n\t\tscope: scopes.join(\" \"),\n\t};\n\n\treturn { success: true, data: response };\n}\n","import { handleAuthorize } from \"./authorize.js\";\nimport { approveConsent } from \"./consent.js\";\nimport { getAuthorizationServerMetadata, getProtectedResourceMetadata } from \"./metadata.js\";\nimport { registerClient } from \"./registration.js\";\nimport { requireScopes } from \"./require-scopes.js\";\nimport { buildStepUpResponse } from \"./step-up.js\";\nimport { handleTokenExchange } from \"./token.js\";\nimport type {\n\tApproveConsentParams,\n\tMcpAuthContext,\n\tMcpAuthModule,\n\tMcpClient,\n\tMcpClientRegistrationRequest,\n\tMcpConfig,\n\tResult,\n} from \"./types.js\";\nimport { buildUnauthorizedResponse, validateAccessToken, withMcpAuth } from \"./validate.js\";\n\n// ─── Default Configuration ──────────────────────────────────────────────────\n\nconst DEFAULT_ACCESS_TOKEN_TTL = 3600; // 1 hour\nconst DEFAULT_REFRESH_TOKEN_TTL = 604800; // 7 days\nconst DEFAULT_CODE_TTL = 600; // 10 minutes\n\n/**\n * Create the MCP authorization server module.\n *\n * This is the main factory that wires up all MCP OAuth 2.1 endpoints\n * into a single module. The caller provides storage callbacks (how to\n * persist clients, codes, and tokens) and user resolution (how to identify\n * the currently authenticated user).\n *\n * @example\n * ```typescript\n * const mcp = createMcpModule({\n * config: {\n * enabled: true,\n * issuer: 'https://auth.example.com',\n * baseUrl: 'https://auth.example.com/api/auth',\n * signingSecret: process.env.MCP_SIGNING_SECRET,\n * },\n * storeClient: async (client) => { await db.insert(mcpClients).values(client); },\n * findClient: async (id) => { return db.query.mcpClients.findFirst({ where: eq(mcpClients.clientId, id) }); },\n * storeAuthorizationCode: async (code) => { await db.insert(mcpCodes).values(code); },\n * consumeAuthorizationCode: async (code) => {\n * const found = await db.query.mcpCodes.findFirst({ where: eq(mcpCodes.code, code) });\n * if (found) await db.delete(mcpCodes).where(eq(mcpCodes.code, code));\n * return found ?? null;\n * },\n * storeToken: async (token) => { await db.insert(mcpTokens).values(token); },\n * findTokenByRefreshToken: async (rt) => { ... },\n * revokeToken: async (at) => { ... },\n * resolveUserId: async (request) => {\n * const session = await getSession(request);\n * return session?.userId ?? null;\n * },\n * });\n *\n * // Use in a framework adapter:\n * app.get('/.well-known/oauth-authorization-server', () => mcp.getMetadata());\n * app.get('/.well-known/oauth-protected-resource', () => mcp.getProtectedResourceMetadata());\n * app.post('/mcp/register', (req) => mcp.registerClient(req.body));\n * app.get('/mcp/authorize', (req) => mcp.authorize(req));\n * app.post('/mcp/token', (req) => mcp.token(req));\n * ```\n */\nexport function createMcpModule(params: {\n\tconfig: McpConfig;\n\tstoreClient: McpAuthContext[\"storeClient\"];\n\tfindClient: McpAuthContext[\"findClient\"];\n\tstoreAuthorizationCode: McpAuthContext[\"storeAuthorizationCode\"];\n\tconsumeAuthorizationCode: McpAuthContext[\"consumeAuthorizationCode\"];\n\tstoreToken: McpAuthContext[\"storeToken\"];\n\tfindTokenByRefreshToken: McpAuthContext[\"findTokenByRefreshToken\"];\n\trevokeToken: McpAuthContext[\"revokeToken\"];\n\tresolveUserId: McpAuthContext[\"resolveUserId\"];\n}): McpAuthModule {\n\t// ── Validate required config ────────────────────────────────────\n\tconst config = params.config;\n\tif (!config.issuer) {\n\t\tthrow new Error(\"McpConfig.issuer is required\");\n\t}\n\tif (!config.baseUrl) {\n\t\tthrow new Error(\"McpConfig.baseUrl is required\");\n\t}\n\tif (!config.signingSecret) {\n\t\tthrow new Error(\"McpConfig.signingSecret is required (>= 32 chars)\");\n\t}\n\tif (config.signingSecret.length < 32) {\n\t\tthrow new Error(\"McpConfig.signingSecret must be at least 32 characters\");\n\t}\n\n\t// ── Build resolved config with defaults ─────────────────────────\n\tconst resolvedConfig = {\n\t\t...config,\n\t\tissuer: config.issuer,\n\t\tbaseUrl: config.baseUrl,\n\t\tsigningSecret: config.signingSecret,\n\t\taccessTokenTtl: config.accessTokenTtl ?? DEFAULT_ACCESS_TOKEN_TTL,\n\t\trefreshTokenTtl: config.refreshTokenTtl ?? DEFAULT_REFRESH_TOKEN_TTL,\n\t\tcodeTtl: config.codeTtl ?? DEFAULT_CODE_TTL,\n\t};\n\n\t// ── Build the context shared by all handlers ────────────────────\n\tconst ctx: McpAuthContext = {\n\t\tconfig: resolvedConfig,\n\t\tstoreClient: params.storeClient,\n\t\tfindClient: params.findClient,\n\t\tstoreAuthorizationCode: params.storeAuthorizationCode,\n\t\tconsumeAuthorizationCode: params.consumeAuthorizationCode,\n\t\tstoreToken: params.storeToken,\n\t\tfindTokenByRefreshToken: params.findTokenByRefreshToken,\n\t\trevokeToken: params.revokeToken,\n\t\tresolveUserId: params.resolveUserId,\n\t};\n\n\t// ── Pre-register static clients ─────────────────────────────────\n\t// Store each pre-registered client via storeClient during module\n\t// initialisation. Returns a Promise that callers may await if needed.\n\tconst preRegistrationPromise: Promise<void> = (async () => {\n\t\tconst preClients = resolvedConfig.preRegisteredClients ?? [];\n\t\tconst now = new Date();\n\t\tfor (const preClient of preClients) {\n\t\t\tconst isPublic = preClient.clientSecret === undefined || preClient.clientSecret === null;\n\t\t\tconst client: McpClient = {\n\t\t\t\tclientId: preClient.clientId,\n\t\t\t\tclientSecret: preClient.clientSecret ?? null,\n\t\t\t\tclientName: preClient.clientName ?? null,\n\t\t\t\tclientUri: null,\n\t\t\t\tlogoUri: null,\n\t\t\t\tredirectUris: preClient.redirectUris,\n\t\t\t\tgrantTypes: [\"authorization_code\", \"refresh_token\"],\n\t\t\t\tresponseTypes: [\"code\"],\n\t\t\t\ttokenEndpointAuthMethod: isPublic ? \"none\" : \"client_secret_basic\",\n\t\t\t\tscope: preClient.scope ?? null,\n\t\t\t\tcontacts: null,\n\t\t\t\ttosUri: null,\n\t\t\t\tpolicyUri: null,\n\t\t\t\tsoftwareId: null,\n\t\t\t\tsoftwareVersion: null,\n\t\t\t\tclientType: isPublic ? \"public\" : \"confidential\",\n\t\t\t\tdisabled: false,\n\t\t\t\tuserId: null,\n\t\t\t\tcreatedAt: now,\n\t\t\t\tupdatedAt: now,\n\t\t\t};\n\t\t\tawait params.storeClient(client);\n\t\t}\n\t})();\n\n\t// Expose the promise so tests/callers can await full initialisation.\n\tvoid preRegistrationPromise;\n\n\t// ── Return the public module API ────────────────────────────────\n\treturn {\n\t\tgetMetadata: () => getAuthorizationServerMetadata(ctx),\n\t\tgetProtectedResourceMetadata: () => getProtectedResourceMetadata(ctx),\n\n\t\tregisterClient: (body: McpClientRegistrationRequest) => registerClient(ctx, body),\n\n\t\tauthorize: (request: Request) => handleAuthorize(ctx, request),\n\n\t\tapproveConsent: (p: ApproveConsentParams) => approveConsent(ctx, p),\n\n\t\ttoken: (request: Request) => handleTokenExchange(ctx, request),\n\n\t\tvalidateToken: (token: string, requiredScopes?: string[]) =>\n\t\t\tvalidateAccessToken(ctx, token, { requiredScopes }),\n\n\t\tmiddleware: (request: Request) => withMcpAuth(ctx, request),\n\n\t\tbuildStepUpResponse: (options: {\n\t\t\tcurrentScopes: string[];\n\t\t\trequiredScopes: string[];\n\t\t\tresource?: string;\n\t\t}) => buildStepUpResponse(ctx, options),\n\n\t\trequireScopes: (request: Request, scopes: string[]) => requireScopes(ctx, request, scopes),\n\t};\n}\n\n/**\n * Create HTTP Response helpers for framework adapters.\n *\n * These take Result types and produce standard Response objects\n * with proper status codes, cache-control headers, and CORS.\n */\nexport function createMcpResponseHelpers(ctx: McpAuthContext) {\n\tconst corsHeaders = {\n\t\t\"Access-Control-Allow-Origin\": \"*\",\n\t\t\"Access-Control-Allow-Methods\": \"GET, POST, OPTIONS\",\n\t\t\"Access-Control-Allow-Headers\": \"Content-Type, Authorization\",\n\t\t\"Access-Control-Max-Age\": \"86400\",\n\t};\n\n\treturn {\n\t\t/** Metadata endpoints: 200 with JSON */\n\t\tmetadataResponse: (data: unknown): Response =>\n\t\t\tnew Response(JSON.stringify(data), {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t...corsHeaders,\n\t\t\t\t},\n\t\t\t}),\n\n\t\t/** Registration: 201 with Cache-Control: no-store */\n\t\tregistrationResponse: (result: Result<unknown>): Response => {\n\t\t\tif (!result.success) {\n\t\t\t\treturn new Response(\n\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\terror: \"invalid_client_metadata\",\n\t\t\t\t\t\terror_description: result.error.message,\n\t\t\t\t\t}),\n\t\t\t\t\t{\n\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\theaders: { \"Content-Type\": \"application/json\", ...corsHeaders },\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn new Response(JSON.stringify(result.data), {\n\t\t\t\tstatus: 201,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t\t\tPragma: \"no-cache\",\n\t\t\t\t\t...corsHeaders,\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\n\t\t/** Authorization: 302 redirect or error */\n\t\tauthorizeResponse: (result: Result<{ redirectUri: string }>): Response => {\n\t\t\tif (!result.success) {\n\t\t\t\t// If login is required, the caller should redirect to the login page\n\t\t\t\tif (result.error.code === \"LOGIN_REQUIRED\") {\n\t\t\t\t\tconst details = result.error.details as\n\t\t\t\t\t\t| { loginPage?: string; returnTo?: string }\n\t\t\t\t\t\t| undefined;\n\t\t\t\t\tif (details?.loginPage) {\n\t\t\t\t\t\tconst loginUrl = new URL(details.loginPage);\n\t\t\t\t\t\tif (details.returnTo) {\n\t\t\t\t\t\t\tloginUrl.searchParams.set(\"returnTo\", details.returnTo);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn Response.redirect(loginUrl.toString(), 302);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn new Response(\n\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\terror: result.error.code.toLowerCase(),\n\t\t\t\t\t\terror_description: result.error.message,\n\t\t\t\t\t}),\n\t\t\t\t\t{\n\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn Response.redirect(result.data.redirectUri, 302);\n\t\t},\n\n\t\t/** Token: 200 with Cache-Control: no-store or error */\n\t\ttokenResponse: (result: Result<unknown>): Response => {\n\t\t\tif (!result.success) {\n\t\t\t\tconst status = result.error.code === \"INVALID_CLIENT\" ? 401 : 400;\n\t\t\t\treturn new Response(\n\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\terror: result.error.code.toLowerCase(),\n\t\t\t\t\t\terror_description: result.error.message,\n\t\t\t\t\t}),\n\t\t\t\t\t{\n\t\t\t\t\t\tstatus,\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t\t\t\t\tPragma: \"no-cache\",\n\t\t\t\t\t\t\t...corsHeaders,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn new Response(JSON.stringify(result.data), {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t\t\tPragma: \"no-cache\",\n\t\t\t\t\t...corsHeaders,\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\n\t\t/** Auth failure in JSON-RPC format for MCP resource servers */\n\t\tunauthorizedResponse: (error: { code: string; message: string }): Response =>\n\t\t\tbuildUnauthorizedResponse(ctx, error),\n\t};\n}\n"]}
|