Stateful Authentication (Session-based) – Server giữ state
-
Server tạo session cho user sau khi đăng nhập và lưu nó trên server (memory/db/Redis).
-
Client nhận session ID thông qua cookie và gửi lại mỗi lần request.
-
Mỗi request được xử lý bằng cách server tra cứu session dựa trên ID đó.
-
Stateful: server cần lưu và quản lý trạng thái đăng nhập.
-
Dễ invalidate (hủy) phiên tại server ngay lập tức.
-
Cookie tự động gửi kèm domain tương ứng.
-
Server kiểm soát hoàn toàn session → dễ revoke khi user logout / thay đổi quyền.
-
Có thể bảo mật hơn nếu dùng cookie HttpOnly (có thể chống XSS).
-
Tốn bộ nhớ server khi nhiều session đồng thời.
-
Khó scale ngang (cluster nhiều instance) nếu không có session store chung như Redis.
-
Load balancing cần “sticky session” hoặc shared session store.
Stateless Authentication (JWT) – Không cần server giữ state
-
Server tạo một JWT chứa thông tin user (claims) sau khi login, ký bằng secret.
-
Client lưu token (ví dụ localStorage / cookie) và gửi mỗi request trong header
Authorization: Bearer ....
-
Server xác thực JWT bằng signature mà không cần tra cứu state.
-
Stateless: server không lưu bất kỳ session nào.
-
Mỗi request mang đủ thông tin để server kiểm tra quyền. 200Lab
-
Rất dễ scale trong kiến trúc phân tán (microservices, nhiều instance).
-
Không cần session store → giảm overhead tra cứu state.
-
Phù hợp với API, SPA, mobile app, hệ thống nhiều domain.
-
Khó revoke token trước khi hết hạn → nếu token bị leak, attacker vẫn dùng tới khi hết hạn.
-
Token thường to hơn session ID → header request lớn hơn.
-
Nếu lưu JWT ở localStorage có thể dễ bị XSS; nếu ở cookie cũng cần config CORS/CSRF cẩn thận.
So sánh
| Tiêu chí | Session (Stateful) | JWT (Stateless) |
| Lưu trạng thái | Server (session store) | Client (token) |
| Server load | Tăng | Thấp |
| Horizontal scaling | Khó hơn (cần shared store) | Rất dễ |
| Revocation | Dễ (xóa session) | Khó (phải dùng blacklist/exp) |
| API / microservices | Kém linh hoạt | Rất phù hợp |
| Cookie tự động gửi | Có | Có (nếu lưu trong cookie) |
| Token trong header | Không | Có thường xuyên |
Use Case – Khi nào dùng Session-based (Stateful)
Web app truyền thống:
-
Monolithic server render (SSR) HTML.
-
Form login / trang nhiều session state.
-
User logout phải hết phiên ngay lập tức. 200Lab
-
Banking / app nhạy cảm muốn chủ động revoke khi password đổi.
-
Dùng cookie HttpOnly chống XSS, tránh JWT lưu localStorage.
-
Dùng Redis cho session store → hợp lý cho app vừa & nhỏ.
Use Case – Khi nào dùng JWT-based (Stateless)
API / Microservices
-
Hệ thống phân tán, nhiều dịch vụ kiểm tra auth độc lập.
-
Frontend dễ tách khỏi backend → token phù hợp.
-
JWT theo chuẩn bearer, dễ gửi đi khắp nơi hơn cookie domain.
-
Không cần session store, chỉ cần verify token → scale lên nhiều instance.
Nếu app của bạn cần kiểm soát chặt trạng thái người dùng → Session-based
Nếu bạn đang xây API / hệ phân tán lớn → JWT-based
Không có lựa chọn hoàn hảo, chỉ có lựa chọn phù hợp với bài toán + kiến trúc.
Use case – Revoke JWT token ở device khác làm sao?
JWT stateless ⇒ Server không biết:
-
User đang login ở bao nhiêu device
-
Token nào đang active
-
Token nào cần bị revoke ngay
-
Không thể revoke sớm
-
Không logout toàn bộ device được
Kết hợp JWT + server-side session metadata (hybrid)
Solution 1 JWT + Session Store
-
Mỗi lần login → tạo session_id
-
Lưu session vào DB / Redis
-
JWT chứa
sid
-
Mỗi request:
Logout 1 device Delete session_id
Logout all devices Delete all sessions of user
-
Revoke ngay
-
List được user login ở đâu
-
Không còn stateless 100%
Solution 2 Access Token ngắn hạn + Refresh Token
-
Access token sống ngắn (5–15 phút)
-
Refresh token sống lâu lưu server-side
⇒ Access token tự hết hạn sau vài phút
-
Scale tốt, Giảm rủi ro token leak, Ít DB query hơn Solution 1
-
Không revoke ngay tức thì