Skip to main content

Sessions & refresh

A session in IdentSphere is a row in user_sessions plus a pair of cookies on the client.

Tokens

TokenLifetimeStoragePurpose
Access token15 min defaultidentsphere_at cookie + Authorization headerAuthenticates every request. JWT with sub, org, email, aal, mfa_verified_at claims.
Refresh token30 days defaultidentsphere_rt cookieExchanged at /refresh for a new access token. Opaque; SHA-256 hashed in DB.
CSRF tokenmatches access TTLidentsphere_csrf cookie (not HttpOnly)Double-submit pattern.

Rotation

Refresh tokens rotate on every successful /refresh. The new refresh token replaces the prior one in-place on the user_sessions row. A replayed old refresh token finds no matching row → 401.

In a future version, replay detection will revoke the entire session family.

Revocation

Revocation is soft: the row's revoked flag is set to true. The session-cache stores the revocation signal under IdentSphere:session:revoked:{session_family_id} so the auth middleware sees it on the next request without re-querying.

Revoke a session:

ActionEndpoint
Sign out currentPOST /v1/auth/logout
Sign out one specificDELETE /v1/auth/sessions/:id
Sign out everywhereDELETE /v1/auth/sessions
Sign out everywhere except current (e.g. after password change)Use sign_out_other_sessions: true on POST /v1/users/me/password

Listing

GET /v1/auth/sessions returns active sessions for the caller, marking is_current: true for the one signing the request.

[
{
"id": "...",
"user_agent": "Mozilla/5.0 ...",
"ip_address": "203.0.113.42",
"last_active_at": "...",
"is_current": true,
"created_at": "..."
}
]

Session families

session_family_id groups related sessions. A single session family covers a series of /refresh rotations — same browser, same login, many access tokens over time. Revoking by family revokes the whole chain.

This is the unit of MFA step-up assertions: the step-up TTL is keyed per family.

Last-active tracking

The auth middleware bumps last_active_at on every authenticated request (subject to a short debounce window to avoid one UPDATE per request in hot paths).

DPoP (planned)

The schema already has dpop_thumbprint reserved. DPoP-bound sessions — tokens that only validate when accompanied by a fresh per-request signature from the binding keypair — are planned for a future release.

Idle vs absolute timeout

The SDK enforces only ABSOLUTE timeouts (access_expiry_secs, refresh_expiry_secs). It doesn't enforce idle timeouts. If you want one, implement it client-side or via a middleware that revokes sessions whose last_active_at is older than your idle threshold.

CORS + cookies

Cookie auth across origins requires:

  • Backend sends Set-Cookie with SameSite=None and Secure (toggle via cookies_secure: true).
  • Frontend sends requests with credentials: 'include' (or axios.defaults.withCredentials = true).
  • CORS middleware allows credentials and lists the frontend origin explicitly (no *).