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
  • Hôm qua đến nay, lượt truy cập tới từ Facebook tăng đột biến. Thường như thế là do ai đó chia sẻ bài viết của blog vào một nhóm nào đó.

    Cơ mà lần này là liên kết trực tiếp đến trang chủ luôn. Tò mò ghê, không biết ai chia sẻ, chia sẻ ở đâu nữa. Muốn biết để tìm hiểu "insight" ghê 🥹

    » Xem thêm
  • Mình mới phát hiện ra thư viện idb-keyval giúp triển khai cơ sở dữ liệu dạng key-value một cách đơn giản. Như đã chia sẻ trong chuỗi bài viết về quá trình làm OpenNotas, mình loay hoay đi tìm một loại cơ sở dữ liệu để lưu trữ mà xem chừng vất vả quá, cuối cùng chốt localForage.

    idb-keyval cũng tương tự như localForage nhưng có vẻ như nó đang làm tốt hơn một chút. Đơn cử là có hàm update để cập nhật dữ liệu, hình dung đơn giản là:

    update('counter', (val) => (val || 0) + 1);

    Chứ không như hàm set là thay thế dữ liệu mất tiêu luôn.

    » Xem thêm
  • Đầu xuân năm mới, xin phép khoe số tiền kiếm được sau 1 tháng đặt quảng cáo tại indieboosting.com 🥳🥳🥳

    » 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 Đỗ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
Bấm hoặc cuộn mạnh để sang bài mới