security: prevent re-use of refresh token (reduce surface for any stolen token)
Security: session hardening Refresh token rotation with theft detection (family_id) - Added family_id column to auth.sessions (migration 20260507000000_session_family.sql) grouping all tokens issued from the same login into a family - On refresh, the new session inherits the parent's family_id - If a revoked token is replayed (indicates the token was stolen after rotation), the entire family is immediately invalidated and a warning is logged — forcing re-authentication on all devices SameSite=Strict on refresh cookie - Access cookie stays SameSite=Lax (needed for top-level navigation) - Refresh cookie upgraded to SameSite=Strict — it is only ever used for explicit POST to /api/auth/refresh, never via cross-site navigation Refresh token TTL: 30 days → 7 days - With rotation, active sessions auto-renew and effectively never expire - Inactive sessions expire after 7 days instead of 30, reducing the theft window
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
-- Add token family tracking to sessions.
|
||||
--
|
||||
-- family_id groups all refresh tokens issued from the same original login.
|
||||
-- When a rotation detects a revoked token being replayed (possible theft),
|
||||
-- the entire family is invalidated — forcing re-authentication on all devices
|
||||
-- that shared that login event.
|
||||
--
|
||||
-- Existing sessions are seeded with family_id = id (each is its own family).
|
||||
|
||||
ALTER TABLE auth.sessions
|
||||
ADD COLUMN family_id UUID;
|
||||
|
||||
UPDATE auth.sessions
|
||||
SET family_id = id;
|
||||
|
||||
ALTER TABLE auth.sessions
|
||||
ALTER COLUMN family_id SET NOT NULL;
|
||||
|
||||
CREATE INDEX idx_sessions_family_id ON auth.sessions(family_id);
|
||||
Reference in New Issue
Block a user