Skip to content

Wire in-process JWKS key resolution for vMCP embedded auth server#4526

Merged
tgrunnagle merged 2 commits intomainfrom
issue_4466_self-ref-jwksurl-vmcp
Apr 3, 2026
Merged

Wire in-process JWKS key resolution for vMCP embedded auth server#4526
tgrunnagle merged 2 commits intomainfrom
issue_4466_self-ref-jwksurl-vmcp

Conversation

@tgrunnagle
Copy link
Copy Markdown
Contributor

Summary

When the embedded auth server is active in vMCP (VirtualMCPServer), token validation was failing silently because the OIDC middleware fetched JWKS keys over HTTP from the proxy's own endpoint — a self-referential HTTP round-trip that required operators to set insecureAllowHTTP and/or jwksAllowPrivateIP just to make token validation work. These are insecure workarounds, and the failures were difficult to diagnose.

This PR extends the fix from #4502 (which addressed the same problem for the runner and proxy runner) to vMCP. The embedded auth server's KeyProvider is now extracted in runServe and passed through to the OIDC middleware factory, where it is wired into the TokenValidator for in-process key resolution. HTTP JWKS fetch is retained as a fallback for key-ID misses and external OIDC providers.

Closes #4466

Type of change

  • New feature

Test plan

  • Unit tests (task test)
  • Linting (task lint-fix)

Changes

File Change
cmd/vmcp/app/commands.go Extract keyProvider from embeddedAuthServer in runServe and pass it to NewIncomingAuthMiddleware
pkg/vmcp/auth/factory/incoming.go Accept keyProvider keys.PublicKeyProvider parameter in NewIncomingAuthMiddleware and newOIDCAuthMiddleware; wire it into auth.WithKeyProvider option when non-nil
pkg/vmcp/auth/factory/incoming_keyprovider_test.go New test file: three integration-level tests covering local key resolution, HTTP JWKS fallback when no provider is set, and kid-miss fallback to HTTP
pkg/vmcp/auth/factory/incoming_test.go Update existing test to pass nil for the new keyProvider parameter
pkg/vmcp/auth/factory/incoming_upstream_test.go Update existing test to pass nil for the new keyProvider parameter
pkg/vmcp/auth/factory/authz_not_wired_test.go Update existing test to pass nil for the new keyProvider parameter

Does this introduce a user-facing change?

Yes. VirtualMCPServer operators using the embedded auth server no longer need to configure jwksUrl, insecureAllowHTTP, or jwksAllowPrivateIP for token validation to function. The embedded auth server's signing keys are resolved in-process automatically.

Special notes for reviewers

  • The keyProvider parameter is nil-safe throughout: when nil, the OIDC middleware behaves identically to before this change, falling back to HTTP JWKS as the only key source.
  • The three new tests in incoming_keyprovider_test.go stand up a real (in-process) OIDC discovery server to validate the full middleware wiring — local resolution, nil-provider HTTP fallback, and kid-miss HTTP fallback.
  • The core TokenValidator in-process resolution logic (including getKeyFromLocalProvider) lives in pkg/auth/token.go and was introduced in Resolve JWKS keys in-process for embedded auth server (MCP server) #4502. This PR only adds the vMCP-layer wiring.

Generated with Claude Code

tgrunnagle and others added 2 commits April 3, 2026 08:08
Address code review feedback on incoming_keyprovider_test.go:
- MEDIUM: Split TestNewOIDCAuthMiddleware_KeyProviderWiring into two
  independent top-level functions so each test is fully self-contained;
  outer-level setup no longer leaks into subtests that don't use it
- LOW: Add TestNewOIDCAuthMiddleware_KeyProvider_KidMissFallback to cover
  the end-to-end kid-miss path at the factory level, confirming the
  validator falls back to HTTP JWKS when the local provider holds no
  matching key

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot added the size/S Small PR: 100-299 lines changed label Apr 3, 2026
@tgrunnagle tgrunnagle marked this pull request as ready for review April 3, 2026 15:57
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 3, 2026

Codecov Report

❌ Patch coverage is 50.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 69.04%. Comparing base (6adbe2b) to head (7161e2d).
⚠️ Report is 13 commits behind head on main.

Files with missing lines Patch % Lines
cmd/vmcp/app/commands.go 0.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4526      +/-   ##
==========================================
- Coverage   69.13%   69.04%   -0.10%     
==========================================
  Files         502      505       +3     
  Lines       51959    52148     +189     
==========================================
+ Hits        35921    36004      +83     
- Misses      13254    13360     +106     
  Partials     2784     2784              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@tgrunnagle tgrunnagle merged commit ffef243 into main Apr 3, 2026
51 of 52 checks passed
@tgrunnagle tgrunnagle deleted the issue_4466_self-ref-jwksurl-vmcp branch April 3, 2026 20:41
MatteoManzoni pushed a commit to DocPlanner/toolhive that referenced this pull request Apr 4, 2026
…acklok#4526)

When the embedded auth server is active in vMCP (VirtualMCPServer), token validation was failing silently because the OIDC middleware fetched JWKS keys over HTTP from the proxy's own endpoint — a self-referential HTTP round-trip that required operators to set `insecureAllowHTTP` and/or `jwksAllowPrivateIP` just to make token validation work. These are insecure workarounds, and the failures were difficult to diagnose.

This PR extends the fix for the runner and proxy runner to vMCP. The embedded auth server's `KeyProvider` is now extracted in `runServe` and passed through to the OIDC middleware factory, where it is wired into the `TokenValidator` for in-process key resolution. HTTP JWKS fetch is retained as a fallback for key-ID misses and external OIDC providers.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/S Small PR: 100-299 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Eliminate self-referential HTTP fetch for JWKS when using embedded auth server

2 participants