+6

[Authentication] Xác thực với JWT cùng mã hóa Đối xứng và Bất đối xứng (Phần 1)

Hello anh em, xác thực JWT thì chắc hẳn là một chủ đề không còn quá xa lạ gì với anh em DEV chúng ta rồi. Nhưng để nâng cấp JWT trở nên bảo mật hơn thì trong bài viết này mình sẽ cùng anh em tìm hiểu việc áp dụng mã hóa Đối xứng và Bất đối xứng trong xác thực JWT. Trước khi đi vào trọng tâm chính của bài này, anh em mình sẽ cùng lướt qua một số lý thuyết cơ bản về JWT nhé.

1. JWT là gì ?

JWT (JSON Web Tokens) là một chuẩn mở (RFC 7519) định nghĩa một cách nhỏ gọn và khép kín để truyền một cách an toàn thông tin giữa các bên dưới dạng đối tượng JSON. Thông tin này có thể được xác minh và đáng tin cậy vì nó có chứa chữ ký số.

  • Hiểu đơn giản, dữ liệu ban đầu ở dạng JSON. Sau đó được mã hóa bằng một thuật toán nào đó nó trở thành một chuỗi string (hay chúng ta thường gọi là token) mà bằng mắt thường không thể đọc được.
  • JWT có thể được mã hóa (sign) bằng một thuật toán bí mật (HMAC, SHA256) hoặc một public/private key (RSA) . JWT rất hữu ích trong việc xác thực API và ủy quyền từ server đến client.
VD: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

1.png

Anh em truy cập jwt.io để xem kết quả nhé.

2. Tại sao lại xác thực REST API với JWT ?

Đây là một câu hỏi quan trọng giúp các bạn hiểu thêm về security trong việc phát triển một restful api. Tất nhiên đây chỉ là một phần security trong rất rất nhiều phần security còn lại.

Ví dụ: Bạn có một link rest api: https://domain.com/users/getAll. Nhìn sơ qua các bạn cũng thấy nhiệm vụ của nó là gì? Đó chính là lấy tất cả các user hiện có trong collection users. Nếu như link này bất cứ ai cũng có thể truy cập được và lấy nó thì hậu quả như thế nào? Cho nên mới có việc xác thực một ai đó được cấp quyền mới lấy được những user đó. Vậy cho nên chúng ta mới sử dụng JWT để giải quyết vấn đề đó. [trích từ anonystick.com]

3. Cấu trúc JWT

Một JWT gồm 3 phần, được ngăn cách nhau bởi dấu chấm header.payload.signature

image.png

3.1. Header

Phần Header của JWT bao gồm

  • typ: loại token
  • alg: thuật toán được sử dụng để mã hóa và giải mã. Các thuật toán này có thể là HMAC, SHA256, RSA, HS256 hoặc RS256.
{
"typ": "JWT",
"alg": "HS256"
}

3.2. Payload

Phần Payload của JWT bao gồm các nội dung của thông tin và được gọi là các claim. Dưới đây là một số claim tiêu chuẩn mà chúng ta có thể sử dụng:

  • iss (issuer): tổ chức phát hành token (không bắt buộc)
  • sub (subject): chủ đề của token (không bắt buộc)
  • aud (audience): đối tượng sử dụng token (không bắt buộc)
  • exp (expired time): thời điểm token sẽ hết hạn (không bắt buộc)
  • nbf (not before time): token sẽ chưa hợp lệ trước thời điểm này
  • iat (issued at): thời điểm token được phát hành, tính theo UNIX time
  • jti: JWT ID
{
"sub": "user10001",
"iat": 1569302116
}

Các claim tùy chỉnh cũng có thể được bao gồm trong tập hợp các claim. Một số lưu ý khi sử dụng claim tùy chỉnh:

  1. Không đặt dữ liệu lớn trong các tập hợp claim. Các tập hợp claim nên được thiết kế gọn nhẹ nhất có thể
  2. Không đặt thông tin nhạy cảm như password vì JWT có thể được giải mã dễ dàng.
{
"sub": "user10001",
"iat": 1569302116,
"role": "admin",
"user_id": "user10001"
}

3.3. Signature

Signature (phần chữ ký) là phần quan trọng nhất của JWT.

Chữ ký được tính bằng cách mã hóa phần Header và Payload sử dụng Base64url Encoding và ghép chúng với một dấu chấm. Sau đó, chúng được đưa cho thuật toán mã hóa (HMAC, SHA256, RSA, HS256 hoặc RS256).

// VD thuật toán chữ ký
data = base64urlEncode( header ) + "." + base64urlEncode( payload )
signature = HMAC-SHA256( data, secret_salt )

Do Signature đã bao gồm cả header và payload nên Signature có thể dùng để kiểm tra tính toàn vẹn của dữ liệu khi truyền tải.

4. Ưu điểm và Nhược điểm của JWT

JWT là một công cụ hữu ích để xác thực người dùng và cung cấp quyền truy cập. Tuy nhiên, như mọi công nghệ khác, nó cũng có những ưu điểm và nhược điểm riêng. Dưới đây là một số ưu điểm và nhược điểm của JWT:

Ưu điểm:

  • Đơn giản và dễ sử dụng: JWT có cấu trúc đơn giản, dễ dàng để hiểu và sử dụng.
  • Tiết kiệm tài nguyên: JWT được lưu trữ trên máy khách, giúp giảm tải cho máy chủ. Do đó, nó rất hữu ích trong các ứng dụng phân tán, nơi mà trạng thái có thể được lưu trữ tại nhiều vị trí khác nhau.
  • Độ tin cậy cao: JWT được mã hóa và ký, giúp ngăn chặn việc sửa đổi dữ liệu trên đường truyền.
  • Dữ liệu được lưu trữ trong token: JWT cho phép lưu trữ thông tin người dùng trong token, giúp giảm thiểu số lần truy vấn cơ sở dữ liệu.
  • Tích hợp dễ dàng: JWT có thể tích hợp với nhiều ngôn ngữ lập trình và framework.

Nhược điểm:

  • Không thể hủy bỏ token: Khi một token được tạo ra và gửi đến máy khách, không thể hủy bỏ nó trước khi hết thời gian sống hoặc thay đổi secret key và không thể chủ động force logout được. => có thể khắc phục bằng phương pháp mã hóa bất đối xứng sẽ được trình bày trong phần 6.
  • Lưu trữ thông tin quá nhiều: Nếu lưu trữ quá nhiều thông tin người dùng trong token, kích thước của token có thể trở nên quá lớn. => khắc phục bằng cách giảm thiểu dữ liệu, chỉ lưu những thông tin cần thiết.
  • Rủi ro bảo mật: Nếu secret key của JWT bị lộ, thì hacker có thể giả mạo token và truy cập thông tin người dùng. => có thể khắc phục bằng phương pháp mã hóa bất đối xứng sẽ được trình bày trong phần 6.
  • Không hỗ trợ quản lý phiên: JWT không hỗ trợ quản lý phiên như các giải pháp dựa trên cookie. Điều này có nghĩa là nếu bạn muốn hủy bỏ phiên của người dùng, bạn phải chờ cho JWT hết hạn hoặc thay đổi khóa bí mật. => có thể khắc phục bằng phương pháp mã hóa bất đối xứng sẽ được trình bày trong phần 6.
  • Thời gian sống của token không linh hoạt: Nếu thời gian sống của token quá ngắn, người dùng sẽ phải đăng nhập quá thường xuyên. Nếu quá dài, thì việc bảo mật sẽ bị giảm sút. => áp dụng refresh token để khắc phục.

5. Cơ chế hoạt động JWT

image.png

  1. Client gửi username, password tới server để login nhằm mục đích xác thực.
  2. Nếu login thành công server sẽ tạo ra token (jwt) và gửi về client.
  3. Client nhận token đó, rồi lưu trữ trên trình duyệt (cookies, localStorage, ..).
  4. Khi client gửi request tiếp theo tới server, request đó sẽ được đính kèm token nhằm mục đích xác thực.
  5. Server nhận được request và kiểm tra token. Nếu token hợp lệ thì gửi trả kết quả về client, còn không gửi thông báo chưa xác thực (403).

JWT có thể được mã hóa 2 hai phương thức: Mã hóa đối xứngMã hóa bất đối xứng. Trong phần tiếp theo, chúng ta sẽ tìm hiểu cách xác thực JWT cùng mã hóa đối xứng và bất đối xứng sử dụng ngôn ngữ Node.js và thư viện jsonwebtoken để thực hiện tạo JWT.

6. Xác thực JWT cùng Mã hóa đối xứng và Mã hóa bất đối xứng

Do bài này hơi dài nên mình tách làm 2 bài riêng để anh em dễ theo dõi.
Anh em truy cập link này để mình cùng tiếp tục tìm hiểu về Xác thực JWT cùng Mã hóa đối xứng và Mã hóa bất đối xứng nhé.


Nguồn tham khảo:

  1. https://anonystick.com/blog-developer/json-web-token-van-de-xac-thuc-rest-api-voi-jwtjson-web-token-201906074991365
  2. https://dev.to/kcdchennai/how-jwt-json-web-token-authentication-works-21e7
  3. https://viblo.asia/p/jwt-tu-co-ban-den-chi-tiet-LzD5dXwe5jY
  4. https://www.youtube.com/watch?v=o4NSbpJ4VdE
  5. https://viblo.asia/p/tim-hieu-ve-json-web-token-jwt-7rVRqp73v4bP

All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí