1526 words
8 minutes
access-refresh-token

10 vạn câu hỏi vì sao về Refresh token và Access token#

Đây là 2 khái niệm rất là quen thuộc với dev: access token là dùng để xác thực quyền của user còn refresh token dùng để làm mới access token. Vì access token thường có TTL (time to live) ngắn khoảng từ 5-15 phút nên cần refresh token để user có thể tạo access token mới mà không cần phải login lại.Refresh token thì sẽ có TTL dài hơn, khoảng 1 tiếng tới 1 ngày tùy vào hệ thống.

Câu hỏi thứ 1#

Câu hỏi thứ 1 đặt ra là: tại sao không đặt TTL của access token lâu vào để không phải cần refresh token làm gì?

Nếu tìm kiếm google hay thậm chí là tra chatgpt thì câu trả lời đa số sẽ là: để tăng độ bảo mật nếu lỡ như access token của user bị lộ hay đánh cắp thì kẻ cắp sẽ chỉ có thể có 1 thời gian rất ngắn để thao tác với access token đó, hạn chế khả năng rỏ rỉ thông tin user hoặc hệ thống.

Câu hỏi thứ 2#

Sử dụng refresh token có TTL lâu để access token có thể có TTL ngắn, vậy lỡ như refresh token bị lộ/đánh cắp thì sao?

Thì khi đó kẻ cắp có thể tạo mới lại access token liên tục và mãi mãi. Nếu token bị đánh cắp có quyền sudo/admin thì coi như xong, hết cứu.

Câu hỏi thứ 3#

Nếu cả 2 đều có khả năng bị đánh cắp thì sinh thêm refresh token làm chi, có thấy tăng tính bảo mật lắm đâu mà chỉ thấy có nguy cơ cao hơn?

Nếu tìm kiếm google hay thậm chí là tra chatgpt thì câu trả lời đa số sẽ là: vì access token được đính kèm và gửi đi ở mỗi request nên khả năng bị đánh cắp sẽ cao hơn là refresh token vì refresh token chỉ được gửi đi khi access token hết hạn.

Và vì refresh token được lưu ở dưới database nên server có thể thu hồi refresh token đó lại nếu phát hiện có hành vi bất thường.

Câu hỏi thứ 4#

Câu hỏi thứ 4 đặt ra là: nếu tìm kiếm ở google hay thậm chí là tra chatgpt rằng nên lưu refresh token ở đâu thì câu trả lời đa số sẽ là: lưu trong Http cookie để tăng cường bảo mật.

Nhưng data của cookie sẽ được gửi kèm theo với mọi request, vậy thì refresh token sẽ được gửi đi liên tục, tăng khả năng bị đánh cắp giống như access token.

Câu hỏi thứ 5#

Vậy thì sao không dùng cơ chế Session ID truyền trong cookie để thay thế cho access token và refresh token luôn cho gọn? Session ID có thể có TTL dài hơn access token, và server có thể thu hồi session ID bất cứ lúc nào giống như refresh token.

Câu hỏi thứ 6#

Vậy rồi cuối cùng có refresh token cũng bằng thừa hả? Bảo mật thì không tăng, cái tăng duy nhất chắc là tăng độ phức tạp ở code.

Những câu hỏi trên là những câu hỏi tồn tại đã rất lâu trong đời mình kể từ khi biết về 2 khái niệm access token và refresh token. Nhưng mà không hiểu sao khi mà mình tìm kiếm trên google, stackoverflow, forum,… hay là cả chatgpt thì câu trả lời đều đi vào vòng lặp vô hạn ở 5 câu hỏi trên, đều không giải thích được rõ ràng thật sự thì lý do nên tồn tại 1 lúc 2 thằng token này để làm gì. Vì 2 khái niệm này rất là phổ biến nên chắc chắn phải có 1 lý do hợp lý đằng sau đó chứ không thể nào mà kiểu “đẻ” ra cho vui được.

SO WHY????#

Thực ra lý do thường dẫn đến sự khó hiểu khi đụng vào 2 loại key này là đến từ việc hiểu sai bản chất của chúng ngay từ thuở ban đầu. Access và Refresh token chỉ thực sự mang lại hiệu quả khi application của chúng ta có 2 thành phần riêng biệt: Resource Server (RS) và Authorization Server (AS). Theo như tài liệu của OAuth 2.0 về Authorization Framework thì 1 hệ thống Authorization hoàn chỉnh sẽ bao gồm các thành phần: resource owner, client, authorization serverresource server. Luồng hoạt động chính sẽ như sau:

 +--------+                                           +---------------+
  |        |--(A)------- Authorization Grant --------->|               |
  |        |                                           |               |
  |        |<-(B)----------- Access Token -------------|               |
  |        |               & Refresh Token             |               |
  |        |                                           |               |
  |        |                            +----------+   |               |
  |        |--(C)---- Access Token ---->|          |   |               |
  |        |                            |          |   |               |
  |        |<-(D)- Protected Resource --| Resource |   | Authorization |
  | Client |                            |  Server  |   |     Server    |
  |        |--(E)---- Access Token ---->|          |   |               |
  |        |                            |          |   |               |
  |        |<-(F)- Invalid Token Error -|          |   |               |
  |        |                            +----------+   |               |
  |        |                                           |               |
  |        |--(G)----------- Refresh Token ----------->|               |
  |        |                                           |               |
  |        |<-(H)----------- Access Token -------------|               |
  +--------+           & Optional Refresh Token        +---------------+

2 loại token này được thiết kế để phục vụ cho bài toán ủy quyền theo chuẩn OAuth2: User cho phép App A (Client) truy cập dữ liệu của mình ở App B (Resource) thay mặt mình. Vì App A là “người lạ”, nên App B cần cấp Access Token ngắn hạn để hạn chế rủi ro, và Refresh Token để App A xin lại quyền mà không cần User nhập lại pass. Ví dụ khi đăng nhập bằng Google trên 1 app bên thứ 3, Google sẽ đóng vai trò là Authorization Server, app bên thứ 3 sẽ là Client, và dịch vụ mà app bên thứ 3 muốn truy cập (ví dụ Gmail, Google Drive) sẽ là Resource Server.

Lý do chính khi có 2 thành phần riêng biệt này (access và refresh token) là để tăng tính scalabilitysecurity cho hệ thống authorization (mail của các dev ở IETF khi đang nói về mục đích của refresh token ở OAuth2 năm 2011):

  • Security: Access token có TTL ngắn hạn giúp giảm thiểu rủi ro khi token bị đánh cắp. Nếu access token bị lộ, kẻ tấn công chỉ có thể sử dụng nó trong một khoảng thời gian ngắn trước khi nó hết hạn. Refresh token chỉ được gửi về authorization server, không bao giờ được gửi đến resource server, do đó giảm nguy cơ bị lộ token dài hạn.

  • Scalability: Access token có thể được xác thực ngay tại resource server mà không cần phải gọi về authorization server để kiểm tra (token như jwt dùng secret hay public/private key để verify). Điều này giúp giảm tải cho authorization server. Refresh token chỉ được gửi về authorization server để lấy access token mới khi access token hết hạn.

Vì vậy nên các câu hỏi ở trên đều không thể trả lời thỏa đáng nếu không hiểu rõ về kiến trúc của hệ thống authorization với 2 thành phần riêng biệt này. Nếu chỉ có 1 mình access token dài hạn thì bảo mật sẽ kém, nếu ngắn hạn thì client phải gọi về authorization server liên tục để lấy token mới, làm server quá tải vì phải truy cập DB để write token mới liên tục (cần phải write token mới xuống DB vì nếu không sẽ không thể thu hồi khi token bị đánh cắp).

Ngoài ra còn 1 lý do là để đảm bảo stateless cho resource server vì nếu chỉ có 1 access token dài hạn thì resource server sẽ phải giữ trạng thái (stateful) để biết token nào còn hiệu lực, token nào bị thu hồi. Khi có thêm refresh token thì chỉ có mỗi authorization server mới cần giữ trạng thái về refresh token, resource server có thể hoàn toàn không cần giữ trạng thái về access token nữa.

Vì sao người mới tiếp xúc sẽ dễ bị khó hiểu?#

Vì các hướng dẫn ‘mì ăn liền’ ở trên google, youtube về cách triển khai authorization cho ứng dụng web thường chỉ viết 1 ứng dụng monolithic duy nhất, bao gồm cả resource serverauthorization server trong cùng 1 ứng dụng. Điều này khiến cho việc tách ra 2 loại token trở nên không cần thiết, mô tả dưới dạng ascii như sau:

+--------+                                           +-----------------------------+
|        |--(A)------- Login / Auth Grant ---------->|                             |
|        |                                           |      SERVER APPLICATION     |
|        |<-(B)----------- Access Token -------------|                             |
|        |               & Refresh Token             |   +---------------------+   |
|        |                                           |   | Authorization Logic |   |
|        |--(C)---- Access Token (Request) --------->|   +---------------------+   |
|        |                                           |              |              |
| Client |<-(D)- Protected Resource (Response) ------|   (Internal Function Call)  |
|        |                                           |              |              |
|        |--(E)---- Access Token (Expired) --------->|   +---------------------+   |
|        |                                           |   |    Resource Logic   |   |
|        |<-(F)- Invalid Token Error ----------------|   +---------------------+   |
|        |                                           |                             |
|        |--(G)----------- Refresh Token ----------->|                             |
|        |                                           |                             |
|        |<-(H)----------- Access Token -------------|                             |
+--------+           & Optional Refresh Token        +-----------------------------+

Tham khảo#

Mail từ các dev ở IETF bàn luận về OAuth2 năm 2011: https://web.archive.org/web/20150213065559/http://www.ietf.org/mail-archive/web/oauth/current/msg06679.html https://web.archive.org/web/20150723164112/http://www.ietf.org/mail-archive/web/oauth/current/msg06680.html https://web.archive.org/web/20150723164112/http://www.ietf.org/mail-archive/web/oauth/current/msg06684.html https://web.archive.org/web/20150213065609/http://www.ietf.org/mail-archive/web/oauth/current/msg06685.html https://web.archive.org/web/20160105061623/http://www.ietf.org/mail-archive/web/oauth/current/msg06686.html https://web.archive.org/web/20160221101152/http://www.ietf.org/mail-archive/web/oauth/current/msg06687.html https://web.archive.org/web/20151126162306/http://www.ietf.org/mail-archive/web/oauth/current/msg06688.html https://web.archive.org/web/20151126162306/http://www.ietf.org/mail-archive/web/oauth/current/msg06689.html https://web.archive.org/web/20160502175024/http://www.ietf.org/mail-archive/web/oauth/current/msg06690.html https://web.archive.org/web/20151126162306/http://www.ietf.org/mail-archive/web/oauth/current/msg06691.html https://web.archive.org/web/20160502181318/http://www.ietf.org/mail-archive/web/oauth/current/msg06692.html

Stackoverflow: https://stackoverflow.com/questions/3487991/why-does-oauth-v2-have-both-access-and-refresh-tokens/57503520#57503520:~:text=The%20lifetime%20of%20a%20refresh%20token%20is%20up%20to%20the%20(AS)%20authorization%20server%20%E2%80%94%20they%20can%20expire%2C%20be%20revoked%2C%20etc.%20The%20difference%20between%20a%20refresh%20token%20and%20an%20access%20token%20is%20the%20audience%3A%20the%20refresh%20token%20only%20goes%20back%20to%20the%20authorization%20server%2C%20the%20access%20token%20goes%20to%20the%20(RS)%20resource%20server.

https://stackoverflow.com/questions/10703532/whats-the-point-of-refresh-token

access-refresh-token
https://nhamnhi.toilacube.io.vn/posts/access-refresh-token/
Author
toilacube
Published at
2025-10-13
License
CC BY-NC-SA 4.0