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?

Tin ngắn hàng ngày dành cho bạn
  • Cảm ơn threads.net của nhà Meta vì nó là nguồn cảm hứng cho mình tạo ra chuyên mục này trên blog. Ban đầu hơi nghi ngờ về việc liệu tạo ra các bài viết ngắn như thế này có thu hút được người dùng, có ai ngày qua ngày quay trở lại đọc không, hay tất cả chỉ như dã tràng xe cát? Như mình đã nói rất nhiều là làm ra một tính năng không khó, nhưng vận hành nó làm sao cho hiệu quả mới là điều cần phải bận tâm.

    Giờ đây thời gian đã chứng minh tất cả. Chuyên mục Bài viết ngắn luôn đứng trong tốp 5 trang có lượt truy cập nhiều nhất trong ngày/tuần/tháng. Điều đó có nghĩa bạn đọc đã có thói quen quay trở lại nhiều hơn. Tại sao mình lại khẳng định như thế? Vì chuyên mục này gần như không hề được SEO trên các công cụ tìm kiếm như Google.

    Lại kể về thời xa xưa một chút. Thời gian đầu mình rất chịu khó đăng bài trên threads.net với hy vọng thu hút được nhiều người theo dõi, để từ đó khéo léo giới thiệu họ trở thành người dùng blog của mình. Nhưng càng về sau càng thấy "đuối" vì thuật toán của Threads ngày càng không phù hợp với định hướng của mình. Hay nói cách khác là nội dung tạo ra không ăn khách.

    Ví dụ các bài viết của mình thường mang khuynh hướng chia sẻ thông tin, tin tức, hoặc kinh nghiệm cá nhân rút ra sau khi học hoặc làm một cái gì đó. Dường như những bài viết như vậy không được đánh giá cao và thường bị chôn vùi chỉ sau hơn... 100 lượt xem. Hmm... Liệu vấn đề có phải là do mình? Biết thế sao không chịu thay đổi nội dung theo hướng phù hợp hơn với nền tảng?

    Mình đã quan sát Threads, các nội dung dễ lan toả nhất là có yếu tố gây tranh cãi hoặc một định kiến về vấn đề gì đó, đôi khi chỉ đơn giản là phát biểu "ngây ngô" một vấn đề gì đó mà họ biết chắc chắn có tương tác. Mà mình thì gần như là không hề thích định hướng người dùng theo nội dung kiểu này. Mọi người có thể bảo mình bảo thủ, mình chấp nhận. Mỗi người có định hướng nội dung và khán giả khác nhau, lựa chọn nằm ở họ.

    Thế là từ đó mình chủ yếu viết trên này. Chỉ thi thoảng có phát hiện hay lắm thì mới lên Threads "khoe". Ở đây hàng ngày vẫn có người vào đọc, dù cho bạn là ai thì mình tin chắc rằng các bạn nhận ra được thông điệp mà mình muốn truyền tải thông qua mỗi bài viết. Ít nhất chúng ta có chung một định hướng về nội dung. Đôi khi điều sợ nhất không phải là viết ra không ai đọc, mà là họ đọc xong rồi lãng quên trong phút chốc. Số lượng là quan trọng, nhưng chất lượng mới là thứ mang chúng ta lại gần nhau hơn.

    Cảm ơn tất cả 🤓

    » Xem thêm
  • Zed chắc là cộng đồng những nhà phát triển chịu khó lắng nghe người dùng nhất quả đất. Mới đây họ thêm tuỳ chọn để tắt tất tần tật tính năng AI có trong Zed. Trong khi nhiều bên khác đang muốn tích hợp sâu hơn và làm nhiều hơn với AI Agent. Quả là một nước đi táo bạo 🤔

    You Can Now Disable All AI Features in Zed

    » Xem thêm
  • Hôm nay mình đã cố gắng đi hẳn 8k bước trong một phiên để đo lường cho các bạn thấy. Quả là không ngoài dự đoán khi thời gian đi lên đến hơn 1 giờ và quãng đường ~6km 🤓

    À vài hôm nữa là hết tháng, tức là cũng tròn 1 tháng mình bắt đầu thói quen đi bộ mỗi ngày với mục tiêu 8k bước. Để đầu tháng sau mình tổng kết lại xem thế nào luôn ha.

    » 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

Tôi & khao khát "chơi chữ"

Bạn đã thử viết? Và rồi thất bại hoặc chưa ưng ý? Tại 2coffee.dev chúng tôi đã có quãng thời gian chật vật với công việc viết. Đừng nản chí, vì giờ đây chúng tôi đã có cách giúp bạn. Hãy bấm vào để trở thành hội viên ngay!

Bạn đã thử viết? Và rồi thất bại hoặc chưa ưng ý? Tại 2coffee.dev chúng tôi đã có quãng thời gian chật vật với công việc viết. Đừng nản chí, vì giờ đây chúng tôi đã có cách giúp bạn. Hãy bấm vào để trở thành hội viên 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.

Bình luận (1)

Nội dung bình luận...
Avatar
Thành Đỗ3 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
Xuân Hoài Tống3 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

Avatar
Thành Đỗ2 năm trước

Ý mình là hacker vẫn lấy được refresh token ấy