Các cơ chế xác thực người dùng cơ bản
Trong bài viết này, chúng ta sẽ cùng tìm hiểu một số phương pháp xác thực người dùng thông dụng bao gồm Basic HTTP, Digest Access Authentication và JWT.
Basic access Authentication
Đúng như tên gọi của nó, đây là phương pháp cơ bản nhất để xác thực người dùng bằng trình duyệt. Quy trình thực hiện bao gồm các bước như sau:
- Khi người dùng cần truy cập vào một trang web được bảo mật, phía máy chủ yêu cầu xác thực bằng cách gởi một phản hồi có mã 404 và kẹp thêm một trường
WWW-Authenticate: Basic realm="realm_name"
vào phần tiêu đề. Trong đó,realm
là định danh của vùng được bảo mật. Ví dụ:WWW-Authenticate: Basic realm="Secret Place"
- Sau đó, phía người dùng sẽ trả lời bằng cách gởi trường tiêu đề
Authorization
có cấu trúc như sau để trả lờiAuthorization: Basic base64(username:password)
. Trong đó phầnusername
vàpassword
sẽ được nối với nhau bằng dấu:
và sau đó được mã hoá bằng thuật toánbase64
. Ví dụ:Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Chi tiết quy trình được thể hiện trong sơ đồ sau:
Ưu điểm:
- Rất đơn giản, đã được sử dụng lâu đời
- Phương pháp này có thể kết hợp với
HTTPS (HTTP over TLS)
để tăng cường bảo mật
Nhược điểm:
- Thiếu tính bảo mật, dữ liệu về người dùng và mật khẩu được mã hoá đơn giản
- Dễ dàng bị dịch ngược và tấn công bởi bên thứ ba
Phương pháp này hiện đã lỗi thời và chỉ còn sử dụng trong một số trang web nội bộ, đơn giản.
Digest access Authentication
Đây là cơ chế xác thực dựa trên sự đồng thuận (agree-upon). Quy trình thực hiện bao gồm các bước như sau:
-
Khi người dùng cần truy cập vào một trang web được bảo mật, phía server yêu cầu xác thực bằng cách gởi một phản hồi có mã 404 và kẹp thêm một trường
WWW-Authenticate: Digest realm="realm_name" nonce="nonce_value"
vào phần tiêu đề. Trong đó nonce là giá trị đặc biệt được phía máy chủ tạo ra duy nhất cho mỗi lần truy cập. Ví dụ:WWW-Authenticate: Digest realm="testrealm@host.com", qop="auth,auth-int", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", opaque="5ccc069c403ebaf9f0171e9517f40e41"
-
Sau đó phía người dùng sẽ gửi trả lời bằng cách gởi trường tiêu đề
Authorization
có cấu trúc như sau để trả lờiAuthorization: Digest realm="realm_name", nonce="nonce_value", username="user_name", uri="digestURI", response="response_value"
. Trong đó response được tính toán như sau:HA1 = MD5(username:realm:password) HA2 = MD5(method:digestURI) response = MD5(HA1:nonce:HA2)
Ví dụ:
Authorization: Digest username="Mufasa", realm="testrealm@host.com", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", uri="/dir/index.html", qop=auth, response="6629fae49393a05397450978507c4ef1", opaque="5ccc069c403ebaf9f0171e9517f40e41"
Chi tiết quy trình được thể hiện trong sơ đồ sau:
Ưu điểm:
- Mật khẩu được mã hoá 1 chiều bằng thuật toán md5
- Do mật khẩu không được sử dụng trực tiếp nên máy chủ có thể lưu thông tin mã hoá
MD5(username:realm:password)
thay vì lưu chính thông tin mật khẩu - Giá trị
nonce
được tạo ra bằng cách sử dụng thời gian từ phía máy chủ để tránh trường hợp tấn công lặp lại (replay attack)
Nhược điểm:
- Nhiều tùy chọn bảo mật trong RFC 2617 là không bắt buộc dẫn đến tiêu chuẩn bảo mật có thể bị hạ thấp
- Dễ bị tấn công bởi phương pháp
man-in-the-middle
(tấn công người đứng giữa) - Hàm băm MD5 khá yếu nên có thể bị dịch ngược
- Không hỗ trợ các hàm băm tiên tiến như
bcrypt
Phương pháp này hiện đã lỗi thời và được thay thế bằng một số phương pháp hiện đại và bảo mật hơn ví dụ như JWT mà chúng ta sẽ tìm hiểu sau đây.
JWT - JSON Web Token
JWT là một chuẩn mở (RFC 7519) để trao đổi thông tin (token) giữa cái đối tượng bằng định dạng JSON và hiện đang được đề xuất thành tiêu chuẩn mã hoá dữ liệu trên internet.
JWT bao gồm ba phần chính: phần đầu (header), nội dung (payload) và chữ ký (signature) được mã hoá bằng thuật toán base64
và ngăn cách với nhau bằng dấu .
theo cấu trúc như sau:
base64(header) + '.' + base64(payload) + '.' + base64(signature)
Ví dụ một JWT:
`eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjEzODY4OTkxMzEsImlzcyI6ImppcmE6MTU0ODk1OTUiLCJxc2giOiI4MDYzZmY0Y2ExZTQxZGY3YmM5MGM4YWI2ZDBmNjIwN2Q0OTFjZjZkYWQ3YzY2ZWE3OTdiNDYxNGI3MTkyMmU5IiwiaWF0IjoxMzg2ODk4OTUxfQ.uKqU9dTB6gKwG6jQCuXYAiMNdfNRw98Hw_IWuA5MaMo`
Cấu trúc chi tiết của JWT
Phần đầu chứa tên thuật toán mã hoá nội dung:
{
"alg": "HS256",
"typ": "JWT"
}
Phần nội dung bao gồm các thông tin yêu cầu (claims) tuỳ vào nội dung trao đổi giữa client-server:
{
"user_name": "admin",
"user_id": "1513717410",
"authorities": "ADMIN_USER",
"jti": "474cb37f-2c9c-44e4-8f5c-1ea5e4cc4d18"
}
Phần chữ ký bao gồm thông tin mã hoá của phần đầu và nội dung theo nguyên tắc sau:
HMAC_SHA256(secret, base64(header) + "." + base64Url(payload))
Ứng dụng JWT trong cơ chế xác thực người dùng
Sau khi user đăng nhập thành công vào hệ thống, máy chủ sẽ trả về một chuỗi JWT (token) về cho trình duyệt. Token này sẽ được lưu lại trong trình duyệt của người dùng (thường là LocalStorage hoặc Cookies). Bất cứ khi nào người dùng truy cập vào tài nguyên được bảo mật, trình duyệt sẽ tự động thêm token này vào trường tiêu đề như sau: Authorization: Bearer <token>
Chi tiết quy trình được thể hiện trong sơ đồ sau:
Lợi ích của JWT
- Phần chữ ký được mã hoá cả nội dung chính nên máy chủ có thể dễ dàng kiểm tra tính toàn vẹn của dữ liệu được trao đổi
- JWT sử dụng trường tiêu đề
Authorization
để trao đổi token nên sẽ không gặp vấn đề với chính sách bảo mật CORS ở phía máy chủ - JWT sử dụng định dạng JSON nên token có kích thước nhỏ hơn chuẩn SAML (Security Assertion Markup Language) sử dụng định dạng xml
Hy vọng qua bài viết này, bạn đã có thể lựa chọn cơ chế xác thực phù hợp với bài toán của mình.