Authentication luôn là chức năng quan trọng của bất kỳ hệ thống nào. Phương pháp auth đơn giản và hay được sử dụng trong các ứng dụng web đó là dựa trên cookie và lưu giữ state ở phía server(session, database...). Nhưng với các ứng dụng trên mobile và các ứng dụng web SPA(Single Page Application) thì cần có cơ chế auth tốt hơn, đặc biệt khi mà chúng ta phải thiết kế các stateless api thì server không thể đảm nhiệm việc lưu state phiên làm làm việc của user. Có 2 phương pháp tốt để giải quyết là OAuth 2.0 và JWT(JSON Web Token). Bài viết này đi vào tìm hiểu về JWT.
1. JSON Web Token (JWT) là gì:
JSON Web Token hay JWT định nghĩa cách thức trao đổi dữ liệu theo kiểu JSON. Dữ liệu truyền đi sẽ được mã hóa và chứng thực, và có thể được giải mã để lấy lại thông tin. JWT có 2 thuộc tính:
- Gọn nhẹ (compact): JWT là 1 chuỗi string mã hóa, và thông tin chứa trong đó luôn phải tinh gọn nhất, nên nó có thể gửi thông qua param trên URL, post body param, hay header
- Tự đóng gói (self-contained): Payload của JWT đã chứa các thông tin cần thiết về user.
2. JWT Struct:
JWT bao gồm 3 phần, ngăn cách nhau bởi dấu ".", gồm:
- Header
- Payload
- Signature
Chuỗi JWT:
header.payload.signature
Ví dụ chuỗi JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IlR1IFRyYW4iLCJhZG1pbiI6dHJ1ZSwiYXdlc29tZSI6dHJ1ZX0.N1G5eShGXQElyGr8VCHE2hfZqr9oo9gLl-a_GXK0fLw
Trong đó:
- Header:
Là Base64URL encoded của json:
{ "alg": "HS256", "typ": "JWT" }
- Payload:
Là Base64URL encoded của json:
{ "sub": "1234567890", "name": "Tu Tran", "admin": true, "awesome":true }
- Signature:
Là kết quả của function:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret )
2.1 Header:
Gồm 2 phần: type của token, giá tri là JWT, và phương thức mã hóa, HMAC SHA256 hay RSA. Ví dụ:
{ "alg": "HS256", "typ": "JWT" }
JSON object này sau đó được mã hóa Base64URL
2.2. Payload:
Payload chức các thành phần gọi là claim. Các claim này chứa các thông tin về đối tượng(thường là user), và các meta data của token. Server sẽ dùng các thông tin từ các claim này để có thể thực hiện authentication. Có 3 loại claim:
a. Reserved claim:
Là các claim đã được định nghĩa trước. Các claim này là không bắt buộc phải có trong token, nhưng có thể cung cấp các thông tin hữu ích. Các claim này chỉ gồm 3 ký tự, bao gồm:
- iss: Là thông tin người phát hành(issuer) của token
- sub: Là subject của token
- aud: Là audience của token, nội dung này có thể hiểu là resource server mà chấp nhận token này
- exp: là thời gian hiệu lực của token, giá trị là unixtimestamp
b. Public claim:
Là những claim được định nghĩa 1 cách công khai bởi những bên sử dụng JWT. Thường các claim name này sẽ theo dạng URI để tránh trùng tên. Vd public claim:
{ "http://co-mit.com/jwt_clams/user_role" : "admin" }
c. Private claim:
Là các claim tự định nghĩa và chỉ các thành phần liên quan của hệ thống hiểu được. Vd các claim về user id, email, role....Ví dụ:
{ "email":"tran_phuoctu@co-mit.com.vn", "name":"Tu Tran" }
2.3: Signature
Signature được tạo ra bằng cách dùng phương pháp mã hóa được chỉ định ở header để mã hóa nội dung encode của header, payload, cùng với chuỗi khóa bí mật, ví dụ nếu header chỉ định dùng thuật toán mã hóa HMAC SHA256, và phía server dùng chuỗi khóa bị mật là 'secret' thì signature sẽ được tạo ra như sau:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), "secret")
Signature được dùng để chứng thực là token JWT là đúng và nội dung của token đã không được thay đổi.
3. JWT đươc sử dụng để thực thi authentication như thế nào:
Nhìn vào diagram dưới đây chúng ta có thể dễ dàng hiểu được
4. Tại sao sử dụng JWT:
Có nhiều lý do để sử dụng JWT
- Sự gọn nhẹ và đơn giản. Chuỗi token sinh ra ngắn gọn đủ để chứa các thông tin cần thiết. Và bất kỳ ai cũng có thể dễ dàng hiểu, áp dụng được JWT
- Stateless: Rất phù hợp để áp dụng xây dựng stateless API, bởi token đã chứa đầy đủ các thông tin cần thiết để thực thi authentication.
- Việc apply ở phía client rất đơn giản, cho dù nền tảng web hay mobile
- Dễ dàng mở rộng server hơn. Điều này là nhờ tính stateless của JWT, server không cần phải lưu session state, nên trong trường hợp phía server sử dụng cơ chế load balancing, bất ký máy server nào cũng có thể handle request và vẫn có được state của user thay vì chỉ server mà user đã login.
- Security: Vì JWT không sử dụng cookie nên ta không cần phải lo về vấn đề CSRF. Nhưng JWT tốt nhất cần được sử dụng kèm với HTTPS
- Reusable: Chúng ta có thể có nhiều system chạy các nền tảng khác nhau có thể cùng sử dụng 1 JWT để thực hiện authenticate user. Điều này là khó hoặc không thể nếu state được lưu giữ phía server.
Leave a Comment