« Giải mã JWT » nghĩa là gì ?
Giải mã một JWT (« jwt decode », « decode jwt online ») nghĩa là cắt chuỗi tại hai dấu chấm, rồi giải mã từng phân đoạn từ Base64URL để tìm lại JSON ban đầu. Không cần khóa nào: tiêu đề và payload chỉ được chuyển mã, không được mã hóa bí mật — ai cũng đọc được. Đó chính xác là ý định đằng sau « jwt payload decoder » hay « decode jwt without verify » — xem token chứa gì, mà không tự cho rằng nó là thật.
Hãy phân biệt rõ ràng hai hành động này. Đọc một JWT không chứng minh được điều gì: bất kỳ ai cũng có thể tạo ra một token với payload hấp dẫn rồi ký bằng bí mật riêng của mình. Xác minh chữ ký chứng minh rằng nội dung không bị bên thứ ba sửa đổi. Một trình giải mã hiển thị « admin: true » mà không kiểm tra chữ ký đang kể cho bạn một câu chuyện, không phải một sự thật.
Ba phân đoạn của một JWT
Chuỗi được cắt thành đúng ba phần phân cách bằng dấu chấm: header.payload.signature. Tiêu đề chứa ít nhất alg và typ, đôi khi kid để chỉ rõ khóa nào đã được dùng. Payload chứa các claims, những cặp khóa-giá trị mà sổ đăng ký do IANA quản lý. Chữ ký phủ hai phân đoạn đầu được nối chính xác đúng theo dạng viết — chỉ cần thay đổi một dấu cách hay một ký tự là so sánh thất bại.
Toàn bộ khó khăn nằm ở chỗ các phân đoạn này là Base64URL chứ không phải Base64: dấu cộng thành gạch nối, dấu gạch chéo thành gạch dưới, còn phần đệm = thì biến mất. Do đó một trình giải mã Base64 chuẩn sẽ thất bại trên một JWT hoàn toàn hợp lệ. Bảng « Base64URL so với Base64 chuẩn » trong thẻ tham chiếu chỉ rõ đúng các thay thế này.
Cách xác minh chữ ký: HS256, RS256, ES256
Với thuật toán HMAC — HS256, HS384, HS512 — cùng một bí mật dùng để ký cũng như để xác minh: công cụ tính lại HMAC(secret, base64url(header) + "." + base64url(payload)) và so sánh kết quả với chữ ký kèm theo. Đây là trường hợp phổ biến nhất, đồng thời cũng nguy hiểm nhất: mọi dịch vụ nắm giữ bí mật đều có thể phát hành token. Một bí mật dưới 32 byte, tái sử dụng giữa các môi trường, đủ để phá vỡ toàn bộ chuỗi.
Với các thuật toán bất đối xứng — RS256, RS384, RS512, ES256, ES384, ES512, PS256 — bạn chỉ cần khóa công khai để xác minh, nhờ đó kiểm tra được một token do bên thứ ba phát hành mà không bao giờ phải chia sẻ bí mật ký của nó. Dán khóa ở định dạng PEM -----BEGIN PUBLIC KEY----- (SPKI); kết quả thô từ một lần export OpenSSL dùng được ngay. Với ES256, chữ ký ở dạng r||s thô, đúng dạng mà WebCrypto mong đợi.
Cuối cùng, hãy cảnh giác với alg confusion : nếu dịch vụ của bạn mong đợi RS256 nhưng lại chấp nhận một token mà tiêu đề khai báo HS256, kẻ tấn công sẽ ký bằng khóa công khai — vốn đã trở thành khóa HMAC — và vượt qua được bước xác minh. Hãy ghim thuật toán mong đợi ở phía máy chủ, đừng bao giờ đọc nó từ chính token.
exp, iat, nbf: những mốc thời gian dễ gây nhầm lẫn
Ba claim này là các giây Unix, không mili giây và không múi giờ: iat 1516239022 nghĩa là 2018-01-17T21:30:22Z. Hai lỗi lặp đi lặp lại: so sánh với một mốc thời gian tính bằng mili giây (giá trị lớn gấp vạn lần) và hiểu một timestamp theo giờ địa phương thay vì UTC. Thẻ « Thời hạn » chuyển đổi cả hai chiều, hiển thị ISO 8601, ngày địa phương cùng thời gian còn lại hoặc đã trôi qua — đủ để nhận ra ngay một token « đã hết hạn » đến từng giây.
Kéo dài thời gian hiệu lực không làm tăng mức bảo mật: một exp bị đẩy lùi chỉ thay đổi giá trị hiển thị, không thay đổi chữ ký. Nếu bạn phải phát hành lại, hãy ký lại token bằng bí mật hoặc khóa riêng — đó chính xác là vai trò của thẻ « Mã hóa ».
Base64URL: tại sao các trình giải mã chuẩn thất bại
Base64URL (RFC 4648 §5) dùng bảng chữ cái A-Z a-z 0-9 - _ và không chấp nhận phần đệm. Một payload 20 ký tự thường cho ra độ dài không phải bội của bốn sau khi bỏ = : đây là điều bình thường, không phải dữ liệu hỏng. Các ký tự - và _ gây dễ nhầm lẫn với mắt người, điều giải thích phân nửa số « token hỏng » được báo lại. Trình giải mã của chúng tôi chấp nhận cả hai bảng chữ cái, chữ hoa chữ thường lẫn lộn, phần đệm tùy chọn và tiền tố Bearer.
Bảo mật: những gì JWT không làm được
JWT không mang lại cả tính riêng tư lẫn khả năng thu hồi. Payload ai cũng đọc được: tuyệt đối không đặt e-mail, quyền nội bộ hay dữ liệu cá nhân mà bạn không dám gửi ở dạng plaintext. Và một token đã ký vẫn hợp lệ cho đến exp kể cả sau khi đăng xuất — khi đó cần một danh sách thu hồi, một jti cơ chế theo dõi ở phía máy chủ, hoặc thời hạn ngắn kèm refresh token. Một thói quen tốt: exp ngắn (10 đến 15 phút), iat được kiểm soát, nbf canh theo iat, aud và iss được kiểm tra khi nhận.
Dành cho
Lập trình viên back-end và front-end (OAuth 2.0, OpenID Connect, API REST), người tích hợp và DevOps (hạ tầng danh tính, JWKS, xoay vòng khóa), tester và pentester (viết lại claims, alg confusion, hết hạn), quản trị viên hệ thống (gỡ lỗi một 401 không rõ nguyên nhân), sinh viên (hiểu Base64URL và WebCrypto), và bất kỳ ai cần một trình giải mã JWT trực tuyến nhanh, đầy đủ và bảo mật — kèm theo trình mã hóa / giải mã Base64, và trình mã hóa / giải mã URL và trình định dạng JSON.