Authentication Session
Data Entity
Description
Tracks active authentication sessions for users, including JWT tokens issued by Supabase Auth after login via email/password, BankID, or Vipps. Sessions include auth provider metadata, expiry timestamps, and are referenced during biometric re-authentication.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Primary key — unique session identifier, generated on session creation by Supabase Auth | PKrequiredunique |
user_id |
uuid |
Foreign key referencing users.id — the authenticated user this session belongs to | required |
token |
text |
JWT access token issued by Supabase Auth. Contains sub (user_id), role, org_id claims. Stored encrypted at rest. Never logged or exposed in API responses. | requiredunique |
refresh_token |
text |
Opaque refresh token used to obtain a new JWT without re-authentication. Rotated on every use. Stored in Flutter Secure Storage on device, reference hash kept server-side. | unique |
auth_provider |
enum |
The authentication method used to create this session | required |
created_at |
datetime |
UTC timestamp when the session was created. Used for audit trails and session age calculations. | required |
expires_at |
datetime |
UTC timestamp when the JWT access token expires. Default: created_at + 1 hour (Supabase default). Extended sessions for biometric flows may use longer TTL. | required |
is_active |
boolean |
Whether this session is currently valid and usable. Set to false on logout, token revocation, password change, or admin revocation. Does not auto-update on expiry — use expires_at for expiry checks. | required |
device_id |
string |
Stable device identifier (e.g., Flutter device_info platform ID). Used to correlate sessions per device and limit concurrent active sessions per device. | - |
device_name |
string |
Human-readable device label (e.g., 'iPhone 15 Pro'). Displayed in active session management UI for user transparency. | - |
ip_address |
string |
IP address of the client at session creation time. Used for anomaly detection and audit logging. IPv4 or IPv6. | - |
user_agent |
text |
HTTP User-Agent string from the initial authentication request. Useful for audit and fraud detection. | - |
revoked_at |
datetime |
UTC timestamp when the session was explicitly revoked (logout, admin action, password reset). Null if session expired naturally or is still active. | - |
revocation_reason |
enum |
Reason the session was revoked, for audit purposes | - |
last_used_at |
datetime |
UTC timestamp of the most recent authenticated request using this session token. Updated on each API call. Used to detect and clean up idle sessions. | - |
is_biometric_session |
boolean |
True if this session was initiated or re-authenticated via biometric (Face ID / fingerprint) without a full BankID/Vipps re-flow. Used to determine whether sensitive operations require step-up authentication. | required |
bankid_token_claims |
json |
Parsed BankID ID token claims (e.g., sub, pid, acr) stored at session creation for audit and compliance. Only populated when auth_provider = 'bankid'. PII — restricted access via RLS. | - |
vipps_token_claims |
json |
Parsed Vipps ID token claims (e.g., sub, phone_number, nnin) stored at session creation. Only populated when auth_provider = 'vipps'. PII — restricted access via RLS. | - |
Database Indexes
idx_auth_sessions_user_id
Columns: user_id
idx_auth_sessions_user_active
Columns: user_id, is_active
idx_auth_sessions_token
Columns: token
idx_auth_sessions_refresh_token
Columns: refresh_token
idx_auth_sessions_expires_at
Columns: expires_at
idx_auth_sessions_provider
Columns: auth_provider
idx_auth_sessions_device_id
Columns: user_id, device_id
Validation Rules
token_format_valid
error
Validation failed
expires_at_future_on_create
error
Validation failed
user_id_references_existing_user
error
Validation failed
auth_provider_claim_consistency
error
Validation failed
revocation_fields_consistent
error
Validation failed
device_id_format
warning
Validation failed
last_used_at_not_in_future
error
Validation failed
rls_self_read_only
error
Validation failed
Business Rules
single_active_session_per_device
A user may not have more than one active session per device_id. On new login from the same device, the existing session for that device must be revoked (revoked_at set, is_active = false) before the new session is created.
biometric_session_requires_prior_full_auth
A session with is_biometric_session = true can only be created if the user has a prior non-biometric session (auth_provider in ['email_password', 'bankid', 'vipps']) that was created on the same device_id within the biometric enrollment window. Prevents biometric sessions from being bootstrapped without a full auth flow.
session_revoked_on_password_reset
All active sessions for a user must be revoked when a password reset is completed. Prevents stolen session tokens from remaining valid after a security event.
step_up_required_for_sensitive_operations
Sessions where is_biometric_session = true are not permitted to perform sensitive operations (e.g., viewing BankID/Vipps claims, initiating encrypted assignment decryption, modifying payment details) without a step-up re-authentication via BankID or Vipps. The consuming component must check this flag before proceeding.
bankid_vipps_claims_immutable
bankid_token_claims and vipps_token_claims are write-once fields set at session creation and must never be updated. These are audit records of what the identity provider attested at login time.
max_concurrent_active_sessions
A user may not have more than 5 concurrent active sessions across all devices. If this limit is reached, the oldest active session (by created_at) is automatically revoked before the new one is created.
admin_session_revocation
Administrators may revoke any user's session via Admin Portal. Revocation sets is_active = false, revoked_at = now(), revocation_reason = 'admin_revocation'. The affected user's next request will receive a 401 and must re-authenticate.
refresh_token_rotation
Refresh tokens are single-use. When a refresh token is exchanged for a new JWT, the old refresh_token value is immediately invalidated (set to null or replaced) and a new token is stored. Reuse of a revoked refresh token triggers immediate full session revocation (security event).
CRUD Operations
Storage Configuration
Entity Relationships
A user may have multiple active sessions across different devices and auth providers