Skip to content

Support RFC 9728 §3.1 WWW-Authenticate resource_metadata in OAuth discovery #196

@mgoldsborough

Description

@mgoldsborough

Problem

workspace-oauth-provider.discoverAuthorizationServerOrigins only tries <bundle-origin>/.well-known/oauth-protected-resource when probing for the MCP server's protected-resource metadata, then falls back to the bundle origin as the AS.

This misses spec-compliant servers that advertise the metadata URL via the WWW-Authenticate: Bearer ... resource_metadata="..." header on a 401 response from the MCP endpoint, per RFC 9728 §3.1. The metadata may live at any path — RFC 9728 only requires that the server advertise the URL, not that it sit at the well-known root.

Concrete blocker

Supabase MCP (https://mcp.supabase.com/mcp):

$ curl -sI -X POST https://mcp.supabase.com/mcp ...
HTTP/2 401
www-authenticate: Bearer error="invalid_request",
  error_description="No access token was provided in this request",
  resource_metadata="https://mcp.supabase.com/.well-known/oauth-protected-resource/mcp"

$ curl https://mcp.supabase.com/.well-known/oauth-protected-resource/mcp
{
  "resource": "https://mcp.supabase.com/mcp",
  "authorization_servers": ["https://api.supabase.com"],
  ...
}

The metadata is at /.well-known/oauth-protected-resource/mcp, not the root. We don't follow the header pointer, so we never find it. Install fails with "no AS metadata advertised registration_endpoint."

Supabase is currently dropped from catalog.yaml until this is fixed (see commit message on the catalog change in PR #195).

Fix

In discoverAuthorizationServerOrigins (src/tools/workspace-oauth-provider.ts):

  1. After the well-known-root probe returns no AS origins, do a no-auth GET (or POST) to the bundle URL.
  2. Parse the WWW-Authenticate response header for the resource_metadata parameter.
  3. If found, GET that URL; treat its authorization_servers[] the same way the well-known-root path does today.
  4. Bundle origin remains the final fallback.

Mirror the same fallback in scripts/check-catalog-dcr.ts so the probe agrees with production behavior.

Test plan

  • Add com.supabase/mcp back to catalog.yaml.
  • bun run check:catalog reports it passing via the WWW-Authenticate path.
  • Manual: install Supabase via Browse, complete the DCR round-trip against api.supabase.com.

Related

  • Catalog: src/connectors/catalog.yaml
  • Discovery: src/tools/workspace-oauth-provider.ts:222
  • Probe: scripts/check-catalog-dcr.ts

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions