Vấn đề
Câu hỏi PV: "Giả định hệ thống sử dụng JWT làm access token. Vậy làm thế nào để user có thể revoke token/session? Từ đó user đương nhiên có thể list lại danh sách các thiết bị logged-in để revoke chúng nếu cần?"
Các bạn mới học backend khi làm việc với JWT đa số thường sẽ chỉ lấy userId (và một số thông tin hỗ trợ authorize) đưa vào payload. Từ đó các bạn sẽ làm một middleware verified và lấy lại phần payload này. Đây là cách đơn giản nhất để làm quen với JWT cho login và authorize.
Lý do và giải pháp
Tuy nhiên, khi cần quản lý lại session của user thì phải cần thêm ít nhất một table nữa (VD: user_sessions). Có table này thì middleware (hoặc identity service) sau khi verify và lấy được payload rồi phải đi check xem record tương ứng còn hay không. Từ đó chương trình có thể quyết định xử lý request hoặc dừng lại.
ID (pk) của bảng user_sessions có thể dùng cho "tid - Token identifier" trong payload của JWT token. Từ đó verify và parse ra là có id để query tìm kiếm.
Đương nhiên về hiệu năng sẽ tăng latency rất đáng kể vì tương ứng với mỗi request đều có một query đi vào table user_sessions. Vì thế chỗ này thường sẽ triển khai thêm caching để hỗ trợ tăng tốc truy vấn. Cache này đương nhiên cũng bị invalid ngay khi user revoke hoặc hết hạn TTL (tính theo thời gian hiệu lực còn lại của token JWT).
Table session này cũng bị nhiều record theo thời gian. Vì thế cũng cần một cron/scheduler đi xoá những record đã hết hạn - với field expired_at để làm điều kiện.
Các case study khác
Một số nghiệp vụ có thể làm được với bảng user_sessions
:
- Có thể giới hạn số lượng session đồng thời của 1 user.
- Có thể lưu thêm một số metadata cần thiết như: IP, Device Name, Browser Name, GEO Location...
- Hệ thống có thể cưỡng chế logout tất cả sessions của một user bất kỳ, hoặc khi user thực hiện đổi password.
- Hệ thống có thể detect trường hợp access token của user bị lấy cắp và sử dụng ở một device khác.
- Hệ thống có thể detect "vị trí hoặc thiết bị khác thuờng" dựa trên lịch sử đăng nhập.
- Và đương nhiên phía user vẫn có thể listing và revoke bất kì một session nào của họ nếu cần.
Và đây là digram minh hoạ:
sequenceDiagram
autonumber
participant User
participant Frontend
participant Backend
participant Database
participant JWT
User->>Frontend: Enter login credentials
Frontend->>Backend: Send credentials
Backend->>Database: Validate credentials
Database-->>Backend: Return user data if valid
Backend->>JWT: Generate JWT
JWT-->>Backend: Return JWT
Backend->>Database: Store session in session table
Backend-->>Frontend: Return JWT
Frontend-->>User: Store JWT
User->>Frontend: Make a request
Frontend->>Backend: Send request with JWT
Backend->>JWT: Validate JWT
JWT-->>Backend: Return validation result
Backend->>Database: Check session in session table
Database-->>Backend: Return session status
Backend-->>Frontend: Return requested data if valid
User->>Frontend: Revoke session
Frontend->>Backend: Send revoke request with JWT
Backend->>Database: Delete session from session table
Database-->>Backend: Confirmation of deletion
Backend-->>Frontend: Inform User of revocation
Note over User, Backend: User is logged out and session is revoked.
Việt Trần
Yêu thích tìm hiểu các công nghệ cốt lõi, kỹ thuật lập trình và thích chia sẻ chúng tới cộng đồng
follow me :
Bài viết liên quan
Giới thiệu Kiến trúc Backend for Frontend (BFF)
Nov 16, 2024 • 10 min read
Flask là gì? Hướng dẫn tạo Ứng dụng Web với Flask
Nov 15, 2024 • 7 min read
Webhook là gì? So sánh Webhook và API
Nov 15, 2024 • 8 min read
Spring Boot là gì? Hướng dẫn Khởi tạo Project Spring Boot với Docker
Nov 14, 2024 • 6 min read
Two-Factor Authentication (2FA) là gì? Vì sao chỉ Mật khẩu thôi là chưa đủ?
Nov 13, 2024 • 7 min read
Test-Driven Development (TDD) là gì? Hướng dẫn thực hành TDD
Nov 13, 2024 • 6 min read