JWT là gì? 3 phần header.payload.signature và cách đọc an toàn【2026】

(Cập nhật: 19 tháng 7, 2026 ) JWT JSON Web Token header payload signature decode verify authentication API
Kết luận

JWT = 3 phần header.payload.signature nối bằng dấu chấm. Header và payload chỉ là Base64URL — ai có token đều đọc được. Decode ≠ verify: đọc claims để debug; tin claims chỉ sau khi server verify chữ ký. Đừng nhét secret vào payload. Debug nhanh, local, không upload: JWT decode Kawa.

Khi API trả 401 hoặc SPA “có token mà vẫn mất quyền”, bước đầu tiên của junior và freelancer outsource thường là nhìn vào JWT. Nhưng nhiều người dừng ở “dán lên trang decode nào đó” mà không hiểu ba phần đang nói gì — và nhầm đọc được payload với token hợp lệ.

Bài này tập trung góc JWT là gì qua cấu trúc header.payload.sig: mỗi phần chứa gì, vì sao decode không cần secret, khi nào verify, và checklist debug cho team Việt Nam làm SPA / Nest / Laravel API.

Bài viết này giúp bạn

  • Nhận diện đúng 3 phần và lỗi copy thiếu đoạn
  • Đọc header (alg, kid) và payload (sub, exp, roles)
  • Phân biệt encoding vs encryption, decode vs verify
  • Tránh 6 lỗi phổ biến (alg=none, secret trong repo, tin payload chưa verify…)
  • Dùng tool trình duyệt để decode trước khi mở ticket “auth hỏng”

JWT là gì (một câu rồi đi vào 3 phần)

JSON Web Token là chuỗi compact dùng trong OAuth2 / session API: client gửi kèm request, server kiểm tra chữ ký rồi đọc claims (ai, hết hạn khi nào, role gì).

Hình dạng luôn giống:

xxxxx.yyyyy.zzzzz
 │      │      └── signature (chữ ký)
 │      └───────── payload  (claims — dữ liệu)
 └──────────────── header   (metadata thuật toán)

Ba phần bắt buộc. Nếu DevTools hiện 2 đoạn hoặc có khoảng trắng/newline giữa chừng — token đã bị cắt khi copy từ Slack, email, hoặc log wrap dòng.


Phần 1 — Header

Header là JSON nhỏ, rồi Base64URL. Ví dụ sau decode:

{
  "alg": "HS256",
  "typ": "JWT"
}
TrườngÝ nghĩa thực tế
algThuật toán chữ ký: HS256 (shared secret), RS256/ES256 (keypair)
typThường JWT
kidKey ID — chọn đúng key trong JWKS khi rotate

Checklist header khi debug:

  1. alg có khớp với server đang verify không? (Client “HS256” nhưng gateway chỉ nhận RS256 → fail)
  2. kid không — và key đó còn active sau rotate không?
  3. Cảnh báo: token với "alg":"none" hoặc header bị sửa để bỏ chữ ký là vector tấn cổ điển — library cũ từng chấp nhận. Server phải denylist none và cố định thuật toán cho phép.

Bạn không cần secret để đọc header. Chỉ cần decode Base64URL đoạn thứ nhất.


Phần 2 — Payload (claims)

Payload cũng chỉ encode, không mã hóa. Ví dụ:

{
  "sub": "user_42",
  "name": "An",
  "role": "editor",
  "iat": 1710000000,
  "exp": 1710003600
}
Claims hay gặp khi debug API
Claim Nghĩa Hỏi gì khi 401 / mất quyền
sub Subject — ID user ID này có map đúng DB / tenant không?
exp Hết hạn (Unix giây) Đồng hồ client lệch? Refresh token chưa chạy?
iat / nbf Issued-at / not-before Token dùng quá sớm vì clock skew?
iss / aud Issuer / audience Gửi nhầm môi trường (staging token → prod)?
roles / scope Quyền Claim tên khác với middleware đang đọc?
Payload không phải chỗ giấu bí mật

Ai cầm JWT đều đọc được claims. Cấm đưa mật khẩu, API key production, số thẻ, PII nhạy cảm vào payload. Chỉ để ID, role, expiry — thứ lộ ra vẫn chấp nhận được trong threat model của bạn.

Encoding ≠ encryption

Đừng nhầm hai khái niệm
Encoding (JWT header/payload) Encryption (JWE / TLS)
Ai cũng đảo ngược được Cần khóa mới đọc được
Mục đích: đưa JSON vào chuỗi URL-safe Mục đích: che nội dung
JWT thường gặp = JWS (ký) Cần ẩn claims → dùng JWE hoặc không để data nhạy trong token

Phần 3 — Signature

Signature = kết quả thuật toán trên base64url(header) + "." + base64url(payload) với secret hoặc private key.

  • Đổi 1 byte trong payload → chữ ký cũ không còn khớp
  • Server so sánh → 401 Unauthorized
  • Đó là lý do “đọc được payload” nhưng không thể giả mạo nếu secret/key giữ chặt

Decode không kiểm tra signature. Tool chỉ tách 3 phần và JSON-pretty. Muốn biết token có bị sửa hoặc secret đúng không → verify (backend, hoặc bước verify HS256 trên tool nếu bạn đang test secret staging).


Decode vs verify — quy tắc cho SPA và API

ViệcAi làmCần secret?Kết luận an toàn?
Decode xem exp, roleDev / frontend debugKhôngChỉ để quan sát
Verify chữ kýBackend / API gatewayCó (secret hoặc JWKS)Mới được tin claims
Tin role trên React để ẩn nútFrontendUX thôi — vẫn phải authorize lại trên API

Freelance / team outsource hay lỗi: middleware frontend đọc role từ JWT đã decode để cho vào trang admin, không kiểm tra lại trên API → user sửa payload trên DevTools (signature sai) vẫn bị chặn ở API nếu verify đúng — nhưng nếu API cũng quên verify thì thủng.


Quy trình debug 5 phút (staging)

  1. Network → request lỗi → copy Authorization: Bearer … (che nếu gửi screenshot)
  2. Dán vào JWT decode — chạy trong trình duyệt, không cần đăng ký
  3. Đọc header: alg đúng không?
  4. Đọc payload: exp còn hạn? sub đúng user test? aud đúng service?
  5. Nếu claims đúng mà API vẫn 401 → nghi verify (secret/JWKS/kid) hoặc middleware đọc sai tên claim — không nghi “Base64 hỏng” nữa

Ví dụ mental model với token giả (không dùng production):

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0IiwibmFtZSI6IkFuIiwiZXhwIjoxOTk5OTk5OTk5fQ.signature
  • Đoạn 1 → {"alg":"HS256","typ":"JWT"}
  • Đoạn 2 → sub, name, exp
  • Đoạn 3 → chỉ có ý nghĩa khi verify với đúng secret

6 lỗi hay gặp ở team nhỏ / outsourcing

  1. Tin payload chưa verify trên server — coi như auth = decode Base64
  2. Secret HS256 commit vào Git hoặc hardcode trong app mobile
  3. Dán access token production lên trang decode không rõ privacy
  4. Clock skew: exp đúng UTC nhưng server so sánh local time lệch
  5. Copy thiếu phần signature từ log → “JWT phải có 3 phần”
  6. alg=none hoặc thuật toán lệch sau khi đổi IdP / Keycloak / Cognito

Case study ngắn

Case A — “Role không vào UI”: Decode thấy roles: ["editor"] nhưng code đọc role (số ít). Sửa map claim → xong. Không phải hỏng JWT.

Case B — “Token mới vẫn 401”: Payload đúng, exp còn hạn. Header có kid cũ sau key rotation. Gateway JWKS không còn key đó → verify fail. Fix: phát hành lại token hoặc cập nhật JWKS cache.


Khi nào dùng công cụ decode trên Kawa

  • Xác nhận nhanh 3 phần và JSON claims khi pair programming
  • Kiểm tra exp trước khi nghi refresh token
  • Học JWT: paste sample, xem cấu trúc — không cần cài CLI

Tool giải mã JWT xử lý trên trình duyệt. Decode luôn khả dụng; verify chữ ký (nếu dùng) chỉ hỗ trợ ngữ cảnh debug (ví dụ HS256 với secret test) — không thay verify production trên server. Không dán secret production lâu dài.

Checklist trước khi hỏi senior

  • Token đủ 3 phần, không có newline giữa chừng
  • Đã decode header + payload (không chỉ nhìn chuỗi)
  • Đã so exp với giờ UTC
  • Đã xác nhận API verify chữ ký (không chỉ decode)
  • Screenshot đã che token / PII

FAQ nhanh trong bài

Có cần secret để decode? Không.
Đổi payload rồi gửi lại? Signature lệch → server từ chối (nếu verify đúng).
JWT có mã hóa không? Bản JWS phổ biến thì không — chỉ ký.


Liên kết liên quan