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à… không còn sau đó nữa nếu trường hợp tệ nhất là token bị đánh cắp có quyền sudo/admin.
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 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 server và resource 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 +---------------+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 scalability và security 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. Đ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.
There is a scalability reason, in that the access_token could be verifiable on the resource server without DB lookup or a call out to a central server, then the refresh token serves as the means for revoking in the “an access token good for an hour, with a refresh token good for a year or good-till-revoked.”
There is a security reason, the refresh_token is only ever exchanged with authorization server whereas the access_token is exchanged with resource servers. This mitigates the risk of a long-lived access_token leaking (query param in a log file on an insecure resource server, beta or poorly coded resource server app, JS SDK client on a non https site that puts the access_token in a cookie, etc) in the “an access token good for an hour, with a refresh token good for a year or good-till-revoked” vs “an access token good-till-revoked without a refresh token.”
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 server và authorization server trong cùng 1 ứng dụng. Điều này
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
https://stackoverflow.com/questions/10703532/whats-the-point-of-refresh-token