Xây dựng hệ thống Authentication và Authorization phân quyền cho React Web và React Native với OAuth2/OIDC và JWT

17 lượt xem · 2 trả lời

1. 15:36 12/10/2026
Trong phát triển ứng dụng đa nền tảng, việc thống nhất cách đăng nhập và kiểm soát quyền truy cập là yếu tố then chốt để giảm thiểu lỗi bảo mật và tiết kiệm công sức bảo trì. Bài viết này chia sẻ quy trình thực tế để triển khai một hệ thống xác thực (Authentication) và phân quyền (Authorization) dùng OAuth2/OpenID Connect (OIDC) kết hợp JSON Web Token (JWT) cho cả React Web và React Native. 1. Chọn Identity Provider (IdP) phù hợp - Sử dụng Keycloak, Auth0 hoặc Azure AD – tất cả đều hỗ trợ chuẩn OIDC và cung cấp endpoint descubrimiento (/.well-known/openid-configuration). - Cấu hình client kiểu "public" cho SPA và "native" cho mobile, bật PKCE để ngăn chặn tấn công mã ủy quyền. 2. Luồng đăng nhập thống nhất - Web: Redirect trình duyệt đến trang đăng nhập của IdP, nhận authorization code, trao đổi lấy access_token và id_token qua endpoint /token. - Native: Mở tab trình duyệt hệ thống (ASWebAuthenticationSession trên iOS, Chrome Custom Tab trên Android) để thực hiện cùng luồng PKCE, sau đó nhận token về qua deep link. - Lưu access_token trong bộ nhớ an toàn (SecureStore/Keychain trên mobile, httpOnly cookie hoặc memory trên web). 3. Quản lý token và refresh - Access token ngắn hạn (5‑15 phút). - Refresh token dài hạn, lưu trữ an toàn, tự động gọi /token khi access token hết hạn. - Triển khai interceptor Axios/Fetch để tự động làm mới token mà không làm gián đoạn UX. 4. Phân quyền dựa trên claim trong JWT - IdP cấp claim "roles" hoặc "permissions" trong id_token/access_token. - Trên client, decode JWT (không verify signature vì đã tin cậy IdP) để lấy mảng quyền. - Tạo hook `usePermission(required)` trả về boolean, dùng để render điều kiện component, route guard hoặc disable action. 5. Bảo vệ API backend - Middleware kiểm tra signature JWT (RS256) với JWKS endpoint của IdP. - Xác thực claim `aud`, `iss`, `exp` và quyền cần thiết cho từng endpoint. 6. Xử lý đăng xuất toàn cục (Single Logout) - Gọi endpoint `end_session_endpoint` của IdP, xóa token cục bộ, chuyển hướng về trang đăng nhập. - Trên mobile, xóa SecureStore và đóng webview đăng nhập. 7. Mẹo thực tế - Tách cấu hình IdP theo environment (dev, staging, prod) bằng file `.env`. - Viết test integration cho luồng PKCE trên cả hai nền tảng. - Theo dõi log lỗi token expired để điều chỉnh thời gian sống token phù hợp. Với kiến trúc này, team chỉ duy trì một bộ logic xác thực, giảm thiểu sai lệch giữa web và mobile, đồng thời tuân thủ các tiêu chuẩn bảo mật hiện đại.
0 Facebook
2. 19:21 14/10/2026
Trả lời Quản Trị Viên Trong phát triển ứng dụng đa nền tảng, việc thống nhất cách đăng nhập và kiểm soát quyền truy cập là yếu tố then chốt để…
Bài viết rất hay, tổng hợp đủ từ lý thuyết đến thực chiến. Mình đã áp dụng Keycloak cho dự án cross-platform trước đây, phần khó khăn nhất không phải ở luồng đăng nhập mà là đồng bộ trạng thái token giữa web (dùng memory + httpOnly cookie cho refresh) và mobile (SecureStore). Cụ thể là khi refresh token bị revoke ở một client thì client kia vẫn nghĩ token hợp lệ cho đến khi gọi API bị 401 mới xử lý logout. Mình thấy giải pháp "silent refresh" qua iframe (web) hoặc background task (native) giúp UX mượt mà hơn so với chờ interceptor bắt 401 rồi mới refresh. Ngoài ra, việc validate `aud` claim ở backend thường bị bỏ quên dẫn đến rủi ro token của web app bị dùng cho mobile app (nếu dùng chung client_id). Bác có chia sẻ thêm cách handle race condition khi nhiều request cùng lúc bị 401 và cùng trigger refresh token không? Mình dùng mutex/queue ở Axios interceptor nhưng trên React Native bridge đôi khi vẫn bị leak một request.
0
3. 19:27 25/10/2026
Trả lời Clara King Bài viết rất hay, tổng hợp đủ từ lý thuyết đến thực chiến. Mình đã áp dụng Keycloak cho dự án cross-platform trước đây, …
Vấn đề race condition này thường không nằm ở interceptor mà ở chỗ thiếu một cơ chế “single-flight refresh” đủ toàn cục. Mình sẽ gom mọi request 401 vào một auth manager duy nhất, giữ một refreshPromise ở module scope; request đến sau chỉ await promise đó rồi replay với token mới, đồng thời đánh dấu _retry để tránh vòng lặp.
0
Vui lòng đăng nhập để tham gia trả lời chủ đề này.
Điều hướng nhanh

Bạn muốn khám phá điều gì?

Tìm chủ đề, bài viết hoặc đi thẳng đến một khu vực của cộng đồng.

Esc để đóng Ctrl K để mở lại