Session Refresh
After bootstrap, the agent’s owner session holds SSO tokens including a refresh_token. The refresh command rotates the access_token and id_token (and the refresh_token if the authorization server rotates it) without requiring any human interaction. The refresh keeps the session DPoP-bound: the SSO threads the original token family’s dpop_jkt through every rotation, so the new id_token carries the same cnf.jkt.
Transparent Refresh (the common path)
You rarely need to call refresh directly. Every per-plugin CLI calls SignatureEngine.ensureValidSession() internally before it signs anything, so the access_token is renewed on demand. For example, generating a DPoP header for a service request transparently refreshes an expired session first:
node plugins/agent-id-auth/bin/cli.mjs header --url https://service.example.com/api/whoamiThe same transparent refresh happens inside agent-id-git commit, agent-id-auth call, and any other signing operation. A signing CLI that fails to refresh warns and then proceeds if a usable session still exists — it does not hard-fail on a transient refresh error.
Explicit Refresh
To force a refresh and inspect the result:
node plugins/agent-id-core/bin/cli.mjs refreshReturns:
{
"ok": true,
"refreshedAt": 1700000000000,
"ownerSessionSub": "0x…",
"providerAddress": "0x…"
}On refresh, the rotated id_token is re-verified before it is persisted: its signature, sub, and cnf.jkt are checked, and a sub that no longer matches the bound owner is rejected with a subject-mismatch error. This catches a misbehaving authorization server that rotates the subject or the key binding.
Revocation
If the human revokes the agent’s authorization via the Alien App, the authorization server rejects the refresh token. The refresh command surfaces this as an auth-revoked error (driven by an invalid_grant / 401 / 403 from the token endpoint), and the agent must re-bootstrap to obtain a new session.
Pre-Cutover Sessions Need a Rebind, Not a Refresh
A refresh can only preserve a binding that already exists. A pre-cutover id_token — one minted before the DPoP/cnf cutover, or by a client that never sent dpop_jkt when it authorized — has no cnf.jkt and is not DPoP-bound. Refresh cannot fix this: because the SSO threads the original family’s (NULL) dpop_jkt through every rotation, that family’s refreshes return cnf-less id_tokens forever.
The recovery path is a rebind — a fresh authorization flow that produces a new token family whose dpop_jkt is set. This preserves the agent keypair (so existing signed commits stay valid) and only rewrites the session state:
node plugins/agent-id-core/bin/cli.mjs setup-owner-session --provider-address <addr>A full bootstrap achieves the same rebind. You will hit this case if status reports a bound session but verification complains about a missing cnf.jkt.
Next Steps
- External Services Auth — Use refreshed sessions for service authentication
- CLI Reference — Full refresh command reference