Luồng Mobile App (Authorization Code + PKCE Flow)
Sơ đồ luồng

Các bước chi tiết
1. Khởi tạo đăng nhập
Người dùng mở Mobile App, chọn "Đăng nhập bằng HUTECH ID". Mobile App gọi Backend của TH3 để khởi tạo PKCE.
2. Sinh PKCE
Backend của TH3 sinh code_verifier (bí mật, chỉ lưu ở server TH3). Từ đó tính code_challenge = SHA256(code_verifier). Gửi code_challenge về lại Mobile App.
3. Điều hướng sang SSO
Mobile App mở WebView trỏ đến trang Client SSO, kèm theo: client_id, redirect_uri, code_challenge.
GET [Domain-Client-SSO]/login-mobile?client_id={client_id}&callback={redirect_uri}&code_challenge={code_challenge}
| Parameter | Mô tả |
|---|---|
client_id | Nhận từ HUTECH TEAM |
callback | Đường dẫn deep link của APP mobile |
code_challenge | Đã xin từ bước 2 |
4. Người dùng đăng nhập
User nhập username/password. Sau khi xác thực thành công, ServerSSO redirect về redirect_uri của Mobile App kèm theo authorization_code.
{callback}?code={authorization_code}
5. Đổi code lấy token
Mobile App gửi authorization_code cho Backend TH3. Backend gọi ServerSSO, gửi authorization_code và code_verifier.
6. Xác minh PKCE
ServerSSO tính lại code_challenge từ code_verifier. Nếu khớp với code_challenge lưu trước đó → hợp lệ. Nếu không khớp → báo lỗi invalid_grant.
7. Nhận token & hoàn tất
Nếu hợp lệ: ServerSSO trả về Access_Token (JSON body). Backend TH3 gửi lại token cho Mobile App. Mobile App lưu token và cho phép người dùng truy cập hệ thống.
Cơ chế SHA256 trong PKCE
App gửi một bản băm an toàn gọi là code_challenge.
Quy trình
- Backend/App sinh ra một chuỗi ngẫu nhiên đủ dài → gọi là
code_verifier - Tính
code_challenge = BASE64URL(SHA256(code_verifier))- SHA256: hàm băm một chiều, đảm bảo không thể tính ngược từ code_challenge về code_verifier
- BASE64URL: mã hóa kết quả băm để truyền an toàn qua URL
- Gửi
code_challengekèm yêu cầu login đến SSO - Khi đổi token, App gửi lại
code_verifier. ServerSSO sẽ tính lạiSHA256(code_verifier)→ so sánh vớicode_challengeđã lưu
Ý nghĩa bảo mật
- Ngăn chặn tấn công Authorization Code Interception Attack: kẻ tấn công đánh cắp
authorization_codenhưng không cócode_verifierthì vẫn không đổi được token - Đảm bảo chỉ chính App đã khởi tạo
code_verifiermới có thể hoàn tất quá trình đăng nhập
Ví dụ minh họa
// JavaScript (Node.js)
const crypto = require('crypto');
const code_verifier = "random_string_very_long_secure";
const code_challenge = crypto
.createHash('sha256')
.update(code_verifier)
.digest('base64url');
console.log("code_verifier:", code_verifier);
console.log("code_challenge:", code_challenge);