1. 08:29 14/10/2026
1. Tổng quan
Việc thống nhất xác thực giữa ứng dụng web (Next.js) và ứng dụng di động (React Native/Expo) giúp giảm thiểu sai sót, dễ dàng bảo trì và tuân thủ các tiêu chuẩn bảo mật hiện đại. OAuth 2.0 kết hợp PKCE (Proof Key for Code Exchange) là lựa chọn phổ biến vì nó loại bỏ việc lưu client secret trên thiết bị khách và chống tấn công mã hóa mã ủy quyền.
2. Kiến trúc luồng chung
- Authorization Server: Cung cấp endpoint /authorize, /token, /revoke, /userinfo (ví dụ: Keycloak, Auth0, hoặc tự host).
- Client Web (Next.js): Sử dụng Authorization Code Flow với PKCE, lưu access token trong httpOnly cookie, refresh token trong secure cookie.
- Client Mobile (Expo): Cùng flow, nhưng lưu token trong SecureStore (iOS) / EncryptedSharedPreferences (Android).
- Backend API: Xác thực bằng cách kiểm tra JWT access token (RS256) và validate scopes.
3. Triển khai chi tiết
**3.1. Tạo code_verifier & code_challenge**
- Tạo chuỗi ngẫu nhiên 43‑128 ký tự (base64url).
- code_challenge = SHA256(code_verifier) → base64url.
- Gửi code_challenge và method=S256 khi gọi /authorize.
**3.2. Yêu cầu mã ủy quyền**
- Web: Redirect trình duyệt đến /authorize với response_type=code, client_id, redirect_uri, scope, state, code_challenge.
- Mobile: Mở ASWebAuthenticationSession (iOS) hoặc Chrome Custom Tab (Android) với cùng tham số. Tránh dùng WebView thuần túy để tận dụng hệ thống quản lý cookie của OS.
**3.3. Trao đổi mã lấy token**
- Gửi POST /token với grant_type=authorization_code, code, redirect_uri, client_id, code_verifier.
- Server trả về access_token, refresh_token, id_token (nếu có).
**3.4. Lưu trữ và sử dụng token**
- Web: Set‑Cookie: HttpOnly; Secure; SameSite=Lax cho access_token, SameSite=Strict cho refresh_token.
- Mobile: Lưu vào SecureStore/EncryptedSharedPreferences; gắn Authorization: Bearer <access_token> cho mọi request API.
**3.5. Làm mới token**
- Khi access_token hết hạn, client gửi POST /token với grant_type=refresh_token, refresh_token, client_id (web không cần client_secret).
- Xoay vòng refresh_token (rotate) và thu hồi token cũ để giảm rủi ro rò rỉ.
4. Mẹo và cạm bẫy thường gặp
- Luôn kiểm tra state parameter để chống CSRF.
- Đặt redirect_uri chính xác (bao gồm scheme cho mobile, ví dụ: myapp://callback) và đăng ký whitelist ở Authorization Server.
- Không log access_token hay refresh_token ở bất kỳ nơi nào (console, file log, Sentry).
- Sử dụng short‑lived access token (5‑15 phút) và long‑lived refresh token (30‑90 ngày) với rotation.
- Triển khai PKCE ngay cả khi client là confidential (web) để thống nhất codebase.
- Kiểm thử luồng trên cả thiết bị thật và emulator; mô phỏng mạng chậm, token hết hạn, revoke token từ server.
5. Kết luận
Việc áp dụng OAuth 2.0 + PKCE cho cả web và mobile mang lại một luồng xác thực đơn nhất, an toàn và dễ dàng mở rộng khi thêm nền tảng mới (desktop, TV). Hãy tập trung vào việc tách biệt lưu trữ token theo đặc thước của từng nền tảng, đồng thời tự động hóa kiểm thử end‑to‑end để phát hiện sớm các lỗi bảo mật.