SecOps Portal
Trang chủ › Nghiên Cứu Bảo Mật

Cách triển khai xác thực Token JWT an toàn trong dự án

Ban biên tập SecOps Portal · · Cập nhật
Cách triển khai xác thực Token JWT an toàn trong dự án

Triển khai JWT an toàn đòi hỏi năm điểm: cố định thuật toán ký phía máy chủ và từ chối "none", kiểm tra đầy đủ chữ ký cùng các claim như hạn dùng, nhà phát hành, đối tượng nhận; giữ access token ngắn hạn kèm refresh token có thể thu hồi; lưu token ở client theo cách hạn chế rủi ro XSS; và không đặt dữ liệu nhạy cảm vào payload vì JWT chỉ được ký, không được mã hóa. Phần lớn lỗ hổng liên quan JWT đến từ việc thư viện được cấu hình lỏng hoặc dùng JWT cho việc nó không phù hợp.

JWT là gì, gồm những phần nào

JSON Web Token (JWT) là chuỗi gồm ba phần ngăn cách bởi dấu chấm:

  • Header: loại token và thuật toán ký, ví dụ HS256 hoặc RS256.
  • Payload: các claim, như sub (định danh người dùng), exp (hết hạn), iat (thời điểm phát hành), iss (bên phát hành), aud (đối tượng nhận), cùng claim tùy chỉnh.
  • Signature: chữ ký trên header và payload, dùng khóa bí mật hoặc khóa riêng.

Header và payload chỉ được mã hóa base64url, ai có token cũng đọc được nội dung. Chữ ký chỉ bảo đảm nội dung không bị sửa, không che giấu nội dung. Vì vậy không bao giờ đặt mật khẩu, số thẻ hay thông tin nhạy cảm vào payload.

Chọn thuật toán ký

Thuật toánCơ chếPhù hợp khi
HS256 (HMAC)Một khóa bí mật dùng chung để ký và xác minhCùng một dịch vụ vừa phát hành vừa xác minh
RS256 (RSA)Ký bằng khóa riêng, xác minh bằng khóa công khaiNhiều dịch vụ cần xác minh nhưng không được phát hành token
ES256 (ECDSA)Như RS256, khóa và chữ ký ngắn hơnTương tự RS256, cần hiệu năng tốt hơn

Với HS256, khóa bí mật phải dài và ngẫu nhiên; khóa ngắn hay dễ đoán có thể bị dò ngoại tuyến từ một token bất kỳ. Khóa phải được quản lý như mọi bí mật khác, xem bài bảo mật tệp cấu hình nhạy cảm.

Kiểm tra token: đừng tin header

Những lỗi kinh điển của JWT đều liên quan việc máy chủ tin vào thông tin trong token:

  • Thuật toán "none": một số thư viện cũ chấp nhận token không có chữ ký nếu header khai báo alg là none.
  • Nhầm lẫn thuật toán: máy chủ dùng RS256, kẻ tấn công đổi header sang HS256 và ký bằng chính khóa công khai; thư viện cấu hình sai sẽ dùng khóa công khai như khóa HMAC và chấp nhận.
  • Tin header kid, jku: dùng giá trị trong header để tìm khóa mà không kiểm soát, cho phép trỏ tới khóa do kẻ tấn công cung cấp.

Cách phòng: cấu hình phía máy chủ danh sách thuật toán được chấp nhận cố định; dùng thư viện phổ biến, cập nhật; chỉ lấy khóa từ nguồn tin cậy đã cấu hình sẵn.

Kiểm tra claim

  1. exp: token hết hạn phải bị từ chối; cho phép lệch giờ nhỏ.
  2. nbf, iat: từ chối token chưa đến thời điểm hiệu lực.
  3. iss: đúng bên phát hành mong đợi.
  4. aud: token phát cho dịch vụ A không được dùng ở dịch vụ B.
  5. Quyền: claim về vai trò chỉ là gợi ý; với thao tác nhạy cảm, kiểm tra quyền hiện tại từ nguồn dữ liệu tin cậy.

Thời hạn và refresh token

JWT có điểm yếu cố hữu: một khi đã phát hành, token hợp lệ cho tới khi hết hạn, khó thu hồi. Mô hình phổ biến để cân bằng:

  • Access token ngắn hạn, thường tính bằng phút.
  • Refresh token dài hạn hơn, lưu ở máy chủ (hoặc có định danh lưu ở máy chủ) để có thể thu hồi.
  • Xoay vòng refresh token: mỗi lần dùng cấp token mới, vô hiệu token cũ; nếu token cũ bị dùng lại, coi là dấu hiệu bị đánh cắp và thu hồi cả chuỗi.
  • Khi người dùng đổi mật khẩu hoặc đăng xuất mọi thiết bị, thu hồi refresh token.

Lưu token ở đâu phía client

Nơi lưuƯu điểmRủi ro
Cookie HttpOnly, Secure, SameSiteScript không đọc được, giảm hậu quả XSSCần chống CSRF nếu SameSite không đủ chặt
localStorage, sessionStorageĐơn giản, dễ gửi qua headerMọi script trên trang đều đọc được nếu có XSS
Bộ nhớ JavaScriptMất khi tải lại trang, khó bị đánh cắp lâu dàiCần cơ chế làm mới phiên

Với ứng dụng web, nhiều nhóm chọn lưu refresh token trong cookie HttpOnly và giữ access token trong bộ nhớ. Dù chọn cách nào, phòng chống XSS vẫn là điều kiện tiên quyết, xem bài ngăn chặn XSS.

Khi nào không nên dùng JWT

JWT phù hợp cho xác thực giữa các dịch vụ hoặc hệ thống phân tán cần xác minh không trạng thái. Với ứng dụng web truyền thống một máy chủ, phiên lưu ở máy chủ kèm cookie thường đơn giản và dễ thu hồi hơn. Dùng JWT chỉ vì "hiện đại" có thể tạo thêm rủi ro không cần thiết.

Xoay khóa ký mà không làm gián đoạn

Khóa ký cần được thay định kỳ hoặc ngay khi nghi bị lộ. Để không làm mọi người dùng bị đăng xuất cùng lúc, hãy gán định danh khóa (kid) cho mỗi khóa và cho phép máy chủ xác minh bằng nhiều khóa trong giai đoạn chuyển tiếp. Quy trình thường là: tạo khóa mới, công bố khóa công khai mới qua điểm JWKS, bắt đầu ký token mới bằng khóa mới, chờ token cũ hết hạn rồi gỡ khóa cũ. Lưu ý danh sách khóa phải do máy chủ cấu hình, không lấy theo địa chỉ ghi trong header của token.

Checklist triển khai

  • Thư viện JWT phổ biến, cập nhật, thuật toán cố định phía máy chủ.
  • Khóa đủ mạnh, lưu trong trình quản lý bí mật, có kế hoạch xoay khóa.
  • Kiểm tra exp, iss, aud ở mọi dịch vụ nhận token.
  • Access token ngắn hạn, refresh token thu hồi được.
  • Không đặt dữ liệu nhạy cảm vào payload; không truyền token qua URL.
  • Ghi log sự kiện xác thực thất bại để phát hiện dò quét.

Xác thực bằng token là một phần của bức tranh bảo mật API rộng hơn, được trình bày trong bài bảo mật API trong phát triển web.

Câu hỏi thường gặp

JWT có được mã hóa không?

JWT thông thường (JWS) chỉ được ký, nội dung payload ai cũng đọc được bằng cách giải mã base64. Nếu cần che giấu nội dung, phải dùng JWE hoặc đơn giản là không đặt dữ liệu nhạy cảm vào token.

Làm sao đăng xuất người dùng khi dùng JWT?

Xóa token ở client và thu hồi refresh token ở máy chủ. Access token còn hiệu lực đến khi hết hạn, vì vậy nên để thời hạn ngắn. Trường hợp cần thu hồi tức thì, dùng danh sách chặn theo định danh token.

Nên chọn HS256 hay RS256?

Nếu chỉ một dịch vụ vừa phát hành vừa xác minh, HS256 với khóa mạnh là đủ. Khi nhiều dịch vụ cần xác minh token, RS256 hoặc ES256 an toàn hơn vì các dịch vụ đó chỉ cần khóa công khai.

Access token nên có thời hạn bao lâu?

Thường từ vài phút đến khoảng một giờ tùy mức nhạy cảm của hệ thống. Thời hạn càng ngắn, thiệt hại khi token bị đánh cắp càng nhỏ, đổi lại cần cơ chế làm mới bằng refresh token.

Bài liên quan