ADR-0003. JWT phi trạng thái - không có danh sách thu hồi, TTL ngắn + refresh
| Trường | Giá trị |
|---|---|
| Trạng thái | Accepted |
| Ngày | 2026-02-10 |
| Người quyết định | Phat Nguyen |
| Thay thế | - |
Bối cảnh
- JWT là các claim đã ký; một khi được phát, chúng có hiệu lực đến khi hết hạn - không có cách nào vô hiệu tức thì mà không lưu trạng thái.
- Thêm danh sách thu hồi (blocklist) đồng nghĩa mọi service anh em phải kiểm tra nó trên mỗi request - phá hỏng mục đích của xác minh phi trạng thái.
- Quy trình POS cần đăng xuất / khoá 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à phi trạng thái - không có danh sách thu hồi. 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.
- Khoá / vô hiệu hoá 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. Việc khoá nghiêm trọng (sự cố bảo mật) yêu cầu xoay khoá.
Hệ quả
| Ưu | Nhược |
|---|---|
| Service anh em xác minh tại chỗ không cần trạng thái dùng chung | User bị vô hiệu hoá vẫn còn quyền cho tới hết TTL |
| Không có blocklist tập trung để tham vấn | Khoá nghiêm trọng yêu cầu xoay khoá JWKS (buộc đăng xuất mọi người) |
| Mở rộng ngang dễ dàng | "Đăng xuất phiên khác" chỉ là trải nghiệm nỗ lực tối đa (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) tải lại 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ổ dữ liệu cũ tối đa 1h
- Với sự cố: xoay cặp khoá JWKS → 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 | Thu hồi tức thì | Service anh em phải kiểm tra Redis trên mỗi request - phá hỏng xác minh phi trạng thái | Sai tầng |
| Token tham chiếu (opaque, lưu phía server) | Thu hồi tức thì | Mỗi request → gọi HTTP đến identity; thảm hoạ độ trễ | Sai đánh đổi |
| TTL rất ngắn (5 phút) | Cửa sổ dữ liệu cũ nhỏ hơn | Refresh quá nhiều lần | Chi phí hiệu năng |
Tham chiếu
JWKSIssuerTokenService(cấu hình TTL)AuthenticationService.refreshToken