Skip to content

[vMCP] Extend identity-refresh integration test to wire TokenValidator.Middleware + fake UpstreamTokenRefresher #5334

@tgrunnagle

Description

@tgrunnagle

Context

The fix for #5323 added a higher-level integration test (pkg/vmcp/session/internal/backend/mcp_session_identity_refresh_test.go) that exercises the full transport chain — headerForwardRoundTripper → identityRoundTripper → authRoundTripper (UpstreamInjectStrategy) → http.DefaultTransport — and verifies that a fresh identity placed on req.Context() drives the upstream Authorization header.

That test attaches freshIdentity to the request context directly via auth.WithIdentity(...), which is the same call TokenValidator.Middleware makes at pkg/auth/token.go:1245. The iteration 2 review of #5323 explicitly allowed this higher-level alternative, but noted that it does not verify the link from TokenValidator.MiddlewareloadUpstreamTokensUpstreamTokenRefresher → fresh map on identity.UpstreamTokens.

Gap

The user-visible "forced re-auth every ~24h" symptom can recur via multiple distinct failure modes:

  1. The transport overriding fresh identity (the bug fixed in [vMCP] identityPropagatingRoundTripper captures stale identity, bypassing per-request upstream token refresh #5323, now covered).
  2. loadUpstreamTokens returning a stale map because UpstreamTokenRefresher is broken.
  3. TokenValidator.Middleware failing to call WithIdentity on the refresh path.

The new test only catches (1). Modes (2) and (3) would still produce the same user-visible symptom.

Proposal

Extend mcp_session_identity_refresh_test.go (or create a sibling test in a higher-level package such as pkg/vmcp/server/...) with an end-to-end case that:

  1. Builds a minimal TokenValidator wired to a fake UpstreamTokenRefresher whose returned tokens differ between the first and second call (simulating transparent refresh).
  2. Constructs a signed JWT carrying a tsid claim that the validator can resolve via the fake UpstreamTokenRefresher.
  3. Issues two requests through the validator's middleware into the backend session.
  4. Asserts the upstream observes the rotated token on the second call.

This is the AC5 acceptance criterion as literally written on #5323. Closing this gap is non-trivial test setup (signed JWT, fake refresher, real middleware wiring), which is why the iteration 2 review allowed deferring it.

Acceptance criteria

Notes

Raised as a MEDIUM finding on the iteration 2 review of #5323. The reviewer noted that either filing this issue or extending the existing test is acceptable; this issue makes the gap visible rather than implicit.

Related: #5323, #3877, #3869

Metadata

Metadata

Assignees

No one assigned

    Labels

    authenticationgoPull requests that update go codevmcpVirtual MCP Server related issues

    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