-
Notifications
You must be signed in to change notification settings - Fork 195
Description
Overview
Add an optional embedded OAuth authorization server (AS) to vMCP. When enabled, the AS acts as the OIDC issuer for incoming clients: it drives users through one or more upstream IDPs, accumulates their tokens, and issues a ToolHive JWT. The OIDC middleware validates that TH-JWT via a self-referencing loopback and eagerly loads the upstream tokens into `identity.UpstreamTokens`. Existing behavior when no AS is configured (Mode A) is byte-for-byte unchanged.
Background
vMCP today requires clients to obtain upstream IDP tokens externally before connecting — there is no mechanism for vMCP to orchestrate the auth flow itself. Additionally, upstream tokens accumulated during login have no unified path into the outgoing auth layer; the `upstream_inject` strategy (which would inject an upstream provider token into backend requests) has no source to draw from.
This RFC adds Mode B, where vMCP hosts the auth server at the same origin, handles OAuth/OIDC discovery as a loopback, and makes upstream tokens available to outgoing auth strategies via `identity.UpstreamTokens`.
RFC: stacklok/toolhive-rfcs#53
Depends on: #3924 (RFC-0052 multi-upstream IDP support) for full end-to-end token flow
Task Breakdown
| Task | GitHub Issue | Title | Depends On |
|---|---|---|---|
| Phase 1 | #4140 | Foundation — add AuthServerConfig model, CRD field, and structural validation | — |
| Phase 2 | #4141 | Server wiring — mount embedded auth server routes on vMCP mux | #4140 |
| Phase 3 | #4142 | Startup validation (V-01..V-07) — upstream_inject types and validateAuthServerIntegration | #4140 |
| Phase 4 | #4143 | Operator reconciler, HTTP handler unit tests, and E2E test coverage | #4141, #4142 |
#4140 (Phase 1: Foundation)
|
+---> #4141 (Phase 2: Server wiring) \
| +---> #4143 (Phase 4: Operator + E2E)
+---> #4142 (Phase 3: Startup validation) /
Phase 1 is the root; Phases 2 and 3 can be developed in parallel; Phase 4 is the integration phase.
Acceptance Criteria
- vMCP can be configured with an embedded AS (
authServer.runConfigin YAML;spec.authServerConfigRefin K8s) and serves OAuth/OIDC endpoints at the same origin -
/.well-known/openid-configuration,/.well-known/oauth-authorization-server,/.well-known/jwks.json, and/oauth/are mounted as unauthenticated routes in Mode B; Mode A is unaffected - The
/.well-known/catch-all handler is replaced with an explicit/.well-known/oauth-protected-resourceregistration (non-breaking) - Validation rules V-01..V-07 are enforced at startup (YAML path) and at operator reconciliation (K8s path), producing actionable error messages
- The operator reconciler resolves
spec.authServerConfigRef, validates type and issuer consistency, and surfaces anAuthServerConfigValidstatus condition - Mode A behavior is byte-for-byte identical to today — all new code paths are gated on
cfg.AuthServer != nil - All linked task issues (Phase 1: Foundation — add AuthServerConfig model, CRD field, and structural validation #4140, Phase 2: Server wiring — mount embedded auth server routes on vMCP mux #4141, Phase 3: Startup validation (V-01..V-07) — upstream_inject types and validateAuthServerIntegration #4142, Phase 4: Operator reconciler, HTTP handler unit tests, and E2E test coverage for embedded AS #4143) completed and merged
- Unit tests for validation rules (V-01..V-07), server route mounting (Mode A/B), and CRD structural validation
- E2E tests for Mode A/B routing, negative validation cases, and operator condition lifecycle