Tất tần tật về JWT & Ứng dụng

Tăng độ bảo mật cho trang web, ứng dụng hay bất cứ một dịch vụ công nghệ thông tin nào cũng là ưu tiên hàng đầu của các nhà phát triển. Trong thời gian gần đây, JWT nổi lên như một hình thức bảo mật tốt – miễn phí ở mức “đỉnh của đỉnh” dành cho các nhà phát triển. Vậy, JWT là gì? Cấu tạo của JWT ra sao? Vì sao và khi nào nên sử dụng JWT?

Mục tiêu

  • Nắm rõ cấu trúc của JWT
  • Hiểu mục đích sử dụng và cơ chế hoạt động của JWT
  • Biết cách bảo mật JWT và áp dụng vào dự án thực tế

Nội dung chính

  • Giới thiệu về JWT
  • Cơ chế hoạt động của JWT & Cấu trúc của một JWT
  • Bảo mật JWT
  • Tổng kết Tips & Tricks

Giới thiệu về JWT

Hoàn cảnh ra đời của JWT

  • Session – Cookie Authenticate

Đối với bất kỳ một ứng dụng web, di động, desktop…vv chắc chắn các bạn đều đã từng tạo tài khoản, sau đó phải đăng nhập để sử dụng các tính năng bên trong của ứng dụng, hành động đó gọi là Authentication – xác thực người dùng.

Vậy thì xác thực người dùng bằng cách nào? Đầu tiên chúng ta sẽ nhìn lại một chút mô hình đơn giản về việc các trang web phổ biến xưa nay sử dụng một Session – Cookie để Authenticate nhé.

Đối với mô hình xác thực Session – Cookie như trên, khi một người dùng đăng nhập vào trang web thì server sẽ tạo ra một Session (phiên làm việc) cho người dùng đó và lưu ở Server, đồng thời ID của Session sẽ được trả về và lưu lại trên Cookie trình duyệt của người dùng.

(Session này sẽ có hạn sử dụng do Dev chúng ta chỉ định, ví dụ 1 ngày chẳng hạn. Sau một ngày thì người dùng phải đăng nhập lại để tạo ra một Session làm việc mới.)

Và khi người dùng vẫn đang đăng nhập, Session còn hạn, thì Cookie sẽ luôn luôn được đính kèm cùng với mọi Request tiếp theo của người dùng đó mỗi khi gửi lên Server.

Sau đó Server sẽ so sánh cái Session ID nhận được từ Cookie với thông tin Session lưu trên server (có thể là RAM hoặc Database) để xác minh người dùng và gửi lại Response tương ứng.

  • Vấn đề gặp phải khi sử dụng Session – Cookie Authenticate: Câu trả lời đơn giản nằm ở việc “Extend Platform”mở rộng nền tảng hệ thống.
    • Không thể xác thực người dùng sử dụng Native app bằng Session được vì Native app không có Cookie, chỉ Browser mới có mà thôi.

Định nghĩa

“JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.”

— Tạm dịch: —

“JSON Web Token (JWT) là 1 tiêu chuẩn mở (RFC 7519) định nghĩa cách thức truyền tin an toàn giữa các thành viên bằng 1 đối tượng JSON. Thông tin này có thể được xác thực và đánh dấu tin cậy nhờ vào “chữ ký” của nó. Phần chữ ký của JWT sẽ được mã hóa lại bằng HMAC hoặc RSA.”

Tham khảo thêm tại: https://jwt.io/introduction

  • Mục đích sử dụng JWT
    • Xác thực (Authentication): JWT thường được sử dụng để xác thực người dùng. Sau khi người dùng đăng nhập, họ được cấp một JWT, và sau đó, mọi yêu cầu tiếp theo từ người dùng đều được gửi kèm theo token này để xác thực.
    • Quyền Truy Cập (Authorization): JWT có thể chứa thông tin về quyền lợi của người dùng, giúp xác định quyền truy cập của họ đối với các tài nguyên cụ thể.
    • Trao Đổi Thông Tin An Toàn (Secure Information Exchange): JWT có thể được sử dụng để truyền thông tin an toàn giữa các bên, vì nó có thể được ký và xác minh để đảm bảo tính toàn vẹn và chắc chắn.
  • Ưu điểm khi sử dụng JWT
    • An toàn hơn
    JWT sử dụng cặp khóa công khai/ riêng tư dưới dạng chứng chỉ X.509 để ký; JWT cũng có thể được ký đối xứng bằng một mã bí mật được chia sẻ sử dụng thuật toán HMAC. SAML có thể sử dụng các cặp khóa công khai/ riêng tư như JWT. Tuy nhiên, chữ ký số bằng XML lại có nhiều lỗ hổng bảo mật rất, phương pháp thực hiện khó khăn hơn JWT rất nhiều.
    • Phổ biến hơn
    Bộ phân tích cú pháp JSON phổ biến hơn trong hầu hết các ngôn ngữ lập trình, vì chúng ánh xạ trực tiếp đến các đối tượng. Ngược lại, XML không có ánh xạ tài liệu một cách tự nhiên. Điều này dẫn đến việc bạn có thể dễ dàng làm việc với JWT hơn so với các xác nhận SAML.
    • Dễ xử lý hơn
    JWT được sử dụng ở quy mô internet. Vì thế, JWT dễ dàng để xử lý trên hầu hết các thiết bị của người dùng, đặc biệt là các thiết bị di động.

Cơ chế hoạt động của JWT

Cấu trúc JWT

“Từ phần này trở đi mình cần các bạn dừng hết mọi xao nhãng xung quanh, tập trung cao độ đọc để hiểu nha.

Let’s keep your mind is depth !”

Ví dụ dưới đây là token trên passio khi Fan dùng để call API:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
eyJpZCI6MTI3LCJwaG9uZV9udW1iZXIiOiIiLCJlbWFpbCI6Im1pbmhudkBlY29tb2JpLmNvbSIsImlhdCI6MTcwMDEyMDI5OSwiZXhwIjoxNzMxMjI0Mjk5LCJwYXNzd29yZF92ZXJzaW9uIjoxfQ.
M3TbGe-iN1xSK_2c4gP4BrnKcDkls1Qf4W6F1sqhmTk

Trông rối rắm thế kia thì có cấu trúc quái gì nhỉ? Thế nhưng không, JWT có cấu trúc của nó đấy các bạn nhé.

JWT trên bao gồm 3 phần:

  • Header (eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9)
  • Payload (eyJpZCI6MTI3LCJwaG9uZV9udW1iZXIiOiIiLCJlbWFpbCI6Im1pbmhudkBlY29tb2JpLmNvbSIsImlhdCI6MTcwMDEyMDI5OSwiZXhwIjoxNzMxMjI0Mjk5LCJwYXNzd29yZF92ZXJzaW9uIjoxfQ)
  • Signature (M3TbGe-iN1xSK_2c4gP4BrnKcDkls1Qf4W6F1sqhmTk)

được phân cách nhau bởi dấu “.” (chấm).

Trông thì có vẻ phức tạp nhưng cấu trúc của nó theo format như sau:

<base64-encoded header>.<base64-encoded payload>.<HMACSHA256(base64-encoded signature)>

Còn đây là data sau khi decode:

HEADER: Đây là nơi chứa cái thông tin mà được dùng để trả lời cho câu hỏi: “Mã JWT được tính toán như thế nào?”

VD:

{
  "typ": "JWT",
  "alg": "HS256"
}

Trong cái Header ví dụ trên, thì “typ” (viết tắt của type) là kiểu Token, ở đây chính là JWT.

Còn “alg” (viết tắt của algorithm) là thuật toán băm tạo ra chữ ký cho Token, ở ví dụ trên HS256 là thuật toán có tên HMAC-SHA256, một thuật toán băm sử dụng khóa bí mật (Secret Key) để tính toán tạo ra chữ ký.

PAYLOAD: Đây là nơi chứa những dữ liệu mà chúng ta muốn lưu lại trong JWT.

Ngoài những trường thông tin do bạn định nghĩa, chú ý thêm 1 số trường thông tin tiêu chuẩn sau:

  • “iss” viết tắt của Issuer là thông tin người tạo ra Token (không phải user đâu nhé, mà nó chính là tên cái hệ thống backend của các bạn chẳng hạn)
  • “iat” viết tắt của Issued at, là nhãn thời gian lúc mà cái token được tạo.
  • “exp” viết tắt của Expiration time, xác định thời gian hết hạn của Token
  • 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)
  • nbf (not before time): token sẽ chưa hợp lệ trước thời điểm này
  • jti: JWT ID

Những thông tin này là optional tức là các bạn có thể tạo hoặc không, nhưng mà nên tạo vì nó sẽ hữu ích. Tham khảo thêm các standard fields khác tại đây: https://en.wikipedia.org/wiki/JSON_Web_Token#Standard_fields

SIGNATURE: Đây là thành phần tối quan trọng dùng để xác thực jwt, được sinh ra dựa vào payload.

Quy trình tạo ra JWT và các thành phần như sau:

B1: Chuẩn bị Header, Payload data

B2: Encode (chuyển đổi) Header & Payload data theo kiểu Base64URL Encoder và ghép lại thành string ngăn cách bởi dấu “.” tạm gán là data

B3: Hash data ở bước 2 sử dụng Secret key (đảm bảo không được để lộ chuỗi này ra ngoài) của bạn. ****Lưu ý sử dụng đúng thuật toán đã khai báo ở “alg” trong Header (HS256 – HMAC-SHA256)

B4: Tiếp tục Encode dữ liệu nhận được từ bước 3 về dạng Base64URL Encode, và chúng ta sẽ thu được chữ ký “Signature”.

B5: Sau khi có đủ 3 thành phần Header, Payload, Signature. Chúng ta sẽ tạo ra JWT bằng cách ghép 3 thành phần trên lại theo đúng cấu trúc header.payload.signature

Lưu ý: ở các bước xử lý Header, Payload, Signature trên kia, dữ liệu chỉ được Encoded và Hash (Signed) chứ không phải Encrypted.

Phân biệt thì xem thêm tại đây: https://danielmiessler.com/p/encoding-encryption-hashing-obfuscation/#encoding

Bảo mật JWT

  • Luôn luôn sử dụng HTTPS
  • Bảo mật Secret key một cách thận trọng, không chia sẻ cho Frontend
  • Xác thực JWT kỹ lưỡng các thông tin như: iss, exp,… verify signature
  • Cân nhắc kỹ lưỡng những thông tin lưu trong payload, đặc biệt là những thông tin nhạy cảm

Tổng kết Tips & Tricks

  • Bắt buộc phải verify token thay vì chỉ decode ra rồi sử dụng
  • Không nên lưu quá nhiều data vào payload sẽ khiến token dài, tốn thời gian xử lý. Khuyến nghị giới hạn kích thước của JWT dưới 4 KB
  • exp của jwt dùng làm access_token nên để ngắn (từ 15 phút – 1 giờ)
  • refresh_token có thời gian dài hơn tuy nhiên nên lưu trữ phía server và có cơ chế để thu hồi khi cần thiết.

kinhnghiemlaptrinh.com

Trả lời

Email của bạn sẽ không được hiển thị công khai.