Keycloak — Identity & Access Management cho Java/Spring Boot
Một tài liệu độc lập để hiểu Keycloak từ mental model đến production: realm, client, role, OIDC/OAuth2, token, session, MFA, federation, service account, token exchange, reverse proxy, TLS, HA, observability, security và debugging. Baseline nội dung: Keycloak 26.7.3.
1. Mental model: Keycloak đứng ở đâu?
Keycloak là Identity and Access Management (IAM) server. Ứng dụng không nên tự giữ password, tự xây SSO hoặc tự phát token nếu không thật sự cần. Thay vào đó, ứng dụng chuyển việc xác thực cho Keycloak và chỉ tin các token được ký bởi issuer mà nó đã cấu hình.
User là ai?
Đăng nhập, password, MFA, identity provider, user federation, session.
Chứng minh danh tính
Browser flow, direct grant, client authentication, WebAuthn/OTP.
Được làm gì?
Realm roles, client roles, groups, scopes và Authorization Services.
Giao tiếp thế nào?
OpenID Connect/OAuth 2.x là lựa chọn phổ biến; SAML vẫn được hỗ trợ.
Browser / App
|
| 1) authorize / login
v
Keycloak ---- identity provider / LDAP / AD
|
| 2) code -> tokens
v
Application / API
|
| 3) Bearer access_token
v
Resource Server
2. Realm, user, group, role và client
| Khái niệm | Ý nghĩa | Điểm dễ nhầm |
|---|---|---|
| Realm | Không gian cô lập logic cho users, clients, roles, flows, keys. | master chủ yếu dành cho quản trị server; tránh dùng nó làm realm ứng dụng. |
| User | Danh tính người dùng. | Attribute không đồng nghĩa role. |
| Group | Nhóm users; có thể gán role/attribute cho nhóm. | Group phù hợp mô hình tổ chức; role phù hợp quyền. |
| Realm role | Role dùng chung toàn realm. | Dễ bị cấp quá rộng nếu dùng cho quyền chỉ thuộc một app. |
| Client role | Role thuộc một client cụ thể. | Thường phù hợp hơn cho quyền của từng ứng dụng. |
| Client | Ứng dụng/service nói chuyện với Keycloak. | Client không nhất thiết là UI; backend service cũng là client. |
| Client scope | Bộ mapper/scope tái sử dụng cho clients. | Ảnh hưởng claim/token; không phải role. |
3. OIDC/OAuth2 flow cho ứng dụng
3.1 Authorization Code Flow
Đây là flow điển hình cho web app và browser-based login. User được redirect sang Keycloak, đăng nhập tại đó, client nhận authorization code rồi đổi code lấy token. Với public client, PKCE là lớp bảo vệ quan trọng.
GET /realms/{realm}/protocol/openid-connect/auth
?client_id=my-app
&response_type=code
&redirect_uri=https://app.example.com/callback
&scope=openid
&code_challenge=...
&code_challenge_method=S256
3.2 Client Credentials
Dùng cho machine-to-machine khi không có end-user. Trong Keycloak, service account của client là identity thực thi flow này.
POST /realms/{realm}/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id=worker&client_secret=...
4. Token, claim, scope và session
Ba token thường gặp là access token, ID token và refresh token. Access token phục vụ API/resource server; ID token nói về authentication event và user cho client; refresh token dùng lấy access token mới mà không bắt user đăng nhập lại ngay.
| Token | Dùng cho | Không nên dùng cho |
|---|---|---|
| Access token | Bearer token gọi API | Hiển thị thông tin profile như một contract UI cố định |
| ID token | Client xác nhận user đã authenticate | Bearer token gọi resource server |
| Refresh token | Xin access token mới | Gửi vào API nghiệp vụ |
JWT signature giúp resource server xác minh integrity và issuer. Nhưng token còn cần được kiểm tra iss, thời gian hiệu lực, audience phù hợp và các claim/role cần thiết.
5. Roles, scopes và authorization
RBAC cơ bản có thể thực hiện bằng realm role/client role. Với quyền phức tạp hơn, Keycloak Authorization Services hỗ trợ resource, scope, policy và permission. Tuy nhiên, domain authorization rất chi tiết thường vẫn nên nằm trong application/domain service thay vì đẩy toàn bộ vào IAM.
Authentication: "Bạn là ai?"
Coarse authorization: "Bạn có role REPORT_VIEWER không?"
Domain authorization: "Bạn có được xem invoice 981 của tenant A không?"
Nguyên tắc thực tế: Keycloak quản lý identity và coarse-grained entitlements; application vẫn chịu trách nhiệm với invariant/domain rule.
6. Authentication flow, MFA và required actions
Authentication flow là pipeline execution quyết định user phải đi qua bước nào. Browser flow có thể gồm username/password, conditional OTP, WebAuthn hoặc identity provider redirect. Required Actions dùng cho các việc như đổi password, cấu hình OTP hoặc cập nhật profile.
- Dùng MFA cho admin và tài khoản nhạy cảm.
- Không copy built-in flow rồi sửa vô hạn mà không ghi lại mục đích; flow tùy biến là cấu hình bảo mật cần version-control/export.
- Kiểm thử login, reset password, email verification, logout, expired session và account lockout.
7. Identity brokering và user federation
Identity brokering cho phép Keycloak nhận authentication từ external IdP như một OIDC/SAML provider khác. User federation kết nối user storage như LDAP/Active Directory để Keycloak dùng hoặc đồng bộ identity từ nguồn đó.
| Case | Chọn |
|---|---|
| Đăng nhập bằng corporate Entra/another OIDC IdP | Identity brokering |
| User nằm trong LDAP/AD hiện hữu | User federation |
| Ứng dụng tự có DB user đặc thù | Cân nhắc custom User Storage SPI, nhưng chi phí vận hành cao hơn |
8. Service account và token exchange
Service account phù hợp cho backend service cần token của chính nó. Khi một service đang cầm token của user nhưng cần token nhắm tới service khác, token exchange có thể giúp tránh chuyển tiếp token quá rộng.
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
subject_token=<user-access-token>
audience=target-service
9. Spring Boot resource server mental model
Với Spring Security, ưu tiên OIDC/OAuth2 support chuẩn. Resource server chỉ cần issuer/JWK metadata để verify token, thay vì phụ thuộc adapter Keycloak cũ.
# application.yml (conceptual)
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://sso.example.com/realms/acme
// Authorization ở app
http.authorizeHttpRequests(auth -> auth
.requestMatchers("/health").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated());
10. Production deployment: build, database, hostname, TLS
Keycloak hiện dùng Quarkus distribution. Production nên dùng start, không dùng start-dev. Container nên được build/optimize trước để giảm startup work ở runtime.
# Ví dụ conceptual
/opt/keycloak/bin/kc.sh build --db=postgres
/opt/keycloak/bin/kc.sh start --optimized \
--hostname=https://sso.example.com \
--health-enabled=true \
--metrics-enabled=true
- Dùng external relational database cho production; backup DB là một phần của upgrade plan.
- Cấu hình hostname rõ ràng để tránh URL/issuer bị suy ra từ request không tin cậy.
- Port management mặc định là
9000; không proxy public health/metrics nếu không cần. - Secrets phải đi qua secret manager/environment injection phù hợp, không hard-code vào image/repo.
11. Reverse proxy và TLS
Ở production, Keycloak thường nằm sau reverse proxy/load balancer. Với TLS re-encrypt hoặc edge termination, cấu hình proxy-headers đúng loại header proxy thực sự ghi đè. Với TLS passthrough, không bật proxy-headers; dùng PROXY protocol nếu cần truyền real client IP.
# Re-encrypt / trusted forwarded headers
kc.sh start \
--hostname=https://sso.example.com \
--proxy-headers=xforwarded \
--proxy-trusted-addresses=10.0.0.0/8
Forwarded/X-Forwarded-*, client có thể spoof IP/proto/host và làm sai audit hoặc access-control logic.12. Cluster, cache, session và HA
Cluster nhiều node dùng distributed caches và cần database chia sẻ. Session affinity có thể cải thiện locality, nhưng thiết kế HA không nên giả định sticky session là cơ chế correctness duy nhất. Với multi-site hoặc topology phức tạp, dùng hướng dẫn HA chính thức thay vì tự ghép cache remote theo cấu hình cũ.
- Kiểm tra database latency, connection pool và transaction behavior.
- Hiểu distinction giữa online session, offline session và persistent user sessions.
- Test rolling/upgrade path theo version thực tế; patch rolling update support có điều kiện từ nhánh 26.6+.
13. Health, metrics, logs và OpenTelemetry
Bật health/metrics khi cần vận hành. Container docs hiện mô tả các endpoint management như /health, /health/ready, /health/live và /metrics trên port 9000 khi feature tương ứng được bật.
Những thứ nên monitor: login failure rate, request latency, DB pool, JVM/GC, cache health, cluster membership, HTTP 4xx/5xx, token endpoint latency và admin events.
14. Security checklist production
- Không chạy
start-devở production. - Không dùng
masterrealm cho application users. - Bảo vệ admin console/API; tách hostname hoặc network policy nếu cần.
- Không public management port 9000.
- Hostname cố định; proxy headers chỉ tin từ proxy đã kiểm soát.
- Client secret phải rotate; public client không có secret để “giấu”.
- Redirect URI phải chặt, tránh wildcard quá rộng.
- Access token TTL ngắn hợp lý; refresh/session policy phù hợp risk.
- Enable MFA cho admin và nhóm nhạy cảm.
- Audit admin events và authentication events cần thiết.
- Backup database trước upgrade; đọc migration notes từng version.
- Không chỉ decode JWT — phải verify signature/issuer/expiry/audience theo contract.
15. Debugging theo symptom
| Symptom | Kiểm tra đầu tiên |
|---|---|
| 403 sau reverse proxy | Hostname, origin, proxy-headers, header overwrite. |
| Invalid redirect_uri | Valid Redirect URIs, scheme/host/path thực tế. |
| Token verify fail | iss, JWK, clock skew, signature algorithm, audience. |
| User login được nhưng API 403 | Role claim, client scope, audience, Spring authority mapping. |
| Logout không như mong đợi | SSO session, client session, front/backchannel logout config. |
| Node restart làm session biến mất | Persistent session/cache topology/version config. |
| CPU/latency cao | DB, GC, request rate, cache, login brute-force, external IdP/LDAP latency. |
16. 20 câu hỏi phỏng vấn Keycloak
- Keycloak giải quyết bài toán gì và app còn phải tự chịu trách nhiệm phần nào?
- Realm khác client như thế nào?
- Realm role và client role nên dùng khi nào?
- Authorization Code Flow hoạt động ra sao?
- PKCE bảo vệ vấn đề gì?
- Access token khác ID token như thế nào?
- Tại sao decode JWT chưa đủ để trust token?
- Issuer và audience có vai trò gì?
- Refresh token nên được bảo vệ khác access token ra sao?
- Service account trong Keycloak là gì?
- Khi nào dùng Client Credentials?
- Identity brokering khác user federation như thế nào?
- Authentication flow và Required Action khác nhau ra sao?
- MFA nên được áp dụng ở đâu?
- Vì sao wildcard redirect URI nguy hiểm?
- Keycloak đứng sau reverse proxy cần lưu ý gì?
- Tại sao không nên expose port 9000 ra internet?
- Token exchange giúp giải quyết use case nào?
- Keycloak HA phụ thuộc database/cache như thế nào?
- Bạn debug case login thành công nhưng Spring API trả 403 như thế nào?
17. 6 labs thực hành
Lab 1 — Realm + client + user + role
Tạo realm lab, client spring-api, user và client role report-viewer. Kiểm tra role xuất hiện trong token theo mapper/scope đã cấu hình.
Lab 2 — Authorization Code + PKCE
Dùng một OIDC client public, login qua browser, quan sát authorization code và token exchange. Ghi lại iss, aud, exp, scope.
Lab 3 — Spring Boot Resource Server
Cấu hình issuer-uri, bảo vệ endpoint, map client role sang authority và chứng minh 401 khác 403.
Lab 4 — Service account / Client Credentials
Tạo confidential client có service account, lấy token bằng client credentials và gọi một API chỉ cho machine role.
Lab 5 — Reverse proxy failure drill
Đặt Keycloak sau Nginx/HAProxy. Cố tình cấu hình sai forwarded headers rồi quan sát 403/redirect URL; sau đó sửa bằng hostname + trusted proxy config.
Lab 6 — Production observability drill
Bật health/metrics, kiểm tra port 9000 chỉ ở internal network. Tạo login failure và quan sát log/metrics; viết runbook 5 bước cho on-call.
18. Version notes cần nhớ
- Baseline tài liệu: 26.7.3.
- Standard Token Exchange V2 là supported path; legacy V1 là deprecated/preview.
- Rolling update cho patch releases có support từ 26.6.0 theo điều kiện trong upgrade guide.
- Upgrade phải đọc migration notes từng version và backup database/config trước khi thay server.
Nguồn chính thức
- Keycloak Documentation 26.7.3
- Server Administration Guide
- Configuring Keycloak for production
- Running Keycloak in a container
- Configuring the hostname (v2)
- Configuring a reverse proxy
- Configuring and using token exchange
- Upgrading Guide
Generated as a standalone curriculum supplement. Verify version-specific behavior against the official guide when upgrading beyond 26.7.3.