0

Auth0 Bài 4: Hiểu về các luồng xác thực (OAuth2 & OpenID Connect) – Khi nào dùng luồng nào?

Ở bài trước, chúng ta đã xây xong "tòa nhà" (Tenant) và "quầy lễ tân" (Application). Bây giờ, câu hỏi đặt ra là: Làm sao để lễ tân trao chìa khóa (Token) cho khách một cách an toàn nhất?

Nếu đưa chìa khóa sai cách, hacker có thể chặn đường và đánh cắp nó. Đó là lý do các Luồng xác thực (Authentication Flows) ra đời.

Trước khi đi vào các luồng cụ thể, chúng ta cần phân biệt rõ hai chuẩn giao thức mà Auth0 đang sử dụng: OAuth 2.0OpenID Connect (OIDC).


1. OAuth 2.0 vs OpenID Connect: Khác nhau chỗ nào?

Hãy nhớ lại Bài 1 về Authentication (Xác thực) và Authorization (Phân quyền):

  • OAuth 2.0: Đây là một giao thức Authorization (Phân quyền). Nhiệm vụ của nó là cấp phát một Access Token. Cái token này giống như một chiếc vé xe bus: người soát vé (API) chỉ cần biết vé này hợp lệ là cho bạn lên xe, chứ họ không quan tâm bạn tên gì hay bao nhiêu tuổi.
  • OpenID Connect (OIDC): OAuth 2.0 rất tốt, nhưng nó không cho ứng dụng biết "ai" đang đăng nhập. Vì vậy, người ta đắp thêm một lớp OIDC lên trên OAuth 2.0. OIDC cung cấp thêm một ID Token (thường ở định dạng JWT - JSON Web Token). ID Token chứa thông tin cá nhân của người dùng (Profile, Email, Tên).

Tóm lại: Auth0 sử dụng OIDC để báo cho ứng dụng Frontend biết ai đang đăng nhập (ID Token), và sử dụng OAuth 2.0 để cấp quyền cho Frontend gọi xuống Backend API (Access Token).


2. Các luồng xác thực (Flows) và khi nào sử dụng?

Tùy thuộc vào kiến trúc ứng dụng của bạn (chạy trên trình duyệt, chạy trên server, hay không có giao diện), Auth0 sẽ yêu cầu bạn dùng luồng khác nhau để đảm bảo bảo mật tối đa.

Dưới đây là 3 luồng phổ biến nhất bạn buộc phải nắm rõ:

Luồng 1: Authorization Code Flow

  • Dành cho: Regular Web Apps (Node.js, Spring Boot, PHP, Next.js Server Components).
  • Đây là luồng an toàn nhất vì mọi việc trao đổi khóa đều diễn ra ở "hậu trường" (Backend).
    1. Người dùng bấm "Login" trên web của bạn.
    2. Web chuyển hướng họ sang trang đăng nhập của Auth0.
    3. Sau khi đăng nhập thành công, Auth0 chuyển hướng ngược lại web của bạn kèm theo một mã dùng một lần gọi là Authorization Code.
    4. Backend của bạn âm thầm cầm mã Code này, cộng thêm một Client Secret (mật khẩu bí mật chỉ server bạn biết) gửi trực tiếp qua Auth0 API để đổi lấy Token.
  • Bảo mật: Vì Token được trả thẳng về Backend và Client Secret không bao giờ lộ ra trình duyệt, hacker không thể can thiệp.

Luồng 2: Authorization Code Flow with PKCE (Phát âm: Pixie)

  • Dành cho: Single Page Apps (React, Vue, Angular) và Mobile/Native Apps (iOS, Android).
  • Tại sao React/Vue không dùng được Luồng 1? Vì các app này chạy hoàn toàn trên trình duyệt của người dùng. Nếu bạn nhét Client Secret vào code React, hacker mở DevTools lên là thấy ngay. PKCE (Proof Key for Code Exchange) ra đời để giải quyết việc này.
    1. Trước khi chuyển hướng người dùng sang Auth0, React App tự động tạo ra một chuỗi bí mật ngẫu nhiên (Code Verifier) và băm nó ra (Code Challenge).
    2. React gửi Code Challenge này cho Auth0 cùng với yêu cầu đăng nhập.
    3. Sau khi đăng nhập, Auth0 trả về một mã Code (giống Luồng 1).
    4. Lúc này, thay vì dùng Client Secret (vì không có), React App sẽ gửi mã Code + chuỗi bí mật ngẫu nhiên ban đầu (Code Verifier) cho Auth0.
    5. Auth0 tự băm cái Verifier ra, nếu khớp với cái Challenge nhận được ở bước 2 thì mới nhả Token.
  • Bảo mật: Kẻ cắp dẫu có chộp được mã Code giữa đường cũng vô dụng vì không có chuỗi ngẫu nhiên ban đầu do trình duyệt của user đang giữ.

Luồng 3: Client Credentials Flow

  • Dành cho: Machine-to-Machine (M2M), Server-to-Server, Cronjobs.
  • Luồng này không có sự tham gia của con người (không có màn hình đăng nhập, không có giao diện).
    1. Server A của bạn muốn gọi một API bảo mật trên Server B.
    2. Server A gửi trực tiếp Client ID và Client Secret của nó cho Auth0.
    3. Auth0 xác nhận và cấp ngay Access Token cho Server A.
    4. Server A cầm Token đó gọi sang Server B.

Lưu ý: Có một luồng cũ tên là Implicit Flow (trả thẳng Token về URL trình duyệt). Luồng này hiện nay đã bị coi là lỗi thời và thiếu an toàn. Đừng bao giờ dùng nó cho các dự án mới. Hãy luôn dùng Authorization Code with PKCE cho SPA.


3. Bảng tổng hợp nhanh (Cheat Sheet)

Để dễ nhớ, mỗi khi chuẩn bị code, bạn chỉ cần nhìn vào bảng này:

Kiến trúc ứng dụng của bạn Nơi lưu trữ Code Luồng (Flow) bắt buộc phải dùng
Backend / Traditional Web (Node.js, Java, Next.js API) Máy chủ an toàn (Server) Authorization Code Flow
Frontend SPA (React, Vue, Angular) Trình duyệt người dùng (Insecure) Authorization Code Flow with PKCE
Mobile App / Desktop App (iOS, Android, Electron) Thiết bị người dùng Authorization Code Flow with PKCE
Server gọi Server (Cronjob, Microservices) Máy chủ an toàn Client Credentials Flow

💡 Lời Kết

Kiến thức nền tảng như vậy là quá đủ rồi. Ở các bài tiếp theo, khi áp dụng thư viện SDK của Auth0, thư viện sẽ tự động làm những bước "băm chuỗi" hay "gửi Code" này cho bạn. Nhưng việc hiểu bản chất bên dưới sẽ giúp bạn debug cực kỳ nhanh nếu có lỗi xảy ra.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí