AI Agents

Xây Dựng Google OAuth Authentication Giữa Next.js Frontend và Headless CMS Backend

By Ginbok5 min read

Tổng Quan

Khi xây dựng một nền tảng nội dung hiện đại, một trong những thách thức kiến trúc thú vị nhất là kết nối Next.js frontend với headless CMS backend cùng trải nghiệm xác thực mượt mà. Trong bài viết này, chúng tôi chia sẻ cách triển khai Google OAuth authentication cho visitor — hoàn toàn tách biệt khỏi hệ thống admin CMS — sử dụng luồng JWT tùy chỉnh.

Bài Toán Hai Hệ Thống

Stack của chúng tôi có hai lớp riêng biệt:

CMS có hệ thống xác thực admin tích hợp sẵn (cookie-based). Chúng tôi cần thêm visitor authentication riêng biệt — dùng Google Sign-In — mà không ảnh hưởng đến phiên admin CMS. Điều này có nghĩa là chạy hai hệ thống auth song song trên cùng một cơ sở dữ liệu ASP.NET Identity.

Kiến Trúc Tổng Quát


┌───────────────────────┐         ┌───────────────────────────┐
│   Next.js Frontend    │         │   CMS Backend (ASP.NET)   │
│                       │         │                           │
│  AuthProvider         │◄───────►│  /api/auth/*              │
│  (React Context)      │  JWT    │  GoogleAuthService        │
│                       │  Cookie │  JwtService               │
│  GoogleLoginButton    │         │                           │
│  UserMenu             │         │  ASP.NET Identity         │
│  AuthGuard            │         │  (Users + Roles)          │
└───────────────────────┘         └───────────────────────────┘
           │                                 │
           └──────── Google OAuth ───────────┘

Ba Authentication Scheme Cùng Tồn Tại

Backend đăng ký ba authentication scheme hoạt động hòa bình:

  1. Default Cookie Scheme — do CMS framework xử lý cho admin login. Chúng tôi không bao giờ đụng vào đây.
  2. Google OAuth Scheme — chỉ dùng trong quá trình OAuth callback. Cookie tạm ngắn hạn (GoogleExternalCookie) chuyển kết quả Google sang callback handler.
  3. JWT Bearer Scheme — đọc JWT từ httpOnly cookie (auth_token) cho tất cả API endpoint dành cho visitor.

Luồng Đăng Nhập: Từng Bước

1. User Click "Sign in with Google"

Nút này gọi một hàm đơn giản chuyển hướng trình duyệt đến backend login endpoint, kèm URL trang hiện tại làm returnUrl:

GET /api/auth/google-login?returnUrl=https://yoursite.com/blog/some-post

2. Backend Challenge Google

Backend phát ra Challenge(GoogleDefaults.AuthenticationScheme), chuyển hướng user đến màn hình đồng ý của Google. returnUrl được lưu trong authentication properties.

3. Google Callback

Sau khi user chấp nhận, Google redirect về /api/auth/google-callback. Backend:

  1. Xác thực kết quả qua Google scheme
  2. Gọi FindOrCreateUserAsync() để xử lý tài khoản visitor
  3. Tạo JWT token với user claims (tên, avatar, roles)
  4. Set httpOnly cookie (auth_token, thời hạn 7 ngày)
  5. Dọn dẹp temporary OAuth cookie
  6. Redirect về trang frontend ban đầu

4. Frontend Khôi Phục Session

Sau khi redirect, AuthProvider (React Context) chạy lúc mount và gọi GET /api/auth/me với cookie tự động đính kèm. Backend validate JWT, lấy profile và trả về. UI cập nhật hiển thị trạng thái đã đăng nhập.

Xử Lý Tài Khoản: Find or Create

Phương thức FindOrCreateUserAsync xử lý ba kịch bản mỗi lần Google login:

  1. Returning user (đã link Google) — Tìm bằng Google provider ID trực tiếp. Đường đi nhanh nhất.
  2. Tài khoản đã có cùng email — Tự động link Google login vào tài khoản hiện có (với non-admin).
  3. User mới — Tạo visitor account mới, gán role Visitors, link Google login.

Vòng Đời Session Trên Frontend

React context AuthProvider quản lý toàn bộ session lifecycle:

Thiết Kế JWT Token

JWT là self-contained và bao gồm:

Token được giao và đọc qua httpOnly cookie — JavaScript trên frontend không bao giờ chạm đến raw token. JwtBearer middleware đọc trực tiếp từ cookie trong mỗi API request.

Bảo Vệ Route

Trên frontend, component AuthGuard bọc các trang cần xác thực. Nó kiểm tra trạng thái auth từ context và redirect user chưa đăng nhập về trang chủ. Loading state được hiển thị trong khi session đang được xử lý.

Trên backend, bất kỳ endpoint nào cần xác thực được đánh dấu với:

[Authorize(AuthenticationSchemes = "JwtBearer")]

Điều này sử dụng JWT scheme một cách tường minh, hoàn toàn tách biệt khỏi CMS admin scheme.

Những Điểm Rút Ra

#next.js#asp.net-core#google-oauth#jwt#authentication#headless-cms#architecture
← Back to Articles
Tìm hiểu cách triển khai Google OAuth authentication giữa Next.js frontend và headless ASP.NET Core CMS backend sử dụng JWT httpOnly cookie, React Context và named authentication schemes. - Ginbok