diff --git a/src/server/auth/middleware/bearerAuth.ts b/src/server/auth/middleware/bearerAuth.ts index dac6530865..923995e558 100644 --- a/src/server/auth/middleware/bearerAuth.ts +++ b/src/server/auth/middleware/bearerAuth.ts @@ -15,7 +15,11 @@ export type BearerAuthMiddlewareOptions = { requiredScopes?: string[]; /** - * Optional resource metadata URL to include in WWW-Authenticate header. + * Resource metadata URL to advertise in the `WWW-Authenticate` challenge on 401/403 + * responses (RFC 9728 §5.1). The MCP authorization spec requires MCP servers to send it, so + * pass `getOAuthProtectedResourceMetadataUrl(mcpServerUrl)` for any protected MCP endpoint. + * When omitted, clients must guess the well-known location and strict clients can fail + * discovery; leave it out only for non-MCP or legacy deployments. */ resourceMetadataUrl?: string; }; diff --git a/src/server/auth/router.ts b/src/server/auth/router.ts index 1df0be091f..e4271e283f 100644 --- a/src/server/auth/router.ts +++ b/src/server/auth/router.ts @@ -51,6 +51,14 @@ export type AuthRouterOptions = { /** * The URL of the protected resource (RS) whose metadata we advertise. * If not provided, falls back to `baseUrl` and then to `issuerUrl` (AS=RS). + * + * Pass the MCP endpoint URL itself (e.g. `https://api.example.com/mcp`), not just the + * origin. RFC 9728 §3 places the metadata at + * `/.well-known/oauth-protected-resource/` and §3.3 requires its `resource` to be + * identical to the resource the client connected to. The `baseUrl` fallback therefore only + * yields a compliant document when the MCP endpoint is served at the origin root; clients + * that enforce §3.3 (Gemini CLI, Antigravity CLI) reject `resource: https://host/` when they + * connected to `https://host/mcp`, while the reference SDK client happens to accept it. */ resourceServerUrl?: URL;