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?

Tin ngắn hàng ngày dành cho bạn
  • R1 chưa qua, R2 đã tới 😅

    Mặc dù mới đang đồn thổi thôi cơ mà chắc chỉ có Deepseek mới gây tiếng vang tương tự như OpenAI hoặc Anthropic. Mà thứ người dùng quan tâm là chất lượng & giá cả 😄

    Deepseek R2 will be releasing soon

    » Xem thêm
  • Opensource này giúp bạn tạo nhanh một trang cá nhân giới thiệu về bản thân (giống như CV á): self.so

    » Xem thêm
  • Cuộc đua mô hình ngày càng khốc liệt khiến các công ty công nghệ không ai muốn bỏ lại phía sau. Llama 4 Scout, Llama 4 Maverick là hai mô hình mã nguồn mở mới nhất của Meta, được quảng cáo với hiệu năng vượt trội, thậm chí còn đánh bại các mô hình tiên tiến nhất như GPT-4.5, Claude Sonnet 3.7, hay Gemini 2.0 Pro... Nhưng bênh cạnh đó, Scout và Maverick đang vấp phải chỉ trích về việc gian lận. Liệu chúng ta có nên đặt lòng tin vào Meta thêm lần nữa 🤔

    Llama 4 Scandal: Meta’s release of Llama 4 overshadowed by cheating allegations on AI benchmark

    » Xem thêm

Vấn đề

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

Xin chào, chuyện là mấy ngày hôm nay tôi có theo dõi cuộc tranh luận của nhiều người trên mạng về vấn đề sử dụng access token và refresh token như thế nào thì hợp lý. Đọc một lúc thì nhận ra có 2 trường phái rõ rệt: Người thì bảo chỉ cần triển khai access token thôi là đủ. Người thì bảo không ổn, cần phải thêm cả refresh token nữa mới bảo mật. Nhưng nổi trội hơn cả là câu hỏi: Cứ cho là có cả access token và refresh token đi! Thì nên lưu chúng ở đâu trong trình duyệt để đảm bảo độ an toàn tuyệt đối?

Thế là sau nhiều giờ ngồi đọc hết bình luận của mọi người tôi đã tổng hợp được khá nhiều kiến thức. Cả những điều trước mà trước làm không tối ưu cho lắm. Vậy nên chúng ta hãy ngồi lại, cùng nhau đi tìm câu trả lời nhé!

Access token và Refresh token là gì?

Access token không cần phải giới thiệu gì nhiều nữa, access token là một chuỗi ký tự được dùng để xác minh hoặc đại diện cho một người dùng trong hệ thống. Một ví dụ dễ nhận thấy nhất là khi đăng nhập vào trang web nào đó, hệ thống gửi lại một đoạn mã, nhiệm vụ là lưu lại đoạn mã đó cho mỗi lần gọi API sau đó.

Ngày trước, khi PHP còn thịnh hành, các trang web xây dựng bằng PHP chủ yếu được kết xuất (render) phía máy chủ. Thứ mà chúng ta nghe nhắc đến nhiều hơn lúc đó là Session & Cookie. Máy chủ trả về trạng thái xác định một phiên đăng nhập cho trình duyệt, thường là một giá trị của Cookie. Khi truy vấn được gửi đi, Cookie kèm theo giúp máy chủ xác định được lại được phiên của người dùng. Ngày nay, nhờ sự phát triển của nhiều thư viện kết xuất phía máy khách như React, Vue, Svelte... mà chúng ta dần chuyển sang một cơ chế xác nhận phiên mới, đó là sử dụng access token.

Vì vậy về cơ bản, access token cũng chỉ là một đoạn mã được máy chủ trả về nhằm xác định một phiên cho máy khách. Access token có thể lưu lại bất kỳ đâu có thể lưu trữ như Cookie, LocalStorage, SessionStorage... hay trong một tệp tin nào đó. Thế còn refresh token thì sao? Nó có vai trò gì trong hệ thống? Hiểu một cách đơn giản, refresh token được dùng để xin cấp lại một access token mới.

Chờ đã, tại sao lại phải cấp access token mới? Vậy là nó có thời hạn sử dụng phải không? Chúc mừng, bạn đã hiểu đúng vấn đề. Nhưng tại sao phải rối rắm như vậy, chẳng phải chỉ cần như Session & Cookie như trên là đã đủ rồi sao? Nếu muốn biết lý do, trước hết chúng ta hãy tìm hiểu về bài toán uỷ quyền.

Bài toán ủy quyền?

Đối với nhiều trang web, tính năng đăng ký/đăng nhập là điều không thể thiếu vì đó là cách tốt nhất để xác định được một người dùng trong hệ thống. Để đăng nhập thì cần thông tin đăng nhập như email, số điện thoại... kèm theo mật khẩu. Nhưng hàng ngày chúng ta không chỉ dùng một trang web mà có thể là rất nhiều, mỗi trang lại yêu cầu thông tin đăng nhập khác nhau, dần dần nó nhiều đến mức không thể nhớ được hết. Thật tuyệt vời nếu như chỉ cần có một tài khoản mà đăng nhập được ở tất cả mọi nơi. Đó là lúc mà Google, Facebook... xuất hiện. Đã bao giờ bạn để ý đến các nút với lời tựa "Đăng nhập bằng tài khoản Google" chưa? Bấm vào, trang web chuyển hướng sang Google, xác nhận cấp quyền cho phép truy cập thế là quá trình đăng nhập hoàn tất, quá nhanh và nguy hiểm phải không nào! Hầu hết hình thức đăng nhập như thế đều dựa trên đặc tả của OAuth 2.

Với OAuth 2, bạn có thể dễ dàng sử dụng nền tảng khác để đăng nhập vào một trang web có hỗ trợ, đó gọi là uỷ quyền. Uỷ quyền cho một trang web đọc được thông tin tài khoản như họ tên, địa chỉ email, số điện thoại... từ đó biết được bạn là ai và thiết lập một phiên sử dụng mới. Về mặt kỹ thuật, sau khi xác minh được danh tính, máy chủ sẽ quay về luồng xử lý như đăng nhập bằng email với mật khẩu thông thường, chỉ khác là không cần nhập bất kỳ thông tin gì nữa, chỉ cần xác nhận với bên uỷ quyền.

Access token xuất hiện trong đặc tả của OAuth 2. Access token được trả về ngay sau khi uỷ quyền. Tức là ngay khi bấm nút cho phép quyền truy cập, access token được trả về cho trang web đang đăng nhập. Dựa vào đó mà trang web xác thực được bạn là một người dùng trong hệ thống của họ. Tương tự refresh token cũng xuất hiện trong đặc tả của OAuth 2. Access token thường có thời gian tồn tại (TTL) rất ngắn, trong khi refresh token thì thường dài hơn. Khi access token hết hạn, cần phải dùng refresh token để xin một access token mới. Cứ như thế cho đến khi refresh token bị vô hiệu hoá thì không thể xin cấp thêm được nữa.

Ngày nay có rất nhiều trang web xây dựng hệ thống đăng nhập theo đặc tả của OAuth 2 hoặc ít nhất là gần giống. Ngay khi đăng nhập thành công, hệ thống trả về refresh token và access token. Việc của lập trình viên là phải lưu lại 2 thông tin quan trọng này trong trình duyệt để sử dụng cho cuộc gọi mỗi lần sau đó. Đồng thời họ phải xử lý hết hạn, làm mới, vô hiệu hoá... mã truy cập.

Do đó nắm được access token gần như là có luôn tài khoản trong thống nào. Việc bị lộ mã access token là rất nguy hiểm bởi vì kẻ tấn công có thể mạo danh người dùng tương tác với hệ thống mà không hay biết. Chính vì lý do đó access token cần được lưu trữ hoặc bảo vệ một cách nghiêm ngặt nhất có thể. Vậy làm sao để bảo vệ nó tốt nhất? Trước tiên hãy phân tích xem access token có cấu tạo như thế nào.

Access token và JSON Web token

Access token có thể là một chuỗi ký tự bất kỳ. Nhưng hầu hết chúng 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ý (sign) bằ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, payloadsignature. 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à một đối tượng JSON đã được base64 encode. Cuối cùng signature là phần mã hóa của headerpayload kết hợp với khoá 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, bạn đọc tham khảo Introduction to JSON Web Tokens.

Nội dung trong payload có thể giống như ở dưới đây:

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

Khi access token được gửi lên, máy chủ xác nhận tính hợp lệ và bắt đầu đọc thông tin trong payload. Nhờ thế mà biết được người dùng đang sử dụng là ai.

Có một điều đáng chú ý là thông tin trong payload thường chỉ được mã hóa bằng base64, điều đó có nghĩa từ mã JWT có thể trích xuất được thông tin có trong payload. payload chỉ nên chứa thông tin đủ để xác định người dùng, payload không nên chứa thông tin nhạy cảm của người dùng như mật khẩu, số tài khoản...

Tại sao lại cần refresh token?

Như đã nói, access token thường có thời hạn ngắn (để giảm rủi ro bảo mật nếu bị lộ). Khi access token hết hạn, thay vì yêu cầu người dùng đăng nhập lại, ứng dụng có thể dùng refresh token để xin một access token mới một cách tự động và an toàn, giúp trải nghiệm người dùng liền mạch hơn.

Access token mang đầy đủ dữ liệu bên trong, máy chủ không cần lưu trạng thái phiên. Khi nhận được mã truy cập, máy chủ chỉ cần kiểm tra chữ ký và giải mã để lấy thông tin trong payload, không cần cơ sở dữ liệu nào tham gia vào quá trình này. Đây chính là đặc tính không trạng thái (stateless), giúp giảm tải bộ nhớ và truy vấn cho máy chủ, dễ dàng mở rộng quy mô ứng dụng.

Tuy nhiên, điểm mạnh cũng chính là điểm yếu của hệ thống thiết kế theo kiểu không trạng thái: không thể bị thu hồi hoặc thay đổi sau khi đã cấp phát. Nếu một access token bị rò rỉ, kẻ tấn công có thể dùng nó đó để truy cập tài nguyên cho đến khi hết hạn, máy chủ lúc này không thể can thiệp. Để giảm rủi ro này, access token thường được thiết kế chỉ tồn tại trong thời gian ngắn, từ vài phút cho đến vài giờ.

Nhưng nếu access token ngắn hạn như vậy, khi nó hết hạn, người dùng phải đăng nhập lại liên tục, gây ra trải nghiệm rất tệ. Đây chính là lý do cần đến refresh token. Refresh token đóng vai trò như một "vé làm mới" — cho phép ứng dụng xin cấp lại một access token mới một tự động, không cần yêu cầu người dùng đăng nhập lại. Khác với access token, refresh token thường được máy chủ quản lý trạng thái (ví dụ lưu trong cơ sở dữ liệu), vì vậy máy chủ có thể chủ động thu hồi hoặc vô hiệu hóa refresh token bất cứ lúc nào nếu cần (chẳng hạn khi người dùng đăng xuất hoặc có dấu hiệu bị đánh cắp).

Sau khi đã hiểu đặc tả OAuth 2, về cấu tạo vào chức năng của access token, cũng như sự cần thiết của refresh token. Chúng ta sẽ tiếp tục tìm hiểu cách lưu trữ chúng như thế nào cho an toàn và bảo mật nhé!

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

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.

Bình luận (4)

Nội dung bình luận...
Avatar
Tuan Nguyen2 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ống2 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ống2 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 😅