Skip to content

auth-framework concept page: deeper structural gaps surfaced during #825 review #837

@jhrozek

Description

@jhrozek

While working on #825 (PR #836), an MCP-protocol + OAuth-expert + ToolHive-source review of docs/toolhive/concepts/auth-framework.mdx surfaced findings that go beyond editorial accuracy — they involve adding missing concepts, reworking diagrams, or restructuring sections. PR #836 deliberately scoped these out so the spec-alignment work could land cleanly. This issue tracks them.

All findings are spec-grounded and were verified either against the MCP authorization spec (2025-11-25) or the ToolHive source code.

Must-fix (spec compliance gaps)

1. Missing RFC 9728 Protected Resource Metadata + WWW-Authenticate 401 challenge

The "Authentication flow" steps and the first mermaid diagram (lines ~157-179) skip the spec-mandated discovery handshake entirely. The spec is explicit:

MCP servers MUST implement OAuth 2.0 Protected Resource Metadata (RFC9728). MCP clients MUST use OAuth 2.0 Protected Resource Metadata for authorization server discovery.

And: clients are expected to discover the AS by hitting an MCP endpoint without a token, getting a 401 Unauthorized with WWW-Authenticate: Bearer resource_metadata=..., then fetching the PRM.

ToolHive does implement this — pkg/auth/token.go:1298 advertises BearerMethodsSupported: [\"header\"] and the auth-info handler exposes the PRM — but the doc never describes it.

Suggested addition: a step 0 ("client probes without token, ToolHive returns 401 with WWW-Authenticate and a resource_metadata URL") and a step 0b ("client fetches PRM and discovers the authorization server") before the existing token-acquisition step. Update the mermaid diagram to match.

2. Missing audience validation / RFC 8707 Resource Indicators

Token-validation step (lines ~165-168) lists "signature, expiration, claims" but never mentions audience binding, which the spec elevates to MUST:

MCP servers MUST validate that access tokens were issued specifically for them as the intended audience, according to RFC 8707 Section 2.

Should be a first-class validation step.

3. Missing PKCE callout

Page calls out "OAuth 2.1 authorization profile" but never mentions PKCE, which is mandatory in OAuth 2.1 and required by the MCP profile (S256 code challenge when capable). Worth at least a sentence.

4. Missing token-passthrough prohibition

Spec MUST NOT: MCP servers must not forward client tokens to upstream APIs.

If the MCP server makes requests to upstream APIs… The MCP server MUST NOT pass through the token it received from the MCP client.

Given the page's "external services like GitHub" framing, a one-liner clarifying that ToolHive does not forward client tokens to backends would close the gap. Cross-link to Backend authentication.

Nice-to-have (accuracy nuances)

5. JWT-first / introspection-fallback wording is overbroad

Lines 150-153 and 236-239: "ToolHive automatically detects the token type ... attempting JWT validation first and falling back to token introspection if needed."

Source check: pkg/auth/token.go:1077 only falls back on jwt.ErrTokenMalformed. A well-formed JWT with a bad signature or expired claim is rejected outright — no fallback. Suggested rewording: "If the token is not JWT-formatted, ToolHive falls back to introspection. A well-formed JWT that fails signature or expiration checks is rejected, not retried as opaque."

6. JWKS / kid / caching / discovery via jwks_uri

Line ~166 says "the provider's public keys (JWKS)" but never mentions kid-based key selection, JWKS caching with TTL, or that the JWKS URL is discovered via the AS metadata's jwks_uri. A single sentence would close the gap.

7. Identity providers list — Kubernetes caveat

Lines ~205-213 list Kubernetes service account tokens alongside Google/Okta/Auth0/etc. as a peer IdP, but Kubernetes service accounts aren't usable with the embedded authorization server (no auth code flow). The line 217 caveat ("the upstream provider must support the OAuth 2.0 authorization code flow") silently excludes them. Make it explicit.

8. Embedded auth server: clarify upstream auth code flow vs RFC 8693

Lines ~183-188: the embedded AS "obtains tokens from an upstream provider on behalf of clients." A reader could wonder if this is RFC 8693 token exchange. Line 62 already says federation/token-exchange isn't the answer, but the embedded-AS section doesn't reconnect. Stating that the embedded AS runs an authorization code flow on the upstream (not token exchange) would disambiguate.

Editorial / structural

9. Mermaid diagrams overlap

Two mermaid diagrams cover the same flow:

  • Lines 172-179 in the "Authentication flow" section (incorrectly includes Cedar/permit/deny — those are authorization).
  • Lines 290-298 in the "Authorization flow" section (correctly shows the auth → authz → Cedar pipeline).

Three options:

  1. Rename the first heading to "Authentication and authorization flow" (and accept end-to-end).
  2. Drop the Cedar nodes from the first diagram so it's authentication-only.
  3. Drop the first diagram entirely; let the second cover the full pipeline.

10. authn/authz vocabulary vs MCP spec terminology

Page-wide: the MCP spec uses "authorization" to cover both phases (token validation and access decision). The doc uses "authentication" for token validation, which is the more familiar split but conflicts with the spec's vocabulary. Worth a one-sentence note that maps the doc's terms to the spec's so readers can navigate both.

Notes

  • All findings are page-level; none requires changes elsewhere in the docs.
  • Items 1-4 (must-fix) are content additions. Items 5-10 are clarifications or restructuring.
  • A natural split for follow-up PRs: one for the missing-spec-concepts cluster (1-4), one for the accuracy-nuance cluster (5-8), and one for the structural cleanup (9-10).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions