Cả 3 đều là cơ chế giữ "ai đang gọi API", chọn cái nào tuỳ vào kiểu client và tuổi thọ phiên.
Session cookie (mặc định của Django): server giữ state, cookie chỉ giữ session key. Hợp nhất cho browser app cùng domain. Logout server-side dễ (chỉ cần xoá session row), nhưng cần CSRF protection và khó scale cross-domain/mobile. Token (DRF TokenAuthentication): mỗi user 1 token lưu DB, gửi qua Authorization: Token <key>. Hợp với mobile app, internal service đơn giản. Revoke dễ, nhưng không expire mặc định — phải tự code rotation. JWT (vd djangorestframework-simplejwt): self-contained, ký bằng SECRET_KEY hoặc keypair. Hợp với SPA + mobile + microservice vì server không cần tra DB mỗi request. Đổi lại: khó revoke (phải maintain blacklist), payload bị lộ nếu không HTTPS, và SECRET_KEY leak là vỡ trận.
# settings.py — DRF với simplejwt
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=15),
'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
'ROTATE_REFRESH_TOKENS': True,
'BLACKLIST_AFTER_ROTATION': True,
}Một hiểu lầm phổ biến: JWT không phải "advanced version" của session, chỉ là trade-off khác.
- Browser app cùng domain mà chọn JWT lưu localStorage là tự tạo XSS risk; cookie HttpOnly + session vẫn là lựa chọn an toàn nhất.
- Chỉ chọn JWT khi thực sự cần stateless hoặc cross-service.
All three identify "who is calling the API". Choose by client type and session lifetime:
- Session cookie (Django default): server holds state, the cookie holds the session key. Browser app on the same domain → the best option. Server-side logout is easy (delete the session row). Needs CSRF protection. Hard to scale across domains/mobile.
- Token (DRF
TokenAuthentication): one token per user in the DB, sent asAuthorization: Token <key>. Mobile apps, simple internal services. Easy to revoke (delete the row). Does not expire by default — you must code rotation. - JWT (e.g.
djangorestframework-simplejwt): self-contained, signed withSECRET_KEYor a keypair. SPA + mobile, microservices — server skips the DB lookup per request. Hard to revoke (must blacklist), payload is visible without HTTPS, a secret leak is game-over.
# settings.py — DRF with simplejwt
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=15),
'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
'ROTATE_REFRESH_TOKENS': True,
'BLACKLIST_AFTER_ROTATION': True,
}Pitfall: JWT is not an "advanced version" of sessions — just a different trade-off.
- A same-domain browser app putting JWT in localStorage invites XSS; HttpOnly cookie + session remains the better default.
- Pick JWT when you really need stateless/cross-service.