OAuth2 = ủy quyền (authorization), OIDC = lớp xác thực (authentication) đặt trên OAuth2.
- Access token (OAuth2): cấp quyền gọi API resource. Bên API kiểm tra scope.
- ID token (OIDC, luôn là JWT): chứng minh user là ai (claims
sub,email...). Dành cho client, không gửi tới resource API.
Authorization Code Flow + PKCE:
1. App đẩy user tới Authorization Server, kèm code_challenge.
2. User đăng nhập → server trả về authorization code (qua redirect).
3. App đổi code + code_verifier lấy token ở back channel.
PKCE chống intercept code trên public client (SPA/mobile) vốn không giữ được client secret. Không dùng Implicit Flow nữa (deprecated).
Revoke / stateless dilemma: JWT tự chứa quyền nên server không tra DB mỗi request → nhưng vì thế khó thu hồi. Giải pháp:
- Access token TTL ngắn (5–15 phút) + refresh token dài hạn (rotate, lưu server-side, revoke được).
- Hoặc duy trì blocklist jti cho tới khi token hết hạn.
Lưu ý: verify JWT bằng public key (RS256) lấy từ JWKS endpoint, không dùng HS256 chung secret cross-service; luôn check iss, aud, exp.
OAuth2 = authorization, OIDC = an authentication layer on top of OAuth2.
- Access token (OAuth2): grants API access. The API checks scopes.
- ID token (OIDC, always a JWT): proves who the user is (claims
sub,email...). For the client, not sent to resource APIs.
Authorization Code Flow + PKCE:
1. App sends user to the Authorization Server with a code_challenge.
2. User logs in → server returns an authorization code (via redirect).
3. App exchanges code + code_verifier for tokens on the back channel.
PKCE prevents code interception on public clients (SPA/mobile) that can't keep a secret. Implicit Flow is deprecated.
Revoke / stateless dilemma: a JWT self-contains its claims so the server need not hit the DB per request → but that makes it hard to revoke. Solutions:
- Short-TTL access tokens (5–15 min) + long-lived refresh tokens (rotated, stored server-side, revocable).
- Or keep a jti blocklist until the token expires.
Note: verify JWTs with the public key (RS256) from a JWKS endpoint, not a shared HS256 secret across services; always check iss, aud, exp.