Các phương pháp xác thực bảo mật ứng dụng #5: JWT (JSON Web Token)

6 phút đọc

🧠 Tổng quan — JWT là gì?

JWT (JSON Web Token) là một chuẩn mở (RFC 7519) dùng để truyền thông tin an toàn giữa các bên dưới dạng một JSON object được ký số (digitally signed).

Hãy hình dung JWT như một thẻ nhân viên điện tử: thẻ chứa thông tin của bạn (tên, phòng ban, quyền hạn), được công ty ký xác nhận. Bảo vệ ở cửa không cần gọi HR để xác minh — họ chỉ cần kiểm tra chữ ký trên thẻ.


🏗️ Cấu trúc JWT

Một JWT gồm 3 phần, phân tách bằng dấu chấm (.):

xxxxx.yyyyy.zzzzz
  │       │      │
Header  Payload  Signature

1. Header

Chứa loại token và thuật toán ký:

{
  "alg": "RS256",
  "typ": "JWT"
}

2. Payload (Claims)

Chứa thông tin người dùng và metadata. Lưu ý: phần này chỉ được mã hóa Base64, KHÔNG được mã hóa — bất kỳ ai cũng có thể đọc được.

{
  "sub": "user_123",
  "name": "Trung Phan",
  "role": "admin",
  "iat": 1711234567,
  "exp": 1711235467
}
Claim Ý nghĩa
sub Subject — ID người dùng
iat Issued At — thời điểm tạo token
exp Expiration — thời điểm hết hạn
role Custom claim — quyền hạn người dùng

3. Signature

Được tạo bằng cách ký Header + Payload với secret key hoặc private key:

RS256(base64(header) + "." + base64(payload), privateKey)

Chữ ký này đảm bảo không ai có thể giả mạo hoặc sửa đổi nội dung token mà không bị phát hiện.


⚙️ Cơ chế hoạt động — Flow xác thực

sequenceDiagram
    participant Client as 🖥️ Client (Browser/App)
    participant Auth as 🔐 Auth Server
    participant API as 📦 Resource Server (API)

    Client->>Auth: POST /login (username + password)
    Auth->>Auth: Xác minh thông tin đăng nhập
    alt ✅ Đăng nhập thành công
        Auth->>Auth: Tạo JWT (Header + Payload + Ký số)
        Auth-->>Client: 200 OK + Access Token (JWT) + Refresh Token
    else ❌ Thất bại
        Auth-->>Client: 401 Unauthorized
    end

    Note over Client: Lưu Access Token (memory/cookie)

    Client->>API: GET /api/data\nAuthorization: Bearer eyJhbG...
    API->>API: 1. Xác minh chữ ký\n2. Kiểm tra exp (hết hạn chưa?)
    alt ✅ Token hợp lệ
        API-->>Client: 200 OK + Dữ liệu
    else ⏰ Token hết hạn
        API-->>Client: 401 Token Expired
        Client->>Auth: POST /refresh (Refresh Token)
        Auth-->>Client: Access Token mới
    end

Giải thích từng bước:

  1. Đăng nhập: Client gửi username/password → Auth Server xác minh → nếu hợp lệ, tạo JWT và trả về.
  2. Lưu token: Client lưu Access Token (thường trong memory hoặc httpOnly cookie).
  3. Gọi API: Mỗi request, Client đính kèm token vào header Authorization: Bearer <token>.
  4. Xác minh: API Server kiểm tra chữ ký và thời hạn — không cần truy vấn database.
  5. Làm mới: Khi Access Token hết hạn, dùng Refresh Token để lấy token mới mà không cần đăng nhập lại.

✅ Ưu điểm

  • Stateless (không trạng thái): Server không cần lưu session → dễ mở rộng (scale) theo chiều ngang.
  • Tự chứa thông tin: Payload chứa đủ thông tin người dùng → giảm truy vấn DB.
  • Linh hoạt: Hoạt động tốt với microservices — nhiều service có thể xác minh cùng một token.
  • Cross-domain: Dễ dùng trong môi trường CORS, mobile app, SPA.

⚠️ Nhược điểm & Rủi ro cần lưu ý

Vấn đề Giải thích Giải pháp
Không thu hồi được Token hợp lệ cho đến khi hết hạn dù user đã logout Đặt exp ngắn (15–30 phút) + Refresh Token
Payload có thể đọc được Base64 ≠ mã hóa, ai cũng decode được Không lưu thông tin nhạy cảm (mật khẩu, CCCD…)
Kích thước lớn Payload càng nhiều claims, token càng to Chỉ lưu claims cần thiết
Thuật toán yếu alg: none hoặc HS256 có thể bị tấn công Dùng RS256 hoặc ES256 cho production

🔐 Best Practices cho Production

  • Dùng thuật toán RS256 hoặc ES256 (asymmetric) thay vì HS256
  • Access Token hết hạn sau 15–30 phút
  • Refresh Token hết hạn sau 7–30 ngày, lưu trong httpOnly cookie
  • Không lưu thông tin nhạy cảm trong payload
  • Validate đầy đủ: chữ ký + exp + iss (issuer) + aud (audience)
  • Implement token rotation: mỗi lần refresh, cấp Refresh Token mới và vô hiệu hóa cái cũ

🔄 Access Token vs Refresh Token

Access Token Refresh Token
Mục đích Xác thực mỗi API request Lấy Access Token mới
Thời hạn Ngắn (15–30 phút) Dài (7–30 ngày)
Nơi lưu Memory / Authorization header httpOnly cookie
Gửi đến Resource Server (API) Auth Server
Khi bị lộ Thiệt hại giới hạn (hết hạn nhanh) Nguy hiểm hơn — cần revoke ngay

🆚 So sánh với Session-based Authentication

Tiêu chí JWT (Stateless) Session (Stateful)
Lưu trữ phía server ❌ Không cần ✅ Cần (DB/Redis)
Khả năng mở rộng ✅ Tốt (scale ngang dễ) ⚠️ Khó hơn (cần shared session store)
Thu hồi token ❌ Khó (cần blacklist) ✅ Dễ (xóa session)
Phù hợp với Microservices, Mobile, SPA Web truyền thống, cần logout ngay lập tức
Kích thước Lớn hơn (token trong header) Nhỏ (chỉ session ID trong cookie)

📚 Tài liệu tham khảo

Bài viết liên quan

Đang cập nhật...