1 Hệ thống sẽ quản lý Access Token và Refresh Token thế nào
Nếu chỉ chém gió lý thuyết suông thì ai cũng có thể dùng chatgpt để phét lác về cách Facebook, Google quản lý AT và RT ra làm sao. Tuy nhiên ai trong ngành cũng đều hiểu 1 điều là nếu ko tận tay gõ từng dòng code thì lý thuyết càng cao xa lại càng trở nên vô nghĩa. Cho nên bàn ở đây là dựa trên chính kinh nghiệm của mình, bằng vào chính trang web của mình, tất cả đều có cơ sở thực tiễn cả.
15/02/2025•N V Tuấn
Khái niệm Access Token (AT) và Refresh Token (RT) đã quá phổ biến thiết nghĩ không cần thiết phải nhắc lại làm gì cho dài dòng. Việc quản lý chúng ra làm sao thì có vô số cách làm, tùy thuộc vào hệ thống, vào yêu cầu bảo mật hay cả nguồn lực tài nguyên. Ở đây mình muốn bàn đến 1 giải pháp cân bằng nhất có thể, tất nhiên khái niệm cân bằng cũng còn tùy quan điểm hay tùy cả vào hệ quy chiếu khác nhau, có lẽ nên dùng từ đủ dùng thay cho từ cân bằng thì đúng hơn.
Nếu chỉ chém gió lý thuyết suông thì ai cũng có thể dùng chatgpt để phét lác về cách Facebook, Google quản lý AT và RT ra làm sao. Tuy nhiên ai trong ngành cũng đều hiểu 1 điều là nếu ko tận tay gõ từng dòng lệnh thì lý thuyết càng cao xa lại càng trở nên vô nghĩa. Cho nên bàn ở đây là dựa trên chính kinh nghiệm của mình, bằng vào chính trang web của mình, tất cả đều có cơ sở thực tiễn cả.
Đã là nguyên tắc rồi, chắc chắn AT và RT đều phải được lưu vào cookie, chứ ko ai lại đi lưu vào localstorage bao giờ cả, rất ít trường hợp thiếu chuyên nghiệp như vậy. Khi Login backend trả về AT và RT dưới dạng data body của response. Frontend lúc này sẽ quyết định lưu AT và RT ở đâu.
Đến đây có 2 trường hợp, nếu Frontend chỉ có dạng client side như ReactJS thì khi lưu Token vào cookie sẽ ko thể đặt httpOnly được. Nhưng nếu Frontend có thêm Server side kiểu NextJS thì sẽ có thể đặt httpOnly để giúp cho token bảo mật hơn. Nhưng lúc này vấn đề phát sinh là phía client side lại không thể lấy được token từ cookie để sử dụng vào việc gọi api đến backend, do thuộc tính httpOnly ko cho phép. Cho nên cách đơn giản nhất là tạo 1 context để lưu AT ngay từ lần đầu đăng nhập. Mỗi lần F5 lại trang thì context cũng bị clear đi thì Server Next sẽ lấy AT từ cookie được trình duyệt đính kèm mặc định theo request và truyền vào context cho client side sử dụng. Cho nên khi gọi api đến backend thì client side sẽ dùng AT trong context còn Server side sẽ dùng AT trong cookie. Đấy là AT thế còn RT thì sao.
RT tất nhiên cũng được lưu trong cookie của trình duyệt, khi nào AT hết hạn thì dùng RT để đổi AT mới. Đổi thì có nhiều cách đổi, nếu backend trả về cụ thể lỗi AT hết hạn thì Frontend sẽ dùng RT đổi AT mới. Nhưng để tránh việc gây ra gián đoạn khiến người dùng phải chờ lâu bất thường thì có thể check hạn của token theo định kỳ, cứ cách 1 khoảng thời gian lại check 1 lần, nếu sắp hết hạn thì tự động gọi ngầm api đổi AT mới.
Việc dùng Token để xác thực có nhược điểm là backend sẽ khó kiểm soát user hơn khi đã phát ra token mà không thể thu hồi. Nếu muốn quản lý thì phải lưu lại AT và kiểm tra ở mỗi request, nhưng cách này sẽ làm tăng gánh nặng đáng kể lên server. Giải pháp cân bằng là chỉ lưu RT vào csdl, thường là ở ngay bảng user. Nếu chặn người dùng thì có thể xóa RT đi thì người dùng chỉ còn AT với thời gian rất ngắn, dù còn RT trong cookie cũng ko thể đổi AT mới nếu backend kiểm tra thấy RT trong csdl đã bị xóa. Như vậy là đã hạn chế được rất nhiều rủi ro rồi.
Mọi người thường nói đến việc RT chỉ có mục đích là để đổi AT mới mà rất ít đề cập đến 1 tác dụng khác của nó là để duy trì đăng nhập. Việc lưu token vào cookie còn có thể hẹn giờ cho trình duyệt tự động xóa chúng đi. Với AT thời gian sống do backend quy định cho nó rất ngắn, thì thời gian hẹn giờ để trình duyệt tự động xóa nó tối đa cũng chỉ bằng thời gian sống thực của nó, thậm chí có thể ít hơn. Cho nên việc duy trì đăng nhập hoàn toàn là dựa vào thời gian của RT.
Mỗi lần truy cập lại trang web, tức là thực hiện 1 request đến Server side của frontend, nếu còn RT trong cookie thì có nghĩa là user này vẫn còn trên trình duyệt, Server side sẽ báo cho client side biết và gọi api đổi AT mới. Frontend có AT mới rồi thì cũng là đã login trở lại.
Nói ra thì rất lằng nhằng, nhưng nếu tóm gọn lại thì cũng vẫn lằng nhằng vậy thôi. Tóm lại là mình muốn nhấn mạnh về tầm quan trọng của Frontned khi dùng server side hay client có tác động rất lớn đến cách quản lý Token. Thế thôi.