ADR-0003. Stateless JWT — không có Danh sách Revocation, TTL ngắn + refresh
| Trường | Giá trị |
|---|---|
| Trạng thái | Accepted |
| Ngày | 2026-02-10 |
| Người quyết định | identity-team |
| Thay thế | — |
Bối cảnh
- JWT là claim đã ký; một khi được phát, chúng có hiệu lực đến hết hạn — không có cách nào vô hiệu tức thì mà không cần state.
- Thêm Danh sách Revocation (blocklist) đồng nghĩa mọi sister service phải kiểm tra nó trên mỗi request — phá hỏng mục đích của xác minh stateless.
- Workflow POS cần logout / lockout phản hồi nhanh (admin vô hiệu hoá user → họ phải bị cắt truy cập sớm).
Quyết định
JWT là stateless — không có Danh sách Revocation. Chấp nhận đánh đổi:
- TTL ngắn (mặc định 1 giờ) — phạm vi ảnh hưởng có giới hạn.
- Refresh token xoay vòng khi sử dụng — phiên dài hạn vẫn nhận token mới.
- Lockout / disable cập nhật
User.statusngay lập tức, nhưng người giữ token vẫn còn quyền đến khi hết hạn tự nhiên. Lockout nghiêm trọng (sự cố bảo mật) yêu cầu xoay key.
Hệ quả
| Ưu | Nhược |
|---|---|
| Sister service xác minh tại chỗ không cần shared state | User bị disable vẫn còn quyền tới TTL |
| Không có blocklist tập trung để tham vấn | Lockout nghiêm trọng yêu cầu xoay key JWKS (force-logout mọi người) |
| Mở rộng ngang dễ dàng | "Logout phiên khác" là UX best-effort (token trên trình duyệt vẫn hợp lệ) |
Mẫu giảm thiểu
- Thao tác nhạy cảm (đổi mật khẩu, hạ role) re-fetch trạng thái user và đánh giá lại phân quyền phía server
- TTL ngắn (1h) + refresh khi hoạt động = cửa sổ stale tối đa 1h
- Với sự cố: xoay JWKS keypair → mọi token trở thành không hợp lệ
Phương án đã xem xét
| Phương án | Ưu | Nhược | Lý do từ chối |
|---|---|---|---|
| Token blocklist trên Redis | Revocation tức thì | Sister service phải kiểm tra Redis trên mỗi request — phá hỏng xác minh stateless | Sai layer |
| Reference token (opaque, lưu phía server) | Revocation tức thì | Mỗi request → gọi HTTP đến identity; thảm hoạ latency | Sai trade-off |
| TTL rất ngắn (5min) | Cửa sổ stale nhỏ hơn | Refresh churn quá mức | Chi phí hiệu năng |
Tham chiếu
JWKSIssuerTokenService(cấu hình TTL)AuthenticationService.refreshToken