JWT (JSON Web Token) là định dạng gọn nhẹ để truyền dữ liệu đã ký, phổ biến nhất là thông tin về người dùng đã xác thực. Một token gồm ba phần ngăn cách bởi dấu chấm: header.payload.signature. Ở Việt Nam, JWT xuất hiện dày đặc trong các API của ví điện tử, ứng dụng ngân hàng số và các nền tảng thương mại điện tử dùng PHP/Laravel hoặc Node.js.
Dấu thanh tiếng Việt khiến payload dài hơn đáng kể
Một payload như {"ten": "Nguyễn Thị Hương", "thanh_pho": "Đà Nẵng"} vẫn được mã hóa Base64URL như mọi JSON khác — quá trình này chỉ xử lý byte UTF-8, không quan tâm ngôn ngữ. Nhưng do tiếng Việt có 5 dấu thanh kết hợp với các nguyên âm đã biến đổi (â, ê, ô, ơ, ư), phần lớn ký tự trong tên hoặc địa chỉ tiếng Việt chiếm 2-3 byte UTF-8 mỗi ký tự, khiến token chứa thông tin người dùng thật của Việt Nam dài hơn rõ rệt so với token chỉ chứa dữ liệu ASCII thuần túy — điều đáng lưu ý khi thiết kế payload cho ứng dụng mobile với băng thông hạn chế.
Ba phần của một token
- Header — một JSON chứa loại token và thuật toán ký (ví dụ HS256 hoặc RS256), được mã hóa Base64URL.
- Payload — một JSON chứa các "claim": dữ liệu người dùng, thời điểm cấp, thời hạn hết hạn, v.v., cũng ở dạng Base64URL.
- Signature — chữ ký được tính trên header và payload bằng khóa bí mật hoặc khóa riêng, xác nhận rằng token chưa bị thay đổi.
Base64URL, không phải Base64 thông thường
JWT dùng một biến thể của Base64 với bảng chữ cái an toàn cho URL: các ký tự + và / được thay bằng - và _, và phần đệm = thường bị bỏ đi. Điều này cho phép chèn token vào URL hoặc header mà không cần mã hóa thêm.
Một khác biệt quan trọng: giải mã ≠ xác minh
Header và payload chỉ là Base64URL — bất kỳ ai cũng có thể giải mã và đọc nội dung mà không cần khóa nào. Chỉ có thể tin tưởng nội dung của token sau khi xác minh chữ ký bằng khóa tương ứng — và việc xác minh này do máy chủ thực hiện, không phải bởi một client chỉ nhìn vào những gì bên trong token.
Tấn công nguy hiểm: đánh tráo thuật toán thành "none"
Đặc tả JWT cho phép thuật toán none — token không có chữ ký. Nếu backend ngây thơ tin tưởng trường alg lấy từ header của token thay vì xác minh bằng một thuật toán cố định, đã biết trước, kẻ tấn công có thể đổi alg thành none, bỏ chữ ký. Các thư viện JWT đáng tin cậy yêu cầu chỉ định rõ thuật toán mong đợi khi xác minh, chính là để chống lại kiểu tấn công này.
Chuẩn hóa Unicode và việc so sánh chuỗi trong claim
Vì một chữ có dấu tiếng Việt có thể được lưu ở dạng dựng sẵn (NFC) hoặc tổ hợp (NFD), hai payload chứa "Việt" theo hai cách chuẩn hóa khác nhau sẽ cho ra hai chuỗi Base64URL khác nhau dù hiển thị giống hệt nhau. Đây là lý do một số hệ thống chuẩn hóa chuỗi tiếng Việt về NFC trước khi đưa vào claim, để tránh so sánh token thất bại một cách khó hiểu.