Authentication: OAuth2

8 phút đọc

🔍 OAuth2 là gì? — Giải thích đơn giản

Hãy tưởng tượng bạn đến khách sạn và nhờ nhân viên lễ tân lấy hộ xe từ bãi đỗ. Thay vì đưa chìa khóa chính của xe, bạn đưa cho họ một chìa khóa valet — chỉ dùng được để lấy xe, không mở được cốp hay két sắt. OAuth2 hoạt động theo cách tương tự: cấp cho ứng dụng một "chìa khóa giới hạn" thay vì mật khẩu thật.

OAuth2 là một khung ủy quyền (Authorization Framework) cho phép ứng dụng bên thứ ba truy cập tài nguyên của người dùng mà không cần biết mật khẩu.


🧩 Các thành phần chính

Thành phần Tên kỹ thuật Vai trò trong thực tế
👤 Người dùng Resource Owner Chủ sở hữu dữ liệu (ví dụ: bạn — người dùng Gmail)
📱 Ứng dụng bên thứ ba Client App muốn truy cập dữ liệu (ví dụ: Notion muốn đọc Google Calendar)
🔑 Máy chủ xác thực Authorization Server Nơi cấp phát token (ví dụ: accounts.google.com)
🗄️ Máy chủ tài nguyên Resource Server Nơi chứa dữ liệu cần truy cập (ví dụ: Google Calendar API)

🔄 Flow xác thực — Authorization Code Grant (phổ biến nhất)

Từng bước theo ngôn ngữ đời thường:

  1. Bạn bấm "Đăng nhập bằng Google" trên ứng dụng Notion
  2. Notion chuyển hướng bạn sang trang đăng nhập của Google, kèm thông tin: "Tôi là Notion, tôi muốn đọc Calendar của user này"
  3. Google hỏi bạn: "Bạn có đồng ý cho Notion đọc lịch của bạn không?"
  4. Bạn đồng ý → Google tạo một mã tạm thời (authorization_code) và gửi về Notion
  5. Notion dùng mã tạm thời (+ secret key riêng) để đổi lấy Access Token từ Google — bước này xảy ra phía server, người dùng không thấy
  6. Notion dùng Access Token để gọi Google Calendar API và lấy dữ liệu lịch của bạn
sequenceDiagram
    participant User as 👤 Người dùng
    participant Client as 📱 Ứng dụng (Notion)
    participant AuthServer as 🔑 Auth Server (Google)
    participant ResourceServer as 🗄️ Resource Server (Google API)
    User->>Client: Bấm "Đăng nhập bằng Google"
    Client->>AuthServer: Redirect → /authorize?client_id=...&scope=calendar&redirect_uri=...
    AuthServer->>User: Hiển thị trang đăng nhập + xin phép
    User->>AuthServer: Đăng nhập + Đồng ý cấp quyền
    AuthServer->>Client: Redirect về callback?code=AUTH_CODE (mã tạm thời)
    Client->>AuthServer: POST /token (code + client_secret) — phía server
    AuthServer-->>Client: Access Token + Refresh Token
    Client->>ResourceServer: GET /calendar/events (Authorization: Bearer access_token)
    ResourceServer-->>Client: 200 OK + Dữ liệu lịch
    Client-->>User: Hiển thị lịch

🗝️ Các loại Token

Token Thời hạn Mục đích Ví dụ
Access Token Ngắn (15 phút – 1 giờ) Gọi API để lấy dữ liệu Như thẻ ra vào tòa nhà — hết hạn phải đổi thẻ mới
Refresh Token Dài (ngày – tuần) Lấy Access Token mới mà không cần đăng nhập lại Như giấy tờ gốc để làm thẻ mới khi thẻ hết hạn
Authorization Code Rất ngắn (vài giây – phút) Dùng một lần để đổi lấy Access Token Như phiếu số tại quầy — dùng xong là hết giá trị

📋 Các Grant Types

Grant Type Dùng khi nào Mô tả Độ an toàn
Authorization Code Web app có backend server An toàn nhất, dùng code trung gian, token trao đổi phía server ⭐⭐⭐⭐⭐
Authorization Code + PKCE SPA (React/Vue), Mobile app Thêm code_verifier/code_challenge để chống tấn công chặn code ⭐⭐⭐⭐⭐
Client Credentials Giao tiếp server-to-server (không có user) App tự xác thực bằng client_id + client_secret, không cần user đăng nhập ⭐⭐⭐⭐
Refresh Token Gia hạn phiên làm việc Dùng refresh token để lấy access token mới khi token cũ hết hạn ⭐⭐⭐⭐
Implicit Grant SPA (cũ) Đã bị deprecated — không dùng nữa, thay bằng PKCE

🔐 Scope — Giới hạn quyền truy cập

scope là cơ chế OAuth2 dùng để giới hạn phạm vi quyền mà ứng dụng được phép làm.

/authorize?scope=read:calendar write:calendar profile

Ví dụ thực tế:

  • read:calendar → chỉ đọc lịch, không sửa được
  • write:calendar → đọc và tạo/sửa sự kiện
  • profile email → chỉ lấy tên và email, không truy cập dữ liệu khác

⚠️ Những hiểu lầm phổ biến

Hiểu lầm Thực tế
"OAuth2 = Đăng nhập bằng Google/Facebook" Đó là OpenID Connect (OIDC) — một lớp xây trên OAuth2. OAuth2 chỉ làm ủy quyền, không làm xác thực danh tính.
"Access Token = Mật khẩu" Access Token có thời hạn ngắngiới hạn scope. Nếu bị lộ, thiệt hại được kiểm soát tốt hơn nhiều so với mật khẩu.
"Refresh Token có thể dùng mãi" Refresh Token cũng có thể bị thu hồi (revoke) khi user đăng xuất hoặc đổi mật khẩu.

🆚 OAuth2 vs OpenID Connect (OIDC)

OAuth2
Mục đích Ủy quyền (Authorization) — "App được làm gì?"
Token trả về Access Token + Refresh Token
Dùng khi Cho phép app đọc/ghi dữ liệu của user
Kết hợp Thường dùng cả hai cùng nhau: OIDC để xác thực danh tính, OAuth2 để lấy quyền truy cập tài nguyên

🛡️ Lưu ý bảo mật quan trọng

  • ✅ Luôn dùng PKCE cho SPA và mobile apps (thay Implicit Grant)
  • ✅ Validate state parameter để chống CSRF attack
  • ✅ Lưu Access Token trong memory (không phải localStorage)
  • ✅ Lưu Refresh Token trong HttpOnly cookie
  • ✅ Dùng HTTPS cho tất cả các endpoint
  • ✅ Kết hợp với OIDC khi cần xác thực danh tính người dùng
  • Implicit Grant đã bị deprecated — không dùng nữa

📚 Tài liệu tham khảo

Bài viết liên quan

Đang cập nhật...