stacklok / stacklok/toolhive

[vMCP] Proactive auth credential refresh via per-request identity resolution (Phase 2)

Open
#3,877 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

Depends on #3869

This is the Phase 2 follow-up to #3869 (auth credential expiration with retry). Phase 1 handles stale credentials reactively (detect 401/403, recreate client). This issue eliminates the problem proactively by resolving credentials on every operation rather than at client creation time.

Context: With session-scoped clients, outgoing credentials are resolved once during SessionFactory.MakeSession() and held for the session lifetime. Short-lived credentials (OAuth tokens, expiring API keys) can become stale mid-session, triggering the retry path in #3869. This issue removes that failure mode entirely for credentials with a known expiry.

Implementation:

Part 1 — Per-request identity resolution:

  • Modify identityPropagatingRoundTripper in pkg/vmcp/client/client.go to read identity from the request context on each operation, instead of capturing it at client creation time
  • This ensures every backend call automatically picks up the latest credentials without any expiry tracking logic
  • Eliminates stale credential issues entirely for backends that return fresh credentials on each resolution

Part 2 — Proactive client recreation for known-expiry credentials:

  • For credentials that carry an explicit expiry (JWT exp claim, OAuth expires_in response field), schedule proactive client recreation shortly before the expiry time
  • This avoids the reactive retry path in #3869 for these credential types — the client is already fresh before the first 401 occurs
  • Proactive recreation should use the same singleflight deduplication as #3869 to handle concurrent requests during the recreation window
Acceptance Criteria
  • identityPropagatingRoundTripper resolves identity from the request context on each operation rather than capturing it at construction time
  • Backends that return fresh credentials on each resolution never trigger the reactive retry path from #3869
  • For credentials with a known expiry (exp claim or expires_in), proactive recreation is scheduled before the expiry time
  • Proactive recreation uses singleflight to deduplicate concurrent requests during the recreation window
  • Proactive recreation does not block in-flight requests — existing clients remain usable until replaced
  • No credentials are logged or stored beyond what is required for the current request
  • Unit tests cover: per-request identity resolution picks up updated credentials, proactive recreation fires before expiry, concurrent requests during recreation window are deduplicated
  • Integration tests cover: full request lifecycle with short-lived credentials, no 401s observed when proactive refresh is working correctly

RFC: THV-0038 — Session-scoped client lifecycle

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

Start in pkg/vmcp/client/client.go at identityPropagatingRoundTripper, then read the linked Phase 1 issue #3869 and RFC THV-0038 for the session-scoped client lifecycle. Done means per-request identity resolution, expiry-aware proactive recreation with singleflight, non-blocking replacement, and the listed unit and integration coverage without unnecessary credential retention.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
authentication, backend, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.