Authentication, session, JWT và authorization
Authentication xác định principal; authorization quyết định principal được làm gì trên resource nào trong context nào. Credential lifecycle, token validation và object-level checks phải được thiết kế cùng nhau.
1. Credential lifecycle
Password cần adaptive salted hash, không mã hóa reversible; login/recovery cần MFA, rate limit và risk signals. Authentication tạo session hoặc token, nhưng không tự cấp quyền. Authorization nên đánh giá principal + action + resource + context, không dùng role do client gửi.
- Recovery flow thường là attack surface ngang login: token một lần, expiry ngắn, revoke sau dùng.
- Không log password, access token, refresh token hay câu trả lời security question.
- Credential change và privilege change nên invalidate hoặc re-evaluate các session liên quan.
2. Opaque session và cookie
Opaque session ID trong Secure, HttpOnly, SameSite cookie để server/session store giữ state. Rotate ID sau login hoặc privilege change chống session fixation. Logout/revocation dễ hơn JWT nhưng cần HA, TTL, cleanup và CSRF controls vì browser tự gửi cookie.
| Cookie control | Protection | Giới hạn |
|---|---|---|
| Secure | Chỉ gửi qua HTTPS | Không bảo vệ khi TLS terminate sai hoặc XSS đọc action trong session |
| HttpOnly | Giảm JS đọc cookie | Không ngăn XSS gửi request thay user |
| SameSite | Giảm cross-site gửi cookie | Phải xét flow cross-site hợp lệ và browser behavior |
| CSRF token/origin check | Chứng minh request hợp lệ | Cần gắn đúng state-changing methods |
3. JWT là claims container, không phải protocol
JWS ký claims nhưng không mã hóa; JWE mã hóa. JWT validation phải dùng algorithm allow-list, kiểm tra signature/key, issuer, audience, expiry, not-before và token type. kid chỉ chọn key trong trust store; không fetch URL tùy ý theo header. Claims không nên chứa secret hoặc PII không cần thiết.
verifySignature(token, allowedAlgorithms, trustedKeySet)
assert iss == expectedIssuer
assert aud contains expectedAudience
assert exp > now && nbf <= now + deliberateClockSkew
authorize(subject, action, resource, requestContext)
4. Key rotation và revocation
Signer chuyển sang key mới nhưng publish old + new verification keys trong overlap cho tới khi token cũ hết hạn. JWKS cache cần refresh khi gặp unknown kid nhưng phải rate limit để tránh amplification. Clock skew chỉ cho phép nhỏ và có chủ đích.
Access token ngắn hạn giảm window nhưng không làm revocation tức thì. Role disable hoặc emergency revoke cần token version, deny list, introspection hoặc re-evaluate authorization data. “Stateless” chỉ chuyển state sang key, identity và lifecycle management.
5. RBAC, ABAC và object-level authorization
| Model | Phù hợp | Cẩn thận |
|---|---|---|
| RBAC | Coarse permission như support/read | Role explosion và không đủ cho ownership/tenant |
| ABAC/policy | Attributes, time, tenant, risk, resource state | Policy drift, explainability và test coverage |
| Object scope | Ownership/tenant trên từng row/object | Phải enforce ở query/use-case boundary, không chỉ UI hoặc endpoint role |
Deny-by-default, least privilege và audit decision. Để tránh IDOR/BOLA, query phải scope theo principal ngay từ đầu: WHERE tenant_id = :tenant AND id = :id, thay vì load object rồi nhớ check ở một nhánh code.
6. Readiness checklist
- Session/token rotate sau login và privilege change chưa?
- JWT kiểm tra issuer, audience, algorithm, expiry và key trust boundary chưa?
- Key rotation có overlap, cache refresh và emergency revoke chưa?
- Authorization có test object/tenant ownership và deny-by-default chưa?
- Cookie flow có CSRF/XSS threat model và audit redaction chưa?