Appearance
Session Management & Device Tracking
Overview
Sessions are the control plane for auth state.
- Every issued access token references a session ID.
- Every issued refresh token is bound to a session.
- Revoking a session immediately invalidates access checks and refresh rotation for that session.
Architecture
Session Entity
A Session represents one active login on one device fingerprint.
- Device identity is a SHA-256 hash of the raw user-agent string (
deviceFingerprint). - Same physical device with different browsers is treated as different sessions.
- One session can have many refresh tokens over time because of rotation.
Data Model
identity.sessions table:
| Column | Type | Description |
|---|---|---|
id | uuid PK | Session ID |
subject_id | uuid | User or Client ID |
subject_type | varchar | 'user' or 'client' |
agency_id | uuid (nullable) | Agency context |
ip_address | varchar | Last known IP |
user_agent | text | Raw user-agent string |
device_fingerprint | varchar | SHA-256 of user-agent |
device_type | varchar (nullable) | desktop, mobile, tablet |
browser | varchar (nullable) | Example: "Chrome 120.0" |
os | varchar (nullable) | Example: "Windows 11" |
location | jsonb (nullable) | Geolocated city/region/country |
last_active_at | timestamptz | Updated on login/refresh |
revoked_at | timestamptz (nullable) | Set when session is revoked |
identity.refresh_tokens:
session_idis required for newly issued tokens.- Refresh token rows always point to the session used for issuance/rotation.
Login and Session Issuance Flow
- The API extracts device info (IP + user-agent).
- Geolocation is resolved from IP when available.
- The adapter parses user-agent to fingerprint/device metadata.
- The adapter tries to find an active session by
(subjectId, subjectType, fingerprint). - If found, session activity is refreshed (
lastActiveAt, IP/location). - If not found, a new session is created.
- If active session count is already 10, the oldest active session is revoked first.
- A new access token and refresh token are issued for that session ID.
Session Management Endpoints
| Method | Path | Auth | Purpose |
|---|---|---|---|
GET | /api/identity/auth/sessions | @Auth | List active sessions with isCurrent |
GET | /api/identity/auth/sessions/current | @Auth | Read the current authenticated session |
POST | /api/identity/auth/sessions/revoke | @Auth | Revoke a specific own session |
POST | /api/identity/auth/sessions/revoke-others | @Auth | Revoke all own sessions except current |
POST | /api/identity/auth/logout | Authenticated | Revoke current session and its refresh tokens |
Security Behaviors
- Logout revokes the authenticated current session and all refresh tokens in that session.
GET /api/identity/auth/sessions/currentuses the active access token'ssessionIdclaim and does not mutate the session.- Password change revokes all other active sessions, revokes current-session refresh tokens, and returns a newly issued token pair for the current session.
- For users with active 2FA methods, password change also requires a valid second factor before the command runs.
- Refresh-token reuse detection revokes all sessions for the subject.
- Access token auth (
jwt-access) validates that the referenced session exists and is active.
Scope
- Users: full support (session lifecycle + new device notifications).
- Clients: full support (session lifecycle, no new device email notification).
Migration Notes
If your environment still has historical refresh tokens without session_id, users may need to sign in again after deployment. Generate and run your own identity migration to enforce the final DB constraint in your environment.