🔑 Authorization Code Grant
Đây là grant type phổ biến và an toàn nhất trong OAuth2. Được thiết kế cho các ứng dụng có backend server, và hiện nay (với PKCE) cũng là lựa chọn chuẩn cho SPA & mobile app.
1. Tổng quan
| Thuộc tính | Giá trị |
|---|---|
| RFC | RFC 6749 §4.1 |
| Dùng cho | Web app (server-side), SPA + PKCE, Mobile app + PKCE |
| Có Refresh Token? | ✅ Có |
| Client Secret cần thiết? | ✅ (server-side) / ❌ thay bằng PKCE (public client) |
| Mức độ bảo mật | ⭐⭐⭐⭐⭐ (8/9) |
2. Các thành phần tham gia
- Resource Owner — Người dùng cuối (end-user)
- User-Agent — Trình duyệt / app của người dùng
- Client — Ứng dụng của bạn (web app, SPA, mobile)
- Authorization Server (AS) — Server xác thực & cấp token (Google, Facebook, Auth0…)
- Resource Server (RS) — API server chứa dữ liệu được bảo vệ
3. Flow chi tiết (Standard — Có Client Secret)
sequenceDiagram
participant U as 👤 User
participant B as 🌐 Browser
participant C as 🖥️ Client App (Backend)
participant AS as 🔐 Authorization Server
participant RS as 📦 Resource Server
U->>B: Click "Login with Google"
B->>AS: GET /authorize?response_type=code&client_id=...&redirect_uri=...&scope=...&state=xyz
AS->>B: Hiển thị trang đăng nhập + consent
U->>AS: Đăng nhập & đồng ý cấp quyền
AS->>B: Redirect → redirect_uri?code=AUTH_CODE&state=xyz
B->>C: Gửi AUTH_CODE lên backend
C->>AS: POST /token (code + client_id + client_secret + redirect_uri)
AS->>C: { access_token, refresh_token, expires_in }
C->>RS: GET /api/data (Authorization: Bearer access_token)
RS->>C: 200 OK + dữ liệu
Giải thích từng bước:
- Authorization Request — Client redirect user đến AS với các params:
response_type=codeclient_id— định danh ứng dụngredirect_uri— URL AS sẽ redirect sau khi xác thựcscope— quyền cần xin (vd:openid profile email)state— random string để chống CSRF
- User Authentication & Consent — AS hiển thị login form, user đăng nhập và đồng ý.
- Authorization Code — AS redirect về
redirect_urikèmcode(short-lived, ~10 phút, single-use).-
Phân biết rõ với MFAKhông giống nhau — đây là hai thứ hoàn toàn khác nhau, dù cùng có từ "code" và đều ngắn hạn. Để phân biệt rõ:
🔢 Google Authenticator (6 số) — đây là TOTP/MFA
- Là gì: Time-based One-Time Password (TOTP) — RFC 6238
- Mục đích: Xác minh danh tính bạn (Authentication / MFA)
- Ai tạo ra: App trên điện thoại bạn tự tính toán dựa trên secret key + thời gian hiện tại
- Dạng: 6 chữ số, đổi mỗi 30 giây
- Ai nhập: Bạn — nhìn app rồi gõ tay vào website
- Ví dụ: Đăng nhập Gmail → nhập mật khẩu → nhập thêm 6 số từ Google Authenticator
🔑 Authorization Code trong OAuth2
- Là gì: Một chuỗi random dài (VD:
4/P7q7W91a3Bc...) do Authorization Server tạo ra - Mục đích: Cho phép backend đổi lấy Access Token một cách an toàn (Authorization)
- Ai tạo ra: Authorization Server (Google, Facebook...) tạo ra phía server
- Dạng: Chuỗi ký tự dài, random, single-use, sống ~10 phút
- Ai nhập: Không ai nhập tay cả — nó được tự động đính vào URL redirect, browser mang đến backend hoàn toàn tự động
- Ví dụ:
https://yourapp.com/callback?code=4/P7q7W91a3Bc...
So sánh nhanh
TOTP (Google Authenticator) Authorization Code Mục đích Xác minh bạn là ai Đổi lấy Access Token Dạng 6 số, đổi 30 giây Chuỗi dài, single-use Ai tạo Điện thoại của bạn Authorization Server Ai nhập Bạn gõ tay Browser tự động qua redirect Tiêu chuẩn RFC 6238 (TOTP) RFC 6749 (OAuth2)
Analogy đơn giản:
- TOTP = Mã PIN rút tiền ATM — bạn nhớ và gõ tay để chứng minh bạn là chủ thẻ
- Authorization Code = Phiếu lấy số ở ngân hàng — nhân viên đưa cho bạn, bạn đưa lại cho quầy khác để lấy dịch vụ, xong là vứt đi
-
- Token Exchange (Back-channel) — Backend gọi POST
/tokenvớicode+client_secret. Đây là bước quan trọng: token được trao đổi qua server-to-server, không qua browser → an toàn. - Access Token sử dụng — Dùng
access_tokenđể gọi Resource Server. - Refresh Token — Khi
access_tokenhết hạn, dùngrefresh_tokenđể lấy token mới mà không cần user đăng nhập lại.
4. Flow PKCE (Proof Key for Code Exchange) — Dành cho SPA & Mobile
sequenceDiagram
participant App as 📱 SPA / Mobile App
participant AS as 🔐 Authorization Server
App->>App: Tạo code_verifier (random 43-128 chars)
App->>App: code_challenge = BASE64URL(SHA256(code_verifier))
App->>AS: GET /authorize?...&code_challenge=...&code_challenge_method=S256
AS->>App: Redirect với authorization_code
App->>AS: POST /token (code + code_verifier — KHÔNG có client_secret)
AS->>AS: Verify: SHA256(code_verifier) == code_challenge?
AS->>App: { access_token, refresh_token }
Tại sao PKCE an toàn?
- Nếu attacker đánh cắp
authorization_code, họ không cócode_verifier→ không thể đổi lấy token. code_challengelà hash một chiều → không thể reverse.
5. Request/Response mẫu
Bước 1 — Authorization Request
GET https://accounts.google.com/o/oauth2/auth
?response_type=code
&client_id=your_client_id
&redirect_uri=https://yourapp.com/callback
&scope=openid%20profile%20email
&state=randomCSRFtoken
&access_type=offline
Bước 2 — Token Exchange
POST https://oauth2.googleapis.com/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=4/P7q7W91
&redirect_uri=https://yourapp.com/callback
&client_id=your_client_id
&client_secret=your_client_secret
Response
{
"access_token": "ya29.A0ARrdaM...",
"expires_in": 3600,
"refresh_token": "1//0gLd...",
"scope": "openid profile email",
"token_type": "Bearer",
"id_token": "eyJhbGciOiJSUzI1NiJ9..."
}
6. Security Checklist
- Luôn validate
stateparameter để chống CSRF attack -
redirect_uriphải được whitelist chính xác tại Authorization Server - Dùng PKCE cho mọi public client (SPA, mobile)
- Lưu
refresh_tokenan toàn (không localStorage — dùng httpOnly cookie hoặc secure server-side storage) - Implement token rotation cho
refresh_token - Đặt
access_tokenTTL ngắn (15–60 phút) - Không log
access_tokenhayrefresh_token
7. Khi nào dùng?
| Scenario | Dùng Authorization Code? | Variant |
|---|---|---|
| Web app có backend (Laravel, Rails…) | ✅ Yes | Standard (với client_secret) |
| Single Page App (React, Vue) | ✅ Yes | • PKCE (không có client_secret) |
| Mobile App (iOS, Android) | ✅ Yes | • PKCE |
| Server-to-server (không có user) | ❌ No | Dùng Client Credentials |
| CLI tool | ⚠️ Maybe | Device Flow hoặc PKCE |