Skip to content

Sessions and logout

Platform sessions live in Postgres, not in a signed cookie. That is what makes them listable and revocable: an administrator can end a session immediately rather than waiting for a token to expire.

The cookie value is stored only as a hash, and is scoped to the tenant host — a session established on acme.oauth.work belongs to acme.oauth.work.

The signed-in user’s own sessions:

GET /sessions
Cookie: <tenant session>
{
"sessions": [
{
"session_id": "sess_…",
"amr": ["pwd", "totp"],
"ip": "203.0.113.4",
"user_agent": "Mozilla/5.0 …",
"created_at": 1750000000000,
"expires_at": 1752592000000,
"current": true
}
]
}

Only live sessions are listed — revoked and expired ones are filtered out. amr shows how each session was established, so a user can see which of their sessions used a second factor.

POST /sessions/:id/revoke # end one device
POST /sessions/revoke_others # keep this one, end everything else

revoke_others is the “you left a laptop somewhere” control: it returns the number revoked and leaves the current session intact.

{ "ok": true, "revoked": 3 }

These are same-origin, cookie-backed endpoints — see authentication.

The administrative counterpart, through the management API:

GET /v1/organizations/org_01J…/users/usr_…/sessions
POST /v1/organizations/org_01J…/users/usr_…/sessions/revoke
Authorization: Bearer sk_live_…

This is what you call when an employee is terminated, a device is lost, or an account is suspected compromised. Revocation takes effect on the next request — not at TTL expiry — so a signed-in session stops working immediately rather than lingering for the rest of its lifetime.

SCIM deprovisioning has the same effect: deactivating a user in the customer’s directory kills their sessions on the next request.

Each revocation writes a session_revoked audit event.

Revoking a session ends the browser session. It does not, by itself, invalidate access tokens already issued to applications — those are signed JWTs with their own lifetime.

For a complete cut-off:

  1. Revoke the sessions (above) — stops new authorizations.
  2. Revoke the tokens — denylists live access tokens and kills refresh tokens.

Access tokens live an hour, so waiting them out is often acceptable. When it is not — a termination, a confirmed compromise — do both.

/logout is the OIDC end_session_endpoint and ends one session. See OIDC for the post-logout redirect rules, which are strict: an unregistered or unverifiable redirect target is simply not followed.