fix: serve RFC 9728 path-suffixed metadata, document connector redirect URIs

Two separate discovery footguns, both found while debugging an Authentik
"Redirect URI Error" on a claude.ai custom connector.

RFC 9728 §3.1 puts the metadata for a resource identified by
`https://host/api/mcp` at `/.well-known/oauth-protected-resource/api/mcp`.
Only the root form was served, so clients that derive the metadata URL from
the MCP endpoint URL — rather than reading `resource_metadata` off our 401 —
got Next.js's HTML 404 and failed discovery with a JSON parse error.

Add a `[...path]` route serving the same document with `resource` naming the
suffixed identifier (§3.3 has the client compare it as an exact string, so
echoing the bare origin would be rejected). The document body moves to
`lib/auth/resource-metadata.ts` so the two routes cannot drift apart on
`scopes_supported` — a divergence there costs you the `aud` claim or the
refresh token. Paths are allowlisted rather than wildcarded so this cannot
advertise resources the app does not serve. `buildWwwAuthenticate()` still
points at the root URL; this change is purely additive.

Separately, the redirect URIs an MCP provider needs depend on how clients
reach it: a loopback URI for the CLI, `https://claude.ai/api/mcp/auth_callback`
for a claude.ai custom connector. Registering only the former is what produces
the "Redirect URI Error" page, and a portless `http://localhost/callback`
entry matches nothing the CLI sends. Document both, keyed on the literal
error text, and note that DCR is enterprise-gated on Authentik so these are
hand-registered on a FOSS instance.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-16 16:08:06 -07:00
co-authored by Claude Opus 5
parent c68d72857f
commit 29f5673eac
7 changed files with 324 additions and 38 deletions
+10
View File
@@ -72,6 +72,16 @@ The redirect URI you register on the Web UI client is
`https://${domain_name}/api/auth/callback/oidc`, so plan the domain name
*before* configuring the IdP.
The MCP client needs its own list, and most of it does not depend on the
domain: a loopback URI for the Claude Code CLI, plus
`https://claude.ai/api/mcp/auth_callback` if anyone will add the server as a
claude.ai custom connector. Only the manual-paste fallback,
`https://${domain_name}/auth/cli-callback`, follows the domain. See
[Which redirect URIs to register](../README.md#which-redirect-uris-to-register)
— a client can only register its own redirect URI against an IdP that offers
Dynamic Client Registration, which Authentik gates behind an enterprise
licence, so plan on adding all of these by hand.
---
## Quick start