Access token short-lived (15 phút) gửi trong mỗi request — stateless, server không lưu gì.
- Refresh token long-lived (7-30 ngày) lưu trong httpOnly cookie, chỉ dùng để lấy access token mới tại endpoint
/auth/refresh. - Rotation strategy: mỗi lần dùng refresh token phải issue cặp token mới và invalidate token cũ (one-time-use) — nếu token cũ bị dùng lại là dấu hiệu bị đánh cắp, revoke toàn bộ session.
- Token blacklisting: lưu revoked JTI (JWT ID) trong Redis với TTL bằng thời gian còn lại của token — kiểm tra blacklist trong auth middleware.
- Sliding sessions: mỗi request hợp lệ extend session — issue refresh token mới nếu còn < 1 ngày.
- Security: lưu hash của refresh token trong DB, không plain text — nếu DB leak thì token vô dụng.
Pitfall: không implement rotation → stolen refresh token dùng mãi đến hết hạn; không lưu vào httpOnly cookie → XSS đánh cắp được.