Tại sao cần Refresh Token? Bạn đã biết cách lưu trữ Refresh Token và Access Token an toàn trong trình duyệt chưa?

Tại sao cần Refresh Token? Bạn đã biết cách lưu trữ Refresh Token và Access Token an toàn trong trình duyệt chưa?

Những mẩu tin ngắn hàng ngày dành cho bạn
  • 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
  • javascript.tm được Ryan Dahl - cha đẻ của Node.js tạo ra với mục tiêu trình bày và kêu gọi cộng đồng ủng hộ việc Oracle "giải phóng" cái tên JavaScript, trả lại nó cho cộng đồng.

    Anh cho rằng Oracle sau nhiều thương vụ mua bán đã gián tiếp sở hữu cái tên JavaScript, nhưng họ lại không sử dụng cái tên này. Một điều nữa là JavaScript đã trở thành tên gọi chung, cộng đồng sử dụng rất nhiều mà ít ai biết rằng nó thuộc về Oracle.

    Việc Oracle nắm giữ thương hiệu này gây ra sự nhầm lẫn không cần thiết. Anh kêu gọi Oracle từ bỏ quyền sở hữu, trả nó về với cộng đồng. Nếu được như vậy, nhiều hiểu lầm được xoá bỏ và mọi người sẽ có nhiều quyền hạn với cái tên này. Ví dụ, chúng ta sẽ có một "Hội nghị về JavaScript" trong tương lai mà không phải lo lắng về vấn đề pháp lý.

    Thông tin mới nhất, Vào ngày 22 tháng 11 năm 2024: Anh đã nộp đơn lên USPTO. Chúng ta cùng chờ xem kết quả ra sao nhé! Ngoài ra bạn cũng có thể bày tỏ sự ủng hộ bằng cách truy cập vào địa chỉ ở trên và tiến hành "ký" vào lá đơn 😇

    » Xem thêm
  • Nhớ mấy ngày đầu đi phỏng vấn, có một câu hỏi là JavaScript có phải là Java không? Thì mình trả lời ngay là có 😆. Buồn cười thật, vì đúng ra JavaScript và Java là hai ngôn ngữ khác nhau hoàn toàn.

    Sự nhầm lẫn này mà mới đây đã dẫn đến vụ kiện đòi Oracle trả lại cái tên JavaScript cho cộng đồng. Oracle? Đúng vậy, cái tên liên quan rất mật thiết đến Java, nhưng tại sao lại kiện họ với JavaScript cơ chứ?

    Hic, hôm nay làm việc mệt mỏi quá nên xin phép ngày mai mình kể chi tiết hơn nha vì câu chuyện khá dài đấy 😅

    » Xem thêm

Vấn đề

Lưu ý: Phạm vi bài viết này nói trong khuôn khổ Oauth2 được mô tả tại rfc6749.

Xin chào mọi người, chuyện là mấy ngày hôm nay tôi có đọc một vài tranh luận của mọi người trên mạng về vấn đề sử dụng access token (AT) và refresh token (RT) sao cho hợp lý. Có người thì bảo chỉ cần triển khai AT thôi là đủ, có người thì bảo cần thêm cả RT nữa mới bảo mật. Ngoài ra cũng có những câu hỏi vậy nếu có cả AT và RT thì tôi nên lưu ở đâu trong trình duyệt để đảm bảo độ an toàn tuyệt đối?

Vậy ngày hôm nay, tôi cùng các bạn hãy mổ xẻ lần lượt từng vấn đề để xem thực hư nó là như thế nào nhé!

Access Token và Refresh Token là gì?

Đầu tiên cho những ai chưa biết, AT là một đoạn string (thường là jwt) được dùng để đại diện cho người dùng thao tác vào hệ thống. Ví dụ như khi bạn đăng nhập vào hệ thống sẽ trả về cho bạn một AT, bạn lưu lại mã AT đó cho mỗi lần gọi API sau đó.

Nếu như các trang web được xây dựng theo phong cách server render thì ngoài cách triển khai AT và RT chúng ta còn có thể định phiên người dùng bằng session - cookie. Nhưng xu thế ngày nay đang hướng đến những trang web client render như React, Angular, Vue... thì việc triển khai AT và RT rất là phổ biến.

Còn RT là đoạn mã được dùng để yêu cầu cấp một mã AT mới. Chúng ta hãy làm rõ vấn đề tại sao lại cần phải dùng RT?

Vấn đề ủy quyền là như thế nào?

Đầu tiên hãy làm rõ việc ủy quyền là gì? Thông thường việc xây dựng một website thì tính năng đăng ký/đăng nhập khá phổ biến. Đăng nhập thì bạn sẽ phải nhập một tài khoản + mật khẩu để xác nhận danh tính. Hệ thống xác nhận thông tin bạn nhập là chính xác thì sẽ trả về cho bạn một đoạn mã AT để đại diện cho bạn với một số quyền hạn nhất định trong hệ thống đó.

Hay trong Oauth, vấn đề ủy quyền thì nằm ở chỗ khi bạn bấm vào nút đăng ký/đăng nhập bằng tài khoản Google, Facebook... Hệ thống sẽ chuyển bạn qua một màn hình mà ở đó bạn sẽ phải đồng ý với việc cho phép cho hệ thống kia lấy một số thông tin như email, tên, ngày tháng năm sinh... của bạn. Khi đó thì Google hay Facebook cũng trả về một mã AT mà dựa vào đó, hệ thống kia có thể lấy được những thông tin của bạn phục vụ cho mục đính xác nhận danh tính.

Tóm lại, ủy quyền là việc xác nhận danh tính để lấy được một đoạn mã AT mà dựa vào mã AT đó có thể thay mặt người dùng để sử dụng được hệ thống.

Do đó, đôi khi việc có mã AT gần như là có luôn tài khoản của bạn trong một hệ thống nào đó. Việc bị lộ mã AT là rất nguy hiểm bởi vì kẻ tấn công có thể mạo danh bạn thao tác với hệ thống mà bạn hoàn toàn không hay biết. Chính vì lý do đó mã AT cần được lưu trữ một cách nghiêm ngặt nhất có thể, hoặc nếu không thì hãy giảm thời gian hiệu lực của mã AT lại, ví dụ như mã AT chỉ có hiệu lực trong thời gian 5 phút, hết 5 phút sẽ yêu cầu người dùng đăng nhập lại!? Nếu bạn chọn cách đó thì quả là một trải nghiệm tội tệ cho người dùng.

Mối quan hệ của Access Token và JWT

Một điều cần lưu ý là mã AT thường là mã JWT (json web token). Nó là một tiêu chuẩn để truyền thông tin an toàn giữa các bên với dữ liệu là một đối tượng JSON. Thông tin này có tính tin cậy cao bởi vì nó đã được kí bằng mã bí mật bằng các sử dụng các thuật toán như HMAC, RSA hoặc ECDSA.

jwt

Một đối tượng JWT gồm có 3 phần là header, payload và signature. Trong đó header giữ các thông tin cơ bản về chuỗi JWT như thuật toán dùng để kí, hạn sử dụng... Payload là dữ liệu cần truyền tải là đối tượng JSON đã được base64 encode. Cuối cùng là signature là phần mã hóa của cả hai header và payload kết hợp với mã bí mật cùng thuật toán mã hóa đã được chỉ định ở header.

Để tìm hiểu kĩ hơn về JWT, các bạn có thể đọc thêm ở Introduction to JSON Web Tokens .

Vì những thông tin cần thiết để truyền tải được nằm trong payload thế nên dựa vào payload hệ thống có thể xác định được danh tính của người dùng thông qua nó.

Ví dụ payload của tôi có nội dung như sau:

{
  "id" : 1,
  "username": "hoaitx"
}

Thì khi lên hệ thống sẽ đọc được id của tôi và xác định được tôi là ai.

Có một lưu ý cực kì quan trọng đó là thông tin trong payload chỉ được mã hóa bằng base64, điều đó có nghĩa từ mã JWT tôi có thể trích xuất được những thông tin có trong payload vì thế bạn cần thận trọng trong việc đưa thông tin vào payload trước khi kí chúng. Chắc chắn rằng những thông tin nhạy cảm như password, hay các thông tin cá nhân không cần thiết thì không nên đưa vào.

Khi mã JWT được gửi lên máy chủ có thể dễ dàng xác định được phần chữ kí trong đó có hợp lệ không. Bởi bất kì một thông tin nào trong payload được sửa đổi để gửi lên sẽ kéo theo chữ kí sẽ bị thay đổi theo. Chưa kể đến kẻ tấn công sẽ không bao giờ biết được mã bí mật dùng để kí lại nội dung bị thay đổi đó.

Có nên dùng Refresh Token không?

Tôi sẽ không khuyến khích mọi người nên triển khai RT hay như thế nào. Vì tôi biết có nhiều hệ thống không cần triển khai đến RT mà vẫn hoạt động tốt. Thay vào đó tôi sẽ đưa ra một vài điểm cần chú ý khi sử dụng AT và RT.

Có một vài lý do để AT chỉ nên tồn tại trong thời gian ngắn như:

  • Access Token là một đoạn mã ủy quyền đã được kí bởi máy chủ ủy quyền, máy chủ tài nguyên chỉ cần nhận access token và xác nhận thế nên thời gian càng ngắn thì nguy cơ access token khi bị lộ càng ít rủi ro.
  • Nếu thời gian hợp lệ của AT quá dài, khi bị lộ AT thì rủi ro cao hơn vì t kẻ gian có nhiều thời gian hơn để khai thác, đồng thời có thể bạn ko biết rằng AT đã bị lộ.
  • Hãy tưởng tượng nếu bạn cho phép người dùng tạo quá nhiều mã AT, lúc đó nếu muốn vô hiệu hóa những mã AT còn lại thì bạn phải đánh dấu nó trong cơ sở dữ liệu. Hay nói cách khác là bạn cần phải lưu lại những mã AT đã được tạo ra.

Có một vài lý do để RT được sử dụng như:

  • Rút ngắn thời gian tồn tại của AT, khi AT bị hết hạn thì sử dụng RT để lấy mã AT mới.
  • Bạn cần phân biệt được máy chủ ủy quyền và máy chủ tài nguyên. Máy chủ ủy quyền có nhiệm vụ cung cấp mã RT và kí mã AT để đại diện cho người dùng. Máy chủ tài nguyên nhận mã đã kí từ máy chủ ủy quyền để có quyền như người dùng đang thao tác với dữ liệu của họ trên hệ thống như thông tin tài khoản, dữ liệu... Máy chủ ủy quyền và máy chủ tài nguyên có thể là một. RT thường được lưu trữ ở máy chủ ủy quyền phục vụ cho mục đích cấp mã AT mới. Còn mã AT được dùng ở máy chủ tài nguyên, dùng để định danh một người dùng.
  • Bạn không cần phải lưu lại nhiều AT, nếu muốn chấm dứt phiên chỉ đơn giản là vô hiệu hóa mã RT trên máy chủ ủy quyền.

Sau khi hiểu được những lý do trên thì việc sinh ra RT giúp giải quyết được một vài hạn chế khi chỉ sử dụng mỗi AT. Nhưng như vậy nếu mã AT hoặc RT bị lộ thì rủi ro sẽ rất cao sao? Và các lưu trữ chúng như thế nào thì mình xin viết tiếp ở phần sau.

Xem tiếp phần 2: Tại sao cần Refresh Token? Bạn đã biết cách lưu trữ Refresh Token và Access Token an toàn trong trình duyệt chưa? Phần 2 .

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.
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 (4)

Nội dung bình luận...
Avatar
Tuan Nguyen1 năm trước
Giả sử rằng: Nếu bị lộ Refresh Token thì sao ? Hacker có thể dùng Refresh Token để "xin" Access Token mới và từ đó sử dụng Access Token để truy cập vào những nội dung không mong muốn. Trong mỗi request được gửi lên (giả sử token được lưu trong cookie hoặc một nơi nào đó) thì request đó luôn bao gồm một cặp Refresh Token + Access Token. Vậy nếu bị "nhảy mất" cái request đó thì có đảm bảo rằng Access Token đó sẽ an toàn (Expired ư ? => Đã có Refresh Token lo hết ). Từ đó khẳng định rằng "nên thời gian càng ngắn thì nguy cơ access token khi bị lộ càng ít rủi ro." khá là thiếu căn cứ.
Trả lời
Avatar
Xuân Hoài Tống1 năm trước
Bonus: AT sinh ra để giảm thiểu gánh nặng trên máy chủ tài nguyên, việc còn lại là gánh nặng của máy chủ ủy quyền nên RT phải làm chặt chẽ hơn. Cụ thể phải từ RT để lấy AT nên AT tồn tại càng ngắn thì càng tốt, bắt buộc phải qua máy chủ ủy quyền để kiểm tra gian lận. Dĩ nhiên là khoảng thời gian "ngắn" đó chỉ mang tính tương tối cho các dự án.
Avatar
Xuân Hoài Tống1 năm trước
Trường hợp bạn nêu trên thì đúng là "thiếu căn cứ" theo như bạn nói. Nhưng đó là trong trường hợp RT + AT được gửi lên trong "mỗi" request. Thực tế thì bạn không nhất thiết phải gửi lên RT trong các yêu cầu đến máy chủ tài nguyên. RT chỉ nên được gửi đến máy chủ ủy quyền (nhiều người hay bị nhầm giữa máy chủ tài nguyên & máy chủ ủy quyền, cũng có thể do máy chủ tài nguyên + ủy quyền là một) để xin AT mới. Thế nên có một vài lý do để bảo mật RT hơn AT để hạn chế RT bị rò rỉ. Nhưng phải nói khi AT bị đánh cắp thì RT bị "bay" theo cũng rất lớn. Chính vì thế chúng ta phải có biện pháp mạnh trên máy chủ ủy quyền để phát hiện RT bị đánh cắp. Vấn đề này cũng có nhiều giải pháp rồi bạn có thể tham khảo các nguồn trên GG, tôi đang tiếp tục series bài viết về AT & RT chỉ là chưa sắp xếp được thời gian, khi nào có mong bạn tiếp tục xem có vấn đề gì cần làm sáng tỏ hơn nữa không.
Avatar
Đình Trung2 năm trước
@gif [XejFQNGS90SvaITLRZ] Mấy tháng rồi nhỉ
Trả lời
Avatar
Long Domi2 năm trước
@gif [10JhviFuU2gWD6] Sắp có từ một tháng trước
Trả lời
Avatar
Linh Trịnh Mạnh2 năm trước
Ủa phần tiếp theo đâu anh ơi đang cuốn mà hóng mãi không thấy
Trả lời
Avatar
Xuân Hoài Tống2 năm trước
Sắp có rồi bạn 😅