Auth / Identity — Mental Model

· ~5 phút đọc

Auth / Identity — Mental Model

1. OAuth 2.0

OAuth 2.0 chuẩn hóa cách Client lấy access token để gọi Resource Server. Điểm chính là quyền được cấp và cách kiểm tra quyền đó, không phải token có format gì.

Authorization Server phát token; Resource Server kiểm tra token để biết request đại diện cho client/user nào và được làm gì. Token có thể là JWT hoặc chỉ là random opaque string. Bên dưới vẫn là database, API endpoints, expiry và permission checks, không có magic.

Server-to-server

Ví dụ, một job cần gọi API báo cáo của công ty:

1
2
3
4
job gửi client_id + client_secret cho Authorization Server
→ nhận access_token có quyền đọc báo cáo
→ gọi GET /reports với token
→ Report API kiểm token và trả dữ liệu

client_id là định danh unique; client_secret là random secret đủ mạnh. Ở đây job xin quyền cho chính nó, không có user tham gia.

User-delegated flow

Ví dụ, một app muốn đọc lịch Google của user:

1
2
3
4
App đưa user đến Google → user login và đồng ý quyền đọc lịch
→ Google redirect authorization_code về App
→ App đổi code lấy access_token (dùng PKCE hoặc client credentials tùy loại client)
→ App dùng token gọi Calendar API → nhận sự kiện lịch

Code đi qua browser redirect, access token thì không. Code có thể chỉ là random string; Authorization Server lưu nó cùng user, client, scope, hạn dùng và trạng thái đã sử dụng để kiểm tra khi đổi token.


2. OpenID Connect

OAuth cho client quyền truy cập tài nguyên; OIDC cho app biết user đã đăng nhập là ai.

OIDC xây trên OAuth 2.0 và thêm ID Token, thường là JWT. Identity Provider xác thực user rồi phát ID Token cho app. App kiểm tra chữ ký, issuer, audience và hạn dùng trước khi tin danh tính trong token.

Ví dụ, user chọn Login with Google trong app Notes. App nhận ID Token chứa:

1
2
3
4
5
6
7
{
"iss": "https://accounts.google.com",
"sub": "user_123",
"aud": "notes-client",
"exp": 1800000300,
"iat": 1800000000
}

Sau khi verify, Notes dùng iss + sub để tìm user và tạo local session riêng. Session đó không bắt buộc là JWT; random session ID lưu trong database cũng được. ID Token trả lời “user là ai”, không phải token để gọi API lịch ở ví dụ OAuth.


3. Identity database

Identity có thể nằm tập trung, nhưng dữ liệu của từng app vẫn nằm ở app đó.

Ví dụ cùng một Google user đăng nhập hai app:

1
2
3
Google Accounts: sub = user_123, password / MFA
Google Drive: user_123 → files / preferences
Gmail: user_123 → mailbox / settings

Drive không giữ mailbox, Gmail không giữ files. Mỗi app liên kết danh tính từ Google với user trong database của mình bằng iss + sub, thay vì chia sẻ toàn bộ dữ liệu user.

Lần đầu login, app verify ID Token, chưa tìm thấy iss + sub thì tạo local user và session: JIT provisioning.


4. SCIM

OIDC giúp app nhận diện user khi họ login. SCIM giúp đồng bộ vòng đời user giữa Identity Provider và các app.

Ví dụ nhân viên nghỉ việc: admin disable account ở Identity Provider, nó gọi PATCH /Users/42 tới SaaS để đặt active: false. SaaS cập nhật user của mình, không phải chờ người đó login lại mới biết tài khoản đã bị disable.

SCIM 2.0 chuẩn hóa các API như POST /Users, PATCH /Users/:id, DELETE /Users/:id và /Groups. Giá trị nằm ở contract chung, không phải một technology đặc biệt.


5. AWS Cognito User Pool

Cognito User Pool giữ user và xử lý login. Sau khi user đăng nhập, Cognito phát token cho app.

Cognito xác thực user và ký token. Backend dùng public key của Cognito để verify chữ ký, không cần gọi Cognito mỗi request.

Ví dụ user đã login qua Cognito và gọi API của app:

1
2
3
4
GET /me với Access Token do Cognito phát
→ backend lấy public key từ Cognito JWKS để verify chữ ký JWT
→ dùng danh tính trong token tìm user của app
→ trả profile của user đó

Chữ ký hợp lệ cho biết token do Cognito ký và nội dung chưa bị sửa. Backend vẫn phải kiểm token còn hạn và đúng mục đích trước khi dùng thông tin trong đó để quyết định quyền truy cập. API dùng Access Token, không coi ID Token (dành cho app nhận diện user) là vé gọi API.

Đổi lại, nếu backend chỉ verify token tại chỗ, việc disable user hoặc thu hồi quyền ở Cognito có thể chưa có hiệu lực ngay với token đã phát.


6. Passkeys / WebAuthn

Passkey cho phép user chứng minh mình giữ private key, mà không gửi private key hay vân tay cho website.

Nền tảng là asymmetric cryptography. Ví dụ login Facebook bằng passkey trên macOS:

Register Passkey

1
2
3
4
Facebook gửi challenge → browser gọi WebAuthn trên macOS
→ authenticator tạo private key + public key
→ private key ở lại passkey store / iCloud Keychain
→ Facebook nhận public key, lưu cùng user_id và credential_id

Login

1
2
3
Facebook gửi challenge mới → Touch ID cho phép macOS dùng private key ký
→ Facebook nhận signature, dùng public key đã lưu để verify
→ chữ ký hợp lệ → Facebook tạo session

Touch ID và private key không được gửi cho Facebook. challenge là random bytes khác nhau cho mỗi lần xác thực, để chữ ký cũ không dùng lại được.

Standards

1
2
3
FIDO2
├── WebAuthn: website ↔ browser
└── CTAP: browser/OS ↔ authenticator

Backend chọn Rails/Go/Postgres/Redis tùy ý, nhưng vẫn phải tuân theo WebAuthn verification rules.


Core conclusion

OAuth, OIDC, SCIM và WebAuthn không phải magic. Chúng là contract để các hệ thống khác nhau cùng hiểu cách cấp quyền, xác nhận danh tính, đồng bộ user và đăng nhập bằng passkey.

Bên dưới vẫn là programming, database, cryptography, API và các bước kiểm tra. Nhờ dùng chung standard, mỗi app không phải tự invent auth protocol.

Home