docs: design for multi-device remember-me tokens

This commit is contained in:
2026-02-28 11:13:22 +01:00
parent 66d04faaa5
commit 20f502543a

View File

@@ -0,0 +1,57 @@
# 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.