Session Management
Vouch sessions are time-limited, DPoP-bound OAuth 2.0 access tokens (ES256 JWTs per RFC 9068) that prove recent hardware presence verification.
Session Lifecycle
- Creation —
vouch loginperforms FIDO2 assertion with YubiKey touch + PIN - Active — Access token stored in agent memory, valid for 8 hours (default)
- Usage — Credential helpers exchange the access token for service-specific credentials
- Expiry — Session expires automatically after the configured duration
- Revocation —
vouch logoutexplicitly ends the session
Session Duration
Default: 8 hours. Configurable via:
VOUCH_SESSION_HOURS=8
Session Storage
Sessions are stored in multiple locations for different access patterns:
| Location | Purpose | Security |
|---|---|---|
vouch-agent memory | Primary access for CLI and credential helpers | In-process, zeroized on drop |
~/.config/vouch/config.json | Fallback when agent is not running | File permissions 0600 |
~/.local/state/vouch/cookie.txt | Netscape cookie file for curl -b usage | File permissions 0600 |
| Server database | Server-side session record | Token hash stored, not plaintext |
Vouch follows the XDG Base Directory Specification
and honors XDG_CONFIG_HOME, XDG_STATE_HOME, XDG_DATA_HOME, XDG_CACHE_HOME,
and XDG_RUNTIME_DIR on all platforms (including macOS). The paths above show the
defaults when those variables are unset. See
File Locations for the full map and the
automatic migration from the legacy ~/.vouch/ directory.
Server-Side Session Management
Cleanup
Expired sessions are cleaned up automatically by a background task:
# Cleanup interval in minutes (default: 15, set to 0 to disable)
VOUCH_CLEANUP_INTERVAL=15
Security Properties
- Presence-bound — Every session traces to a FIDO2 assertion with user verification
- Time-limited — Sessions cannot be renewed; a new login is required after expiry
- DPoP-bound — Access tokens are bound to the client’s DPoP key; token theft without the key is useless
- Non-transferable — Sessions are bound to the client that created them
- Audience-restricted — Tokens narrowed to a specific resource are rejected at every other resource (see below)
- Audited — Every session creation and usage is logged
Audience Enforcement (RFC 8707 Resource Indicators)
Access tokens carry an aud (audience) claim per RFC 9068. By default the
audience equals the requesting client_id and the token is valid at every
Vouch resource endpoint — this covers all standard flows (vouch login,
browser sessions, device flow, client credentials).
A client may instead narrow a token to a specific resource, either with the
RFC 8707 resource parameter at the authorization endpoint or with the
audience/resource parameters at token exchange (RFC 8693). Vouch’s
resource endpoints (/v1/credentials/*, /v1/keys, /api/v1/*, RFC 7592
client management) enforce that narrowing: a narrowed token is accepted only
when its audience names this deployment (same scheme, host, and port as the
configured base URL) and its path covers the request at a path-segment
boundary. An audience of the deployment root (the base URL itself) covers
every endpoint; {base_url}/v1/keys covers /v1/keys and everything below
it, but nothing else. Requests failing the check receive 401 invalid_token
with the standard WWW-Authenticate challenge, and the rejection is logged
with the client ID, audience, and request path.
Per their RFCs, the authorization-server endpoints remain audience-agnostic:
/oauth/userinfo accepts tokens from any client, /oauth/introspect and
/oauth/revoke answer about any token the server issued, and token exchange
accepts narrowed subject tokens (re-scoping them is its purpose).
Clients registered without resource_uris may request any resource value
at issuance. This is safe under enforcement: a token narrowed to an external
resource server is less usable at Vouch, not more — it can only be spent at
the external service it names. Registering resource_uris additionally
restricts which values a client may request at all.