# Remember-Me Multi-Device Tokens Design (2026-02-28) ## Context After the security changes on 2026-02-26, remember-me uses a single `users.remember_token` value. This breaks multi-browser usage because each login overwrites the previous token. The goal is to allow unlimited concurrent remember-me sessions across devices and browsers, with retention cleanup for tokens older than 6 months. ## Goals - Allow unlimited concurrent remember-me sessions per user. - Store only hashed tokens in the database. - Keep existing cookie security attributes (`Secure`, `HttpOnly`, `SameSite=Lax`). - Clean up tokens older than 6 months. ## Non-Goals - Reworking the entire authentication system. - Introducing refresh-token or JWT flows. ## Data Model Add a new table `users_remember_tokens`: - `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY - `user_id` INT UNSIGNED NOT NULL, indexed - `token_hash` CHAR(64) NOT NULL, unique - `created_at` DATETIME NOT NULL - `last_used_at` DATETIME NULL - `user_agent` VARCHAR(255) NULL - `ip` VARCHAR(45) NULL Rationale: - Store only `token_hash` (SHA-256 of raw token) to avoid storing bearer tokens in plain text. - Use `last_used_at` for retention and auditing. If null, fall back to `created_at`. ## Login Flow 1. When user logs in with "Zapamiêtaj mnie": - Generate random token (64 hex). - Store `hash = sha256(token)` in `users_remember_tokens` with metadata and timestamps. - Set cookie to the raw token with expiry +1 year and existing security attributes. 2. When user logs in without "Zapamiêtaj mnie": - Do not create a token. - Existing cookie is cleared. ## Auto-Login Flow 1. If no session and cookie exists: - Hash cookie value with SHA-256. - Look up `users_remember_tokens` by `token_hash`. - If found, load user, set session, update `last_used_at`. - If not found, clear cookie. ## Retention - Delete tokens older than 6 months based on `last_used_at` (or `created_at` if `last_used_at` is null). - Trigger cleanup during login and auto-login paths to avoid extra jobs. ## Error Handling - Missing or invalid token in DB results in clearing the cookie and continuing to login screen. - No user row for token is treated as invalid and cleaned. ## Testing - Integration test: login with remember-me sets cookie and inserts token row. - Integration test: auto-login succeeds from cookie after session is cleared. - Retention test: tokens older than 6 months are removed on login.