Nếu bạn hỏi bất kỳ một lập trình viên Front-End nào về tính năng gây "đau đầu" và tiêu tốn nhiều thời gian debug nhất, câu trả lời khả năng cao sẽ là luồng xác thực người dùng (Authentication), đặc biệt là việc quản lý vòng đời của Access Token và Refresh Token.
Trong các ứng dụng React thông thường (SPA), việc này vốn đã phức tạp. Nhưng khi bước vào thế giới của NextJS, độ khó còn được nhân lên gấp bội. Nguyên nhân là do NextJS hoạt động trên ba môi trường hoàn toàn khác biệt: Server, Client và Middleware. Làm sao để luồng xác thực diễn ra trơn tru và an toàn trên cả ba mặt trận này?
Thông qua các bài giảng chuyên sâu trong Module 9 của khóa học tại Unicode Academy, chúng ta có thể đúc kết ra một quy trình chuẩn mực và những "kinh nghiệm xương máu" sau đây.

Xử Lý Ở Middleware: "Chốt Chặn" An Ninh Đầu Tiên
Trong NextJS, Middleware chạy trên Edge Server và đóng vai trò như người gác cổng trước khi bất kỳ request nào chạm đến Server Components hay Client UI. Đây là nơi lý tưởng nhất để triển khai Protected Route (Bảo vệ các trang yêu cầu đăng nhập).
-
Kiểm tra tính hợp lệ: Bạn cần bóc tách và kiểm tra tính hợp lệ của token ngay tại Middleware.
-
Xử lý Refresh Token sớm: Thay vì để request đi sâu vào ứng dụng rồi mới báo lỗi 401, Middleware có thể (và nên) nhận diện token hết hạn để thực hiện ngay luồng gọi Refresh Token. Nếu thành công, request sẽ được tiếp tục một cách mượt mà; nếu thất bại, người dùng sẽ được redirect về trang
/loginngay lập tức, tối ưu hóa trải nghiệm và bảo mật.
Bài Toán Đồng Bộ: Chia Sẻ Token Giữa Server Và Client
Một trong những rào cản lớn nhất của NextJS là sự đứt gãy trạng thái (state) giữa môi trường Server và Client.
Kinh nghiệm quan trọng ở đây là thiết lập một cơ chế chia sẻ token an toàn. Khi người dùng đăng nhập thành công hoặc khi token được làm mới, thông tin này không chỉ cần lưu ở HTTP-only Cookies (để Server và Middleware có thể đọc) mà còn cần được đồng bộ mượt mà xuống Client Component.
Sử dụng Context API (hoặc các thư viện quản lý State) kết hợp với các kỹ thuật hydrate dữ liệu từ Server Component truyền xuống Client sẽ giúp ứng dụng luôn giữ được trạng thái đăng nhập thống nhất, tránh tình trạng UI bị giật cục (flickering) hay hiển thị sai trạng thái của người dùng.
Xây Dựng Fetch Wrapper: Giải Pháp Tối Ưu Triệt Để
Nếu ở mỗi file gọi API bạn đều phải viết lại một đoạn code: Lấy token -> Gắn vào header -> Gọi API -> Nếu lỗi 401 thì gọi Refresh Token -> Gọi lại API cũ... thì dự án sẽ nhanh chóng trở thành một mớ bòng bong (Spaghetti code).
Giải pháp "đầu giường" cho mọi dự án NextJS là xây dựng một Fetch Wrapper tùy chỉnh (có thể dùng Axios Interceptors hoặc bọc lại hàm fetch native).
-
Tự động hóa: Wrapper này sẽ chịu trách nhiệm tự động gắn token vào mọi Request gửi đi.
-
Xử lý 401 thông minh: Khi nhận về lỗi 401 Unauthorized, nó sẽ tự động tạm dừng các request đang chờ, âm thầm gọi API Refresh Token, sau đó thực thi lại (retry) các request vừa thất bại.
Bug "Tử Huyệt" - Refresh Token bị gọi nhiều lần:
Đây là một lỗi cực kỳ phổ biến trong thực tế. Tưởng tượng một trang Dashboard của bạn gọi cùng lúc 5 API khác nhau. Khi token hết hạn, cả 5 API này đều trả về 401, dẫn đến việc ứng dụng của bạn spam 5 request gọi Refresh Token cùng một lúc. Điều này không những làm nghẽn server mà còn gây lỗi đồng bộ token nghiêm trọng.
Khóa học hướng dẫn rất chi tiết cách áp dụng kỹ thuật Cờ (Flag) hoặc Queue (Hàng đợi) bên trong Fetch Wrapper để "khóa" (lock) tiến trình này lại: Chỉ duy nhất API đầu tiên bị lỗi 401 được quyền gọi Refresh Token, các API khác sẽ phải nằm chờ trong hàng đợi cho đến khi có token mới, xử lý triệt để tình trạng Race Condition.
Tạm kết: Xử lý Authentication trong NextJS chưa bao giờ là dễ dàng, nhưng khi bạn đã nắm rõ bản chất của Server - Client - Middleware và tổ chức code thông minh qua Fetch Wrapper, mọi thứ sẽ trở nên cực kỳ ổn định. Đây cũng là nền tảng cốt lõi để bạn xây dựng những hệ thống Fullstack bảo mật và chuyên nghiệp.








