JWT là gì? Giải mã và kiểm tra token
JSON Web Token (JWT) là ba đoạn văn bản nối với nhau bằng dấu chấm: header, payload và chữ ký. Hai phần đầu chỉ được mã hóa, không được mã hóa bí mật, nên ai giữ token cũng đọc được. Chữ ký cho phép máy chủ kiểm tra rằng một bên đáng tin đã phát hành token và không ai sửa nó. Giải mã token cho bạn biết token nói gì. Chỉ khi xác minh, bạn mới biết có nên tin nó hay không.
Giải mã JWTToken hết hạn hay còn hiệu lực?Dùng miễn phíBa phần
Token có dạng header.payload.signature. Phần đầu của token ví dụ nổi tiếng trên jwt.io là:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Mỗi phần đầu và phần thứ hai đều là JSON được chuyển sang base64url, một dạng văn bản an toàn để dùng trong URL. Phần đầu giải mã thành:
{"alg":"HS256","typ":"JWT"}
Payload của cùng ví dụ giải mã thành:
{"sub":"1234567890","name":"John Doe","iat":1516239022}
Payload chứa các claim, tức là những khẳng định về người dùng hoặc phiên đăng nhập. Chữ ký được tính từ hai phần đầu và một khóa, nên chỉ cần đổi một ký tự là chữ ký không còn khớp. Base64url đảo ngược được mà không cần khóa, vì vậy đừng bao giờ đặt mật khẩu, khóa riêng hay dữ liệu cá nhân vào payload.
Các claim đã đăng ký
RFC 7519, tiêu chuẩn của JWT, dành riêng một số tên claim ngắn:
iss(issuer): bên tạo ra token.sub(subject): token nói về ai, thường là mã người dùng.aud(audience): dịch vụ mà token dành cho.exp(expiration time): thời điểm sau đó token không còn hợp lệ.nbf(not before): thời điểm sớm nhất token có hiệu lực.iat(issued at): thời điểm token được tạo.
Thời gian là số giây kể từ 0 giờ ngày 1 tháng 1 năm 1970 UTC, gọi là Unix time. Ví dụ trên không có exp, nên theo tiêu chuẩn nó không bao giờ hết hạn. Token thực tế nên có trường này. Các tên khác, như role hay email, thuộc về ứng dụng.
Giải mã khác với xác minh
Giải mã là tách token theo dấu chấm, đảo base64url và đọc JSON. Việc này cho bạn biết token khẳng định điều gì, và cũng làm đúng như vậy với token giả mạo, vì bất kỳ ai cũng có thể viết claim tùy ý kèm chữ ký tùy ý.
Xác minh là tính lại chữ ký bằng khóa đúng và kiểm tra nó có khớp không. Nó còn kiểm tra exp và nbf bao quanh thời điểm hiện tại, và iss cùng aud có đúng giá trị dịch vụ mong đợi. Một ứng dụng đọc claim role mà không xác minh là đang tin bất kỳ ai đã viết token. Đây là lỗi phổ biến.
HS256, RS256 và ES256
Giá trị alg cho biết phương thức ký. Có ba loại phổ biến:
- HS256 là HMAC với SHA-256. Một bí mật dùng chung vừa để ký vừa để xác minh, nên bí mật phải nằm trên máy chủ phát hành token.
- RS256 là chữ ký RSA với SHA-256. Bên phát hành ký bằng khóa riêng, còn ai có khóa công khai đều xác minh được. Các dịch vụ khác có thể kiểm tra token mà không tạo được token.
- ES256 là chữ ký ECDSA trên đường cong P-256 với SHA-256. Hoạt động giống RS256 nhưng khóa và chữ ký nhỏ hơn.
Dùng HS256 khi một dịch vụ vừa phát hành vừa kiểm tra token của nó. Dùng RS256 hoặc ES256 khi các dịch vụ khác phải kiểm tra token mà chúng không phát hành.
Các vấn đề phát sinh từ việc tin vào header
Header do bên gửi token viết, nên bên xác minh không được để nó quyết định luật lệ.
alg: none. Một token không có chữ ký có thể khai báo"alg":"none". Có thư viện từng chấp nhận loại token này và bỏ qua bước kiểm tra. Hãy tự đặt các thuật toán được phép trong mã của bạn, đừng bao giờ lấy từ token.- Nhầm lẫn thuật toán. Máy chủ mong đợi RS256 và giữ khóa công khai. Kẻ tấn công gửi token HS256 được ký bằng chính khóa công khai đó làm bí mật HMAC. Bộ xác minh nào chấp nhận bất kỳ thuật toán nào mà header nêu sẽ chấp nhận token này. Hãy gắn mỗi khóa với đúng một thuật toán.
- Bí mật yếu. Kẻ tấn công có header, payload và chữ ký, nên họ có thể thử các bí mật ứng viên ngoại tuyến. Bí mật ngắn hoặc một từ thông dụng sẽ bị bẻ rất nhanh bằng danh sách như vậy. RFC 7518 yêu cầu khóa HS256 dài ít nhất 256 bit và phải ngẫu nhiên.
Dán token production vào một trang web
Một token hợp lệ, chưa hết hạn, có tác dụng với bất kỳ ai nắm giữ nó, cho đến khi hết hạn. Hãy coi nó như mật khẩu. Trước khi dán vào một trang, hãy kiểm tra xem trang đó có gửi token lên máy chủ không. Công cụ chạy hoàn toàn trong tab trình duyệt thì không cần làm vậy. Bạn có thể kiểm tra bất kỳ trang nào bằng cách xem các yêu cầu mạng trong công cụ dành cho nhà phát triển của trình duyệt.
Token thường không thể thu hồi trước khi hết hạn, trừ khi máy chủ có giữ danh sách. Nếu một token đang dùng bị rò rỉ, hãy yêu cầu dịch vụ thu hồi phiên hoặc thay khóa. Khi có thể, hãy dùng token của môi trường thử nghiệm để gỡ lỗi. Công cụ giải mã JWT đọc ba phần của token ngay trong tab trình duyệt của bạn, và không có gì bạn dán vào được gửi đi đâu cả.
Webhook: cùng ý tưởng với bí mật dùng chung
Hầu hết nhà cung cấp webhook gửi một HMAC của nội dung yêu cầu, được tính bằng bí mật bạn dùng chung với họ, trong một header. Bộ nhận của bạn tính ra HMAC giống vậy rồi so sánh hai giá trị. Các lỗi thường gặp đều nhỏ. JSON bị định dạng lại trước khi băm nên các byte bị thay đổi. Bí mật thử nghiệm bị dùng cho lưu lượng thật. Hoặc chữ ký được so sánh bằng phép so sánh chuỗi thông thường, có thể làm rò rỉ thông tin về thời gian. Hãy dùng phép so sánh có thời gian không đổi.
Công cụ kiểm tra chữ ký webhook tính chữ ký từ bí mật và nội dung bạn dán vào, dùng được cho GitHub, Stripe, Slack, Shopify hoặc bất kỳ cơ chế HMAC nào, để bạn thấy hai giá trị có khớp hay không.
Trả lời nhanh
JWT có được mã hóa không?
Không. JWT tiêu chuẩn được ký, và ai cũng đọc được header và payload của nó. Chỉ có chữ ký bảo vệ nó khỏi bị sửa đổi.
Nếu tôi sửa payload thì sao?
Chữ ký sẽ không còn khớp, nên máy chủ xác minh sẽ từ chối token. Việc đọc claim không kiểm tra chữ ký, nên công cụ giải mã vẫn hiển thị bản bạn đã sửa.
Được dịch từ Bản tiếng Anh với sự hỗ trợ của AI.
Bình luận
Chưa có bình luận nào. Hãy là người đầu tiên.


