Appearance
OAuth 2.0 — Authorization Code Flow với PKCE
Đây là luồng (flow) OAuth 2.0 tiêu chuẩn hiện nay, dùng cho mọi ứng dụng có người dùng đăng nhập (web, SPA, mobile, desktop).
mermaid
sequenceDiagram
participant U as Người dùng
participant App as Ứng dụng (Client)
participant AS as Authorization Server
App->>App: Sinh code_verifier (chuỗi ngẫu nhiên bí mật)
App->>App: Tính code_challenge = SHA256(code_verifier), mã hoá base64url
App->>AS: GET /authorize?response_type=code&client_id=...&redirect_uri=...&code_challenge=...&code_challenge_method=S256&state=...
AS->>U: Hiển thị màn hình đăng nhập / màn hình đồng ý cấp quyền
U->>AS: Nhập thông tin đăng nhập, bấm "Đồng ý"
AS->>App: Redirect về redirect_uri kèm authorization code + state
App->>App: Kiểm tra state khớp với giá trị đã gửi (chống CSRF)
App->>AS: POST /token (code, redirect_uri, client_id, code_verifier)
AS->>AS: Tính lại SHA256(code_verifier), so khớp với code_challenge đã lưu
AS->>App: Trả về access_token (+ id_token nếu là luồng OIDC, + refresh_token)Diễn giải từng bước:
- Sinh cặp PKCE: trước khi bắt đầu, ứng dụng tự sinh một chuỗi ngẫu nhiên gọi là
code_verifier(giữ bí mật, không rời khỏi bộ nhớ ứng dụng), rồi băm (hash) chuỗi này bằng SHA-256 và mã hoá base64url để racode_challenge. - Authorization request: ứng dụng redirect người dùng tới authorization server, gửi kèm
code_challenge(không gửicode_verifier) cùng các tham số chuẩn:response_type=code,client_id,redirect_uri,state(chuỗi ngẫu nhiên để đối chiếu sau, chống giả mạo callback). - Người dùng xác thực: authorization server hiển thị màn hình đăng nhập/đồng ý cấp quyền, không liên quan gì tới ứng dụng gốc — đây là lý do ứng dụng gốc không bao giờ nhìn thấy mật khẩu người dùng.
- Trả authorization code: sau khi người dùng đồng ý, authorization server redirect ngược lại
redirect_urikèm mộtcode(chỉ dùng được một lần, sống rất ngắn) vàstate. - Đổi code lấy token: ứng dụng gửi
codecùngcode_verifier(chuỗi gốc, chưa hash) lên authorization server qua requestPOST /token. - Xác minh PKCE: authorization server tự tính lại
SHA256(code_verifier)và so sánh vớicode_challengeđã nhận ở bước 2. Nếu ai đó chặn đượccodeở bước 4 nhưng không cócode_verifiergốc (chỉ tồn tại trong bộ nhớ ứng dụng thật), họ không thể đổi được token — đây chính là cơ chế PKCE ngăn tấn công đánh cắp authorization code. - Nhận token: nếu khớp, authorization server trả về
access_token(vàrefresh_tokennếu có,id_tokennếu đây là luồng OpenID Connect).