Session
Data Entity
Description
Represents an authenticated user session. Tracks active login contexts across mobile (JWT Bearer) and admin portal (HTTP-only cookie) clients, including device identity, authentication method, expiry, and revocation state. Supports multi-device sessions per user and administrator-initiated forced logout.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Primary key. Unique session identifier. | PKrequiredunique |
user_id |
uuid |
Foreign key to users. The authenticated user who owns this session. | required |
token_hash |
string |
SHA-256 hash of the JWT access token or session cookie value. Never stored in plaintext. Used for token lookup and revocation checks. | requiredunique |
refresh_token_hash |
string |
SHA-256 hash of the refresh token. Null for sessions that do not support token refresh (e.g., short-lived BankID sessions). | unique |
auth_method |
enum |
The authentication mechanism used to establish this session. | required |
client_type |
enum |
The type of client that created the session. Determines token transport (Bearer header vs HTTP-only cookie). | required |
device_name |
string |
Human-readable device label (e.g. 'iPhone 14 – Marius', 'Chrome on MacBook'). Populated from user-agent or device metadata at login time. Shown in the Session Management admin page. | - |
device_fingerprint |
string |
Stable device identifier derived from platform metadata. Used to detect session reuse across different devices and flag anomalies. | - |
ip_address |
string |
IP address at session creation. IPv4 or IPv6. Used for security audit and anomaly detection. | - |
user_agent |
string |
Raw User-Agent header string at session creation. Used for device type classification and security monitoring. | - |
organization_id |
uuid |
The organization context active when this session was created. Null for global admins who have no org context. Used for tenant-scoped permission evaluation. | - |
active_role |
string |
The role slug active at session creation (e.g. 'peer_mentor', 'coordinator', 'org_admin', 'global_admin'). Updated when the user switches roles via Profile Switching. Used by RBAC middleware on every request. | required |
is_active |
boolean |
Whether the session is currently valid and usable. Set to false on logout, forced revocation, or token expiry cleanup. | required |
created_at |
datetime |
Timestamp when the session was established (login event). | required |
last_active_at |
datetime |
Timestamp of the most recent authenticated API request using this session. Updated on every successful token validation. Used to enforce inactivity timeout. | required |
expires_at |
datetime |
Absolute expiry timestamp for the session. After this point, the session is invalid regardless of activity. Mobile sessions: 30 days from creation. Web admin sessions: 8 hours. | required |
revoked_at |
datetime |
Timestamp when the session was explicitly revoked (forced logout by admin or user). Null if the session expired naturally or was deactivated on logout. | - |
revoked_by_user_id |
uuid |
ID of the administrator or the session owner who revoked this session. Null for natural expiry. Supports audit trail for forced logouts. | - |
metadata |
json |
Flexible JSON bag for session-specific context: BankID session reference ID, Vipps sub claim, passkey credential ID, or other auth-method-specific identifiers not warranting dedicated columns. | - |
Database Indexes
idx_sessions_user_id
Columns: user_id
idx_sessions_token_hash
Columns: token_hash
idx_sessions_refresh_token_hash
Columns: refresh_token_hash
idx_sessions_user_active
Columns: user_id, is_active
idx_sessions_expires_at
Columns: expires_at
idx_sessions_organization_id
Columns: organization_id
idx_sessions_last_active_at
Columns: last_active_at
Validation Rules
expires_at_in_future
error
Validation failed
user_id_must_exist
error
Validation failed
token_hash_unique
error
Validation failed
revocation_is_irreversible
error
Validation failed
valid_auth_method
error
Validation failed
valid_active_role
error
Validation failed
ip_address_format
warning
Validation failed
Business Rules
session_expiry_enforcement
Sessions with expires_at in the past MUST be treated as invalid on every token validation. The rbac-middleware checks expires_at before processing any authenticated request. Expired sessions cannot be reactivated; a new login is required.
inactivity_timeout
Web admin sessions idle for more than 60 minutes (no last_active_at update) are automatically marked is_active=false. Mobile sessions have a 30-day inactivity window. A scheduled cleanup job enforces this.
token_hash_only_storage
Raw JWT tokens and refresh tokens are NEVER stored in the database. Only SHA-256 hashes are persisted. The auth-service performs hashing before creating or updating session records.
forced_revocation_propagation
When an admin revokes a session via the Session Management page, is_active is set to false and revoked_at/revoked_by_user_id are recorded immediately. The next API call from that client receives a 401 response. No grace period.
role_context_consistency
The active_role on the session must always correspond to a role the user actually holds in the given organization_id. When a user switches roles via Profile Switching, the session's active_role is updated atomically to prevent privilege escalation.
global_admin_no_org_context
Sessions created for users with role 'global_admin' MUST have organization_id = null. Any attempt to set an organization_id for a global admin session is rejected.
audit_all_revocations
Every forced session revocation (admin-initiated or system-initiated) generates an audit_logs entry with the acting user ID, target user ID, session ID, and reason. Natural expiry does not produce an audit record.
single_session_per_device_fingerprint
If a new session is created with the same device_fingerprint as an existing active session for the same user, the prior session is automatically invalidated (is_active=false). Prevents silent duplicate sessions from the same device after reinstall.