stacklok / stacklok/toolhive

MCPRemoteProxy needs separate auth configs for vMCP→proxy and proxy→remote server boundaries

Open
#4,109 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

authentication bug enhancement go kubernetes operator vmcp
Dominant language
Go
Stars
2.2k
Forks
300
Avg merge
1d 15h
Merged PRs (30d)
184

Description

Description

MCPRemoteProxy has a single externalAuthConfigRef field that is currently used for two distinct authentication boundaries:

  1. vMCP → MCPRemoteProxy: vMCP reads the externalAuthConfigRef via outgoingAuth.source: discovered and performs a token exchange to authenticate with the proxy
  2. MCPRemoteProxy → Remote Server: The proxy's own token exchange middleware reads the same externalAuthConfigRef to exchange the incoming token for one scoped to the remote server

This means both exchanges use the same config — same tokenUrl, clientId, and audience — which makes the second exchange circular and redundant. A token exchanged by vMCP with audience=mcp-proxy gets exchanged again by the proxy using the same audience, producing no meaningful change.

The Problem in Detail

The correct flow should be:

Client token (aud=vmcp)
    │
    ▼ Exchange #1 (vMCP → MCPRemoteProxy)
Token (aud=mcp-proxy)
    │
    ▼ Exchange #2 (MCPRemoteProxy → Remote Server)
Token (aud=remote-server)
    │
    ▼
Remote MCP Server

Each exchange must produce a token with a different audience. However, since both exchanges share the same externalAuthConfigRef, they target the same audience — breaking the chain.

Additionally, simply forwarding the client token from vMCP to MCPRemoteProxy without exchange is not a valid workaround, because the client token's audience is scoped to vMCP and would be rejected by MCPRemoteProxy's oidcConfig.

Root Cause

MCPRemoteProxy only has one externalAuthConfigRef field, which is ambiguous — it is read by both vMCP (for outgoing auth to the proxy) and by the proxy itself (for outgoing auth to the remote server), but these two boundaries require different token exchange configurations.

Proposed Solution

Introduce two separate auth config references on MCPRemoteProxy:

  1. externalAuthConfigRef (existing) — used by vMCP to authenticate to the proxy (produces a token with the proxy's expected audience)
  2. remoteAuthConfigRef (new) — used by the proxy itself to authenticate to the remote server (produces a token with the remote server's expected audience)

This cleanly separates the two boundaries and allows each exchange to be independently configured with the correct tokenUrl, clientId, audience, and scopes.

Impact

  • Token exchange with MCPRemoteProxy backends is effectively broken when both boundaries require different audiences
  • Debugging is difficult as both exchanges silently use the same config
  • Users configuring MCPRemoteProxy with token exchange cannot correctly secure both the vMCP→proxy and proxy→remote boundaries independently

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Trace every use of MCPRemoteProxy's externalAuthConfigRef across vMCP outgoing authentication and the proxy's remote-server token exchange. Introduce and wire the separate remote configuration so the two exchanges can target distinct audiences, then verify both authentication boundaries use their intended configs.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
authentication, backend-api-design, security
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.