- Hexagonal identity module: domain ports, use cases, argon2id hasher, pg repos - Migration 002_identity: identity_users + identity_sessions (token hash only) - Opaque 512-bit session tokens; DB stores SHA-256 hash; 7-day TTL in SQL - Cookie HttpOnly + Secure (COOKIE_SECURE, default true) + SameSite=Lax - LoginRateLimiter: 10 failures -> 429 + Retry-After, 15-min cooldown - Anti-enumeration: identical generic 401 + dummy-hash timing equalization - buildApp gains optional pool/cookieSecure; foundation-only app preserved - 47 unit + 14 integration tests; live smoke covers all acceptance criteria
1.7 KiB
1.7 KiB
SPEC — F-005 Identity: register, login, sessions
Problem
Customers need accounts; nothing trusts who calls the API.
Goal
Registration, login, logout with hashed passwords and secure sessions — server is the only authority for identity (never trust the frontend).
Scope IN
src/modules/identitywith hexagonal layers: domain / application / infrastructure / api- Register, login, logout use cases over PostgreSQL (source of truth)
- Argon2id password hashing (OWASP parameters)
- Server-side opaque sessions stored in DB; cookie carries a random token, DB stores only its SHA-256 hash
- Secure session cookie: HttpOnly, Secure, SameSite
- Login rate limiting (10 consecutive failures -> 429 with cooldown) behind an interface
- Migration 002_identity (identity_users, identity_sessions) with down
- Config: COOKIE_SECURE flag (default true)
Scope OUT
- No MFA, no OAuth providers, no profile editing
- No email verification flow, no password reset
- No distributed rate limiting (in-memory per instance; documented)
- No expired-session sweeper (follow-up)
Acceptance criteria
- Given valid credentials When login Then HTTP 200 and secure session cookie set.
- Given wrong password When login Then HTTP 401 and no user enumeration hint (unknown email returns the identical 401).
- Passwords stored with argon2, never plaintext or reversible.
- Given 10 failed logins in a row When next login attempted Then HTTP 429.
- Session cookie is HttpOnly, Secure and SameSite.
./scripts/verify.shgreen.
Dependencies added
- argon2 (canonical Argon2id implementation; PHC string output)
- @fastify/cookie (explicit setCookie/clearCookie; official Fastify plugin)
Justification goes to
spec/tech.md.