1. 19:23 13/10/2026
1. Tổng quan
OAuth2/OpenID Connect là chuẩn phổ biến để quản lý đăng nhập và phân quyền cho cả web và mobile. Việc dùng một Identity Provider (IdP) chung giúp đồng bộ tài khoản, giảm thiểu logic trùng lặp và dễ dàng mở rộng sau này.
2. Kiến trúc chung
- Client Web (Next.js) và Client Mobile (Expo) đều là Public Clients, sử dụng Authorization Code Flow với PKCE.
- IdP (Keycloak, Auth0, Azure AD…) cấp access token, refresh token và ID token.
- Backend API chỉ kiểm tra access token (JWT) và scopes/roles.
3. Cấu hình Identity Provider
- Tạo một Client cho Web (redirect_uri: https://app.example.com/callback) và một Client cho Mobile (redirect_uri: com.example.app:/oauth2redirect).
- Bật PKCE, thiết lập scopes: openid profile email offline_access.
- Định nghĩa roles (admin, user) và map vào claim "roles" của access token.
4. Tích hợp vào React Web (Next.js)
- Dùng next-auth hoặc @auth0/nextjs-auth0 để xử lý login, callback, token refresh tự động.
- Lưu refresh token trong httpOnly cookie, access token trong memory (React context).
- Bảo vệ trang bằng getServerSideProps hoặc middleware kiểm tra session.
5. Tích hợp vào React Native (Expo)
- Sử dụng expo-auth-session + expo-crypto để sinh code_verifier/code_challenge.
- Mở trình duyệt hệ thống (WebBrowser.openAuthSessionAsync) để đăng nhập.
- Lưu refresh token trong SecureStore, access token trong state (React Query cache).
- Triển khai hook useAuth() tập trung xử lý silent refresh khi access token hết hạn.
6. Xử lý token refresh và silent login
- Web: next-auth tự động refresh qua cookie; Mobile: gọi endpoint /token với refresh_token và PKCE challenge mới.
- Thiết lập interceptor (axios/fetch) tự động retry request 401 sau khi refresh thành công.
7. Bảo vệ route và screen
- Web: middleware kiểm tra role từ JWT claim trước khi render page.
- Mobile: wrapper component <ProtectedScreen requiredRoles={["admin"]}> bọc các screen nhạy cảm.
8. Mẹo thực tế và lỗi thường gặp
- Luôn validate issuer, audience và expiration ở backend.
- Tránh lưu access token vào AsyncStorage/ localStorage – dễ bị XSS.
- Test luồng logout toàn bộ (revoke refresh token ở IdP) để đảm bảo session kết thúc trên cả hai nền tảng.
- Sử dụng feature flag để bật/tắt MFA mà không cần deploy lại client.