Files
hermes-agent/website/docs/user-guide/features
Teknium d9e88e19e2 feat(mcp): bind stored OAuth refresh tokens to their issuer
Port from openai/codex#39615: the authorization server discovered for an
MCP server can change (protected-resource metadata edit, server
migration, DNS takeover). Without binding, Hermes would send the stored
refresh token to whatever issuer the server now advertises — handing a
long-lived credential to a different authorization server.

- HermesTokenStorage records hermes_issuer alongside cached tokens
  (stripped before OAuthToken.model_validate; never sent on the wire).
- Both provider classes (tools/mcp_oauth.py legacy path and
  tools/mcp_oauth_manager.py managed path) stamp the discovered issuer
  on every token save and enforce the binding on _initialize.
- On mismatch: refresh token is stripped from memory and disk; the
  unexpired access token keeps working; full re-auth happens at expiry.
- Legacy token files without an issuer adopt the current one once
  (no forced re-login for existing installs — deliberate divergence
  from Codex, which requires reauth).

Validated: 12 new tests + 163 existing MCP OAuth tests green; sabotage
run confirms the new tests fail without the enforcement; E2E against
the real manager provider class with a temp HERMES_HOME confirms
mismatch strips and match preserves.
2026-09-13 20:43:33 -07:00
..