Như chúng ta đã biết thì xác thực là một trong những phần quan trọng nhất trong hầu hết các ứng dụng, từ ứng dụng máy tính để bàn đến ứng dụng web hoặc ứng dụng di động. Bài viết này chúng ta sẽ tìm hiểu chi tiết về JWT để hiểu thêm một số kiến thức:
- Cơ chế xác thực dựa trên phiên (session) so với xác thực dựa trên mã access token (Session-based Authentication vs Token-based Authentication). Tại sao JWT ra đời?
- JWT hoạt động như thế nào.
- Cách tạo JWT.
- Cách chúng ta có thể bảo mật ứng dụng của mình và xác thực bằng JWT.
Session-based Authentication & Token-based Authentication
Để sử dụng bất kỳ trang web, ứng dụng dành cho thiết bị di động hoặc ứng dụng dành cho máy tính để bàn nào… hầu hết chúng ta cần tạo một tài khoản, sau đó sử dụng nó để đăng nhập và để truy cập các tính năng của ứng dụng. Hành động đó gọi là xác thực. Vậy làm thế nào để xác thực tài khoản? Một phương pháp đơn giản mà các trang web phổ biến đã sử dụng trước đây là: Xác thực dựa trên phiên (Session-based Authentication).
Trong hình trên, khi người dùng đăng nhập vào một trang web, Server sẽ tạo một Session (phiên) cho người dùng đó và lưu trữ nó (trong Bộ nhớ - memory ram hoặc Database). Server cũng trả về một SessionId cho Client để lưu nó trong Cookie của trình duyệt. Session này trên Server có thời gian hết hạn. Sau khoảng thời gian đó, Session này sẽ hết hạn và người dùng phải đăng nhập lại để tạo Session mới.
Nếu người dùng đã đăng nhập và Session vẫn chưa hết hạn, khi gửi một HTTP Request tới Server sẽ luôn đính kèm cả thông tin Cookie (bao gồm SessionId). Server sẽ so sánh SessionId này với Session được lưu trữ ở Server để xác thực và trả về phản hồi tương ứng.
Điều này nghe có vẻ ổn. Vậy tại sao chúng ta vẫn cần cơ chế xác thực dựa trên mã access token? Câu trả lời là ngoài ứng web, còn có rất nhiều nền tảng khác. Giả sử rằng có một trang web hoạt động tốt với Session. Một ngày nào đó, ta muốn triển khai ứng dụng trên nền tảng di động (Native App) và sử dụng cùng một Cơ sở dữ liệu với ứng dụng Web hiện tại. Lúc này, chúng ta không thể xác thực người dùng trên ứng dụng di động bằng cơ chế xác thực dựa trên phiên vì ứng dụng di động không có Cookie.
Và đó là lý do tại sao cơ chế xác thực dựa trên mã access token (Token-based Authentication) ra đời. Với phương pháp này, trạng thái và thông tin đăng nhập của người dùng được Server mã hóa thành JSON Web Token (JWT) và gửi đến Client.
JWT hoạt động như thế nào?
Thay vì tạo phiên, Server tạo JWT từ dữ liệu đăng nhập của người dùng và gửi đến Client. Client sẽ lưu JWT và từ đó mọi Request từ Client đến Server phải được đính kèm JWT đó (thường ở Header). Máy chủ sẽ xác nhận JWT và trả về Response.
Để lưu trữ JWT ở Client thì nó phụ thuộc vào nền tảng mà phía Client sử dụng như:
- Browser: Local storage
- IOS: Keychain
- Android: SharedPreferences
Tạo JWT như thế nào?
Chuỗi JWT gồm 3 phần: Header, Payload, Signature
Header
Header lưu thông tin thuật toán mã hóa.
{ "typ": "JWT", "alg": "HS256"
}
typ
chỉ ra rằng loại Token ở đây là JWT.alg
là từ viết tắt củaalgorithm
, là một thuật toán băm để tạo mã Token. Trong đoạn mã trên, HS256 là HMAC-SHA256 - thuật toán sử dụng khóa bí mật (secret key).
Payload
Payload là thông tin đối tượng chính mà ta muốn lưu lại (trường hợp này là thông tin người dùng đăng nhập).
{ "userId": "abcd12345ghijk", "username": "bezkoder", "email": "_@.com", "permissions": [....] "exp": 1570238992
}
Tham khảo một số thông tin JWT cơ bản.
Signature
Phần này là nơi chúng ta sử dụng thuật toán băm khai báo ở header để tạo ra Signature: Ví dụ:
const data = Base64UrlEncode(header) + '.' + Base64UrlEncode(payload);
const hashedData = Hash(data, secret);
const signature = Base64UrlEncode(hashedData);
- Đầu tiên là encode Header và Payload và join chúng với nhau bởi
.
data = '[encodedHeader].[encodedPayload]'
- Tiếp theo, băm dữ liệu bằng thuật toán đã chọn (được xác định ở Header) với một Secret (chuỗi bí mật).
- Cuối cùng, mã hóa kết quả băm để lấy Singnature (chữ ký).
JWT bảo mật dữ liệu như thế nào?
Chúng ta sử dụng Secret Key để tạo Signature. Chuỗi Secret này là duy nhất đối với mỗi ứng dụng và phải được lưu trữ bảo mật trên Server.
Khi nhận JWT từ Client, Server lấy chữ ký trong JWT, xác minh rằng chữ ký được băm chính xác bằng cùng một thuật toán và chuỗi bí mật như trên. Nếu nó khớp với chữ ký của Server tức là JWT hợp lệ.
**Important!**
Các lập trình viên có kinh nghiệm vẫn có thể thêm hoặc chỉnh sửa thông tin Payload khi gửi nó đến Server. Trong trường hợp này chúng ta có thể lưu trữ Token trước khi gửi cho Client. Nó có thể được dùng để verify JWT mà Client truyền sau này là hợp lệ hay không. Ngoài ra, việc lưu Token của người dùng trên Server cũng sẽ có lợi cho tính năng Force Logout khỏi hệ thống.
Tuy nhiên cũng có rủi ro là nếu Database bị lộ thì đồng nghĩa bị lộ hết token của khách hàng và nếu kẻ tấn công đoán ra được chuỗi bí mật thì toàn bộ thông tin khách hàng sẽ bị đánh cắp.
Tổng kết
Không có một phương pháp xác thực tốt nhất. Nó phụ thuộc vào trường hợp sử dụng và cách muốn triển khai. Tuy nhiên, đối với ứng dụng mà muốn mở rộng đến một số lượng lớn người dùng trên nhiều nền tảng, xác thực JWT được ưu tiên hơn. Token-base Authentication cũng là phương pháp bảo mật phổ biến nhất hiện nay.
Trên đây là hướng dẫn chi tiết về JSON Web Token. Hy vọng mọi người sẽ hiểu được ý tưởng tổng thể của bài viết và áp dụng nó vào dự án của mọi các bạn một cách thoải mái.
Mọi người có thể tìm đọc các bài viết liên quan tại:
Nguồn: https://thenewstack.wordpress.com/2021/11/24/jwt-json-web-token-in-depth/
Follow me: thenewstack.wordpress.com