Refresh Tokens
Data Entity
Description
Stores OAuth 2.0 refresh tokens issued to authenticated users, enabling silent token rotation and persistent sessions across mobile and web clients without requiring re-authentication.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Unique identifier for the refresh token record | PKrequiredunique |
user_id |
uuid |
Foreign key referencing the user who owns this refresh token | required |
session_id |
uuid |
Foreign key referencing the session this refresh token belongs to | required |
token_hash |
string |
SHA-256 hash of the actual refresh token value; the plaintext token is never stored | requiredunique |
token_family |
uuid |
Groups tokens in a rotation chain; if a token from a revoked family is reused, the entire family is invalidated to detect token theft | required |
device_id |
string |
Unique device fingerprint or identifier to bind the token to a specific device | - |
device_name |
string |
Human-readable device name for display in session management UI | - |
platform |
enum |
Client platform that issued the token | required |
ip_address |
string |
IP address of the client at token issuance, stored for audit and anomaly detection | - |
user_agent |
text |
User-Agent header of the client at token issuance for device identification | - |
issued_at |
datetime |
Timestamp when the refresh token was created | required |
expires_at |
datetime |
Absolute expiration timestamp after which the token is invalid regardless of activity | required |
last_used_at |
datetime |
Timestamp of the most recent token refresh using this token | - |
revoked_at |
datetime |
Timestamp when the token was explicitly revoked; null if still active | - |
revocation_reason |
enum |
Reason for token revocation, used for audit and security analysis | - |
is_revoked |
boolean |
Quick-check flag indicating whether this token has been revoked | required |
replaced_by_token_id |
uuid |
Points to the new refresh token that replaced this one during rotation; enables chain tracing | - |
organization_id |
uuid |
Organization context at token issuance for multi-tenant scoping and audit | required |
created_at |
datetime |
Record creation timestamp | required |
updated_at |
datetime |
Record last-update timestamp | required |
Database Indexes
idx_refresh_tokens_token_hash
Columns: token_hash
idx_refresh_tokens_user_id
Columns: user_id
idx_refresh_tokens_session_id
Columns: session_id
idx_refresh_tokens_token_family
Columns: token_family
idx_refresh_tokens_expires_at
Columns: expires_at
idx_refresh_tokens_user_active
Columns: user_id, is_revoked, expires_at
idx_refresh_tokens_org_id
Columns: organization_id
Validation Rules
token_hash_format
error
Validation failed
token_hash_uniqueness
error
Validation failed
expires_at_future
error
Validation failed
user_exists_and_active
error
Validation failed
session_exists
error
Validation failed
platform_enum_validation
error
Validation failed
revocation_immutability
error
Validation failed
ip_address_format
warning
Validation failed
organization_id_matches_user
error
Validation failed
Business Rules
token_rotation_on_refresh
Every time a refresh token is used, the old token is revoked and a new token is issued within the same token_family. The old token's replaced_by_token_id is set to the new token's ID.
token_family_revocation_on_reuse
If a revoked refresh token is presented for use, all tokens in the same token_family are immediately revoked. This detects token theft where an attacker replays an old token after the legitimate client has already rotated.
absolute_expiration_enforcement
Refresh tokens have an absolute expiration (e.g., 30 days for mobile, 7 days for web). Expired tokens cannot be used regardless of activity. Users must re-authenticate after expiration.
revoke_all_on_password_change
When a user changes their password, all active refresh tokens for that user are revoked with reason 'password_change', forcing re-authentication on all devices.
revoke_all_on_role_change
When a user's roles are modified via role assignment, all active refresh tokens are revoked with reason 'role_change' to force JWT claims refresh with updated permissions.
concurrent_session_limit
Enforce a maximum number of active sessions per user (e.g., 5). When the limit is exceeded, the oldest session's refresh tokens are revoked with reason 'session_limit_exceeded'.
revoke_on_account_deactivation
When an admin deactivates a user account, all refresh tokens for that user are revoked immediately with reason 'account_deactivated'.
tenant_scoped_token_issuance
Refresh tokens are always issued with the organization_id from the user's account. Token validation must verify organization context matches the requesting context.
expired_token_cleanup
Expired and revoked refresh tokens older than the retention period are periodically purged to prevent table bloat. Archived to audit storage before deletion.