Giải pháp nào để vô hiệu hoá mã thông báo jwt (jwt access token) khi người dùng đăng xuất?

Giải pháp nào để vô hiệu hoá mã thông báo jwt (jwt access token) khi người dùng đăng xuất?

Những mẩu tin ngắn hàng ngày dành cho bạn
  • Hic, dạo này bận quá, lại còn nhiều biến nữa nên mình chưa có thời gian viết bài viết dài nữa. Thay vào đó thì là cố gắng duy trì mục tin ngắn hàng ngày này cho bạn đọc. Vì ngắn mà, viết nhanh hơn nhiều.

    Mình đang sửa lại một chút giao diện đồng thời thêm một tính năng mới. Bạn có đoán ra nó là gì không? Bật mí nhé, liên quan một chút đến AI và Tiktok 😁

    » Xem thêm
  • Đang trong 14 ngày dùng thử Windsurf, hôm nay đã là ngày thứ 7, mình có một số cảm nhận nhanh như sau:

    Đầu tiên là giao diện được tuỳ biến hơn một chút, mang lại cảm giác phẳng và thân thiện hơn VSCode truyền thống.

    Thứ hai là gợi ý siêu nhanh nhưng hơi hấp tấp. Kiểu chưa được chính xác cho lắm ý nhưng lại rất tự tin gợi ý ra cả mấy dòng liền. Nên không phải lúc nào tab tab cũng đúng. Tuy vậy đọc ngữ cảnh tốt, tốt hơn cả Copilot.

    Thứ ba là cái Chat/Edit đạt trình độ thượng thừa, rất tốt, nói một hiểu mười, chắc phải ngang ngửa Cursor đấy, mình không dám chắc nữa, cảm nhận thế. Ngoài ra một lỗi làm mình thấy khá khó chịu là thi thoảng nó gợi ý nhưng tab lại không ăn ý, xong mất công phải xoá đi.

    Không biết sau khi hết 14 ngày sẽ như nào, nên mình sẽ tiếp tục cập nhật thêm. Nhưng nhìn chung là ăn đứt Copilot rồi đấy.

    À! Một cái nữa là tiếng Việt của con này dở tệ. Chả hiểu sao!?

    » Xem thêm
  • smee.io là một cách đơn giản để tạo một địa chỉ webhook và ánh xạ nó về địa chỉ localhost trong máy tính của bạn.

    $ npm install --global smee-client $ smee -u https://smee.io/eu4UoW8vrKSZtTB

    » Xem thêm

Vấn đề

Xác thực người dùng bằng mã token đang ngày càng phổ biến do mô hình client - server được sử dụng rộng rãi. Nếu như trước kia chúng ta thường dùng session hay cookie để xác định phiên người dùng thì giờ đây có thêm một lựa chọn khác là thông qua mã token, đặc biệt là jwt.

Jwt là một chuỗi đùng để định danh, thường là phiên đăng nhập của người dùng. Jwt hoạt động bằng cách kí xác thực vào nội dung được đính kèm trong chuỗi token.

Ví dụ nội chúng ta cần lưu lại những thông tin cơ bản để xác định một người dùng là:

{
    "user_id": 1,
    "role": "user",
}

Jwt sẽ mã hoá thông tin đó kèm theo một "chữ kí", chỉ máy chủ mới có thể xác thực được chuỗi jwt hợp lệ. Một jwt hợp lệ cũng đồng nghĩa với thông tin đi kèm là chính xác.

Trong jwt thuộc tính exp là thời gian hết hạn hết hạn của token, một token đã được kí sẽ đi kèm với thời gian hết hạn. Quá thời gian đó token mới thực sự bị vô hiệu hoá. Jwt được thiết kế để giảm tải việc truy vấn vào cơ sở dữ liệu để tìm kiếm thông tin định danh... Máy chủ chỉ đơn giản xác thực token đó là hợp lệ và lấy ra những thông tin cần thiết.

Vì thế jwt chỉ thực sự bị vô hiệu hoá khi exp đã hết hạn. Vậy thì làm sao để thu hồi lại jwt token khi người dùng đã đăng xuất. Bởi vì bản chất của việc đăng xuất là thoát khỏi phiên, đồng nghĩa với việc token phải không còn hợp lệ

Chỉ cần xóa mã token khỏi trình duyệt

Rõ ràng điều này không có tác dụng gì đối với bảo mật phía máy chủ, nhưng đây là phương pháp đơn giản nhất. Khi áp dụng cách này hãy cầu nguyện rằng hacker sẽ không lấy được mã token của bạn trước khi bạn đăng xuất. Đùa thế thôi bạn chỉ nên áp dụng cách này trong trường hợp bảo mật không quá khắt khe nhé.

Tạo danh sách đen (blacklist)

Bạn có thể lưu trữ các mã token không hợp lệ cho đến ngày hết hạn đã kí vào chúng và so sánh chúng với các yêu cầu đến.

Tuy nhiên, điều này dường như đã phá vỡ nguyên tắc không truy vấn vào cơ sở dữ liệu ngay từ đầu, vì bạn sẽ cần phải truy vấn vào cơ sở dữ liệu cho mọi yêu cầu.

Nhưng dữ liệu lưu trữ có thể sẽ thấp hơn, vì bạn chỉ cần lưu trữ các mã thông báo mà người dùng đã đăng xuất.

Phương pháp này cũng mang lại một rủi ro chính ra bạn vẫn không chắc chắn được rằng liệu token đã bị đánh cắp trước khi bạn đăng xuất ra hay chưa. Hoặc giả sử như trước khi gọi yêu cầu đăng xuất client bị lỗi không truy vấn được tuy nhiên thì đã xoá dữ liệu ở client, điều đó khiến cho token chưa thực sự được đưa vào blacklist ở máy chủ.

Giữ thời gian hết hạn của token trong khoảng thời gian ngắn và làm mới chúng thường xuyên

Nếu đã từng nghe đến refresh token thì đây chính là phương pháp sử dụng refresh token để giảm thời gian hết hạn của token xuống mức thấp nhất có thể.

Giữ thời gian hết hạn của token xuống thấp khiến mã token chỉ tồn tại trong thời gian ngắn, khi đó bắt buộc phải dùng mã refresh token để lấy một mã token mới và cứ xoay vòng như vậy. Giả sử token hoặc refresh token bị rò rỉ chúng ta chỉ cần đưa refresh token đó vào blacklist. Điều này cũng giúp cho việc lưu trữ dữ liệu trong blacklist xuống mức thấp hơn so với lưu lại access token.

Vậy phải làm sao khi mã token của người dùng bị phát hiện là đã rò rỉ?

Trong bất kì trường hợp nào hãy sẵn sàng đối mặt với mã token của người dùng bị rò rỉ và bạn phải xử lý chúng. Một giải pháp đơn giản nhất là làm mất đi hiệu lực của id định danh được lưu trong payload của token. Ví dụ payload bạn kí cho token bao gồm:

{
    "user_id": 1,
    "role": "user",
}

Thì hãy thay đổi id của user là 1 trong cơ sở dữ liệu. Hoặc nếu nghiêm trọng hãy đổi mã bí mật (secret) dùng để kí mã để làm cho các mã token đã phát hành bị mất hiệu lực ngay lập tức.

Dù sao thì cách trên chỉ là bất đắc dĩ, điều tôi muốn nói là hãy chuẩn bị những phương án dự phòng để đối mặt với việc mã token bị rò rỉ bất kì lúc nào. jwt được thiết kế để giảm tải cho máy chủ, tuy nhiên hãy cân nhắc giữa hiệu suất và bảo mật.

Tổng kết

Access Token là một chuỗi được dùng để xác định phiên của người dùng. Khi access token là chuỗi tạo ra theo tiêu chuẩn jwt chúng ta hoàn toàn có thể định danh người dùng mà không cần truy vấn vào cơ sở dữ liệu. Mỗi jwt đi kèm với thời gian hết hạn, nếu chẳng may bị rò rỉ hoặc xử lý token khi người dùng đăng xuất không đúng cách rất có khả năng dữ liệu của người dùng bị tấn công. Chính vì thế hãy thận trọng trong việc xử lý token khi người dùng đăng xuất, đồng thời có những phương án đối mặt với việc mã token bị rò rỉ bất kì lúc nào.

Cao cấp
Hello

5 bài học sâu sắc

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? Hãy bấm vào ngay!

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? Hãy bấm vào ngay!

Xem tất cả

Đăng ký nhận thông báo bài viết mới

hoặc
* Bản tin tổng hợp được gửi mỗi 1-2 tuần, huỷ bất cứ lúc nào.
Author

Xin chào, tôi tên là Hoài - một anh Dev kể chuyện bằng cách viết ✍️ và làm sản phẩm 🚀. Với nhiều năm kinh nghiệm lập trình, tôi đã đóng góp một phần công sức cho nhiều sản phẩm mang lại giá trị cho người dùng tại nơi đang làm việc, cũng như cho chính bản thân. Sở thích của tôi là đọc, viết, nghiên cứu... Tôi tạo ra trang Blog này với sứ mệnh mang đến những bài viết chất lượng cho độc giả của 2coffee.dev.Hãy theo dõi tôi qua các kênh LinkedIn, Facebook, Instagram, Telegram.

Bạn thấy bài viết này có ích?
Không

Bình luận (1)

Nội dung bình luận...
Avatar
Thành Đỗ2 năm trước
Giữ thời gian hết hạn của token trong khoảng thời gian ngắn và làm mới chúng thường xuyên - không hiểu tại sao phải làm thế này trong khi xss có thể lấy được luôn refresh token rồi
Trả lời
Avatar
Thành Đỗ2 năm trước
Ý mình là hacker vẫn lấy được refresh token ấy 
Avatar
Xuân Hoài Tống2 năm trước
Bạn nói đúng có thể lấy đc refresh token nhưng mục đích của refresh token là giữ cho access token có thời gian hết hạn ngắn nhất có thể, nếu chẳng may bị lộ bạn có thể block refresh token thay vì rất nhiều access token có thời gian hết hạn lâu dài mà bạn tạo ra