Skip to content

[codex] add generic OAuth broker credential source - #23945

Open
gregm711 wants to merge 2 commits into
NousResearch:mainfrom
gregm711:codex/generic-oauth-broker-source
Open

[codex] add generic OAuth broker credential source#23945
gregm711 wants to merge 2 commits into
NousResearch:mainfrom
gregm711:codex/generic-oauth-broker-source

Conversation

@gregm711

Copy link
Copy Markdown

Summary

Adds a generic oauth_broker credential-pool source so Hermes can use short-lived runtime credentials minted by an external OAuth refresh authority.

This is intentionally platform-agnostic: broker configuration lives on the pool entry (broker_url, optional broker_headers_env, optional broker_subject), and the broker can be any service that owns refresh tokens and returns access credentials.

Closes / follows up on #23944.

What changed

  • agent/credential_pool.py recognizes source: "oauth_broker" for OAuth entries.
  • Broker entries refresh without requiring or persisting a local refresh_token.
  • Hermes honors refresh_after, expires_at, and expires_at_ms for local caching, and calls the broker with force: true during forced credential retry.
  • Added docs for the broker request/response contract.
  • Added focused tests covering initial fetch, cached-token reuse, and forced refresh.

Why

Some OAuth providers issue single-use rotating refresh tokens. Multiple Hermes runtimes holding the same refresh token can consume/rotate it independently and break each other. A broker source lets deployments centralize refresh ownership while Hermes still caches short-lived access tokens locally.

Validation

  • python -m py_compile agent/credential_pool.py
  • scripts/run_tests.sh tests/agent/test_credential_pool.py

Security

Broker-sourced entries never write a refresh token to auth.json. Broker authentication is supplied via an env var containing JSON headers, so deployments can use their own runtime auth mechanism without baking a specific vendor into Hermes.

@gregm711
gregm711 marked this pull request as ready for review May 11, 2026 18:32
@alt-glitch alt-glitch added type/feature New feature or request area/auth Authentication, OAuth, credential pools comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P3 Low — cosmetic, nice to have labels May 11, 2026
…olution

# Conflicts:
#	agent/credential_pool.py
#	tests/agent/test_credential_pool.py

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing the rotating-refresh-token deployment case; current main still lacks this capability.

Problems

  • agent/credential_persistence.py:110 in this PR exempts oauth_broker from main’s fail-closed borrowed-secret boundary. That writes broker-minted access tokens to auth.json, conflicting with the policy introduced by d7c5d5dee and the current unowned-OAuth regression test at tests/agent/test_credential_pool.py:1071-1095.
  • The added HERMES_OAUTH_BROKER_TIMEOUT_SECONDS is a new non-secret behavioral environment variable. AGENTS.md requires this class of setting to use config.yaml; provider timeout resolution already exists in hermes_cli/timeouts.py:14-40.
  • The new guide is not registered in the explicit Guides sidebar list at website/sidebars.ts:684-709.

Suggested changes

  • Retain the broker descriptor while keeping broker-minted tokens runtime-only, and add a no-secret-on-disk regression test.
  • Move the timeout to a config-backed mechanism.
  • Register the guide in the sidebar.

Automated hermes-sweeper review.

return False
if normalized_source == "manual" or normalized_source.startswith("manual:"):
return False
if normalized_source == "oauth_broker":

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oauth_broker is an external credential source, so exempting it here writes its broker-minted access token to auth.json. Main deliberately treats unowned OAuth sources as borrowed and strips both access and refresh tokens (tests/agent/test_credential_pool.py:1071-1095). Please preserve the broker descriptor while keeping minted token material runtime-only instead of bypassing this disk boundary.

Comment thread agent/credential_pool.py
"subject": getattr(entry, "broker_subject", None) or entry.id,
"force": bool(force),
}
timeout_seconds = float(os.environ.get("HERMES_OAUTH_BROKER_TIMEOUT_SECONDS", "20"))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This introduces a new non-secret HERMES_* behavior knob. Project policy requires behavioral configuration in config.yaml; please use a config-backed timeout mechanism instead.

@teknium1 teknium1 added sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/auth Authentication, OAuth, credential pools comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants