Quick start (Làm ngay trong 5 phút)
Cần dựng nhanh một cụm Keycloak trên Fedora Server để kiểm thử ứng dụng hoặc làm môi trường sandbox? Chỉ mất khoảng 5 phút với vài lệnh cơ bản dưới đây.
Đầu tiên, hãy cài OpenJDK 21 cùng các công cụ giải nén cần thiết:
sudo dnf install -y java-21-openjdk-headless tar gzip curl
Tiếp theo, tải bản phân phối Keycloak (Quarkus runtime) và giải nén vào thư mục /opt:
cd /opt
KEYCLOAK_VERSION="24.0.2"
sudo curl -LO https://github.com/keycloak/keycloak/releases/download/${KEYCLOAK_VERSION}/keycloak-${KEYCLOAK_VERSION}.tar.gz
sudo tar -xzf keycloak-${KEYCLOAK_VERSION}.tar.gz
sudo mv keycloak-${KEYCLOAK_VERSION} keycloak
sudo rm -f keycloak-${KEYCLOAK_VERSION}.tar.gz
Thiết lập thông tin tài khoản admin tạm thời rồi khởi chạy ở chế độ phát triển (development mode):
export KEYCLOAK_ADMIN=admin
export KEYCLOAK_ADMIN_PASSWORD=AdminStrongPassword123!
/opt/keycloak/bin/kc.sh start-dev --http-port=8080
Fedora Server mặc định chặn các port ngoài SSH. Bạn mở port 8080 qua firewalld:
sudo firewall-cmd --add-port=8080/tcp --permanent
sudo firewall-cmd --reload
Bây giờ, hãy mở trình duyệt và truy cập http://<IP-Fedora-Server>:8080. Đăng nhập bằng user admin vừa tạo để vào ngay bảng điều khiển Admin Console.
Giải thích chi tiết: Kiến trúc và cách Keycloak vận hành SSO
1. Các khái niệm cốt lõi trong Keycloak
Để làm chủ Keycloak trong bài toán SSO và IAM, bạn chỉ cần nắm vững 4 khái niệm nền tảng này:
- Realm: Không gian quản lý người dùng độc lập (multi-tenant). Mặc định hệ thống có realm
masterchuyên dùng để quản trị. Với các dự án thực tế, bạn nên tạo realm riêng biệt (ví dụ:internal-corphoặcecommerce-app). - Client: Mọi ứng dụng cần Keycloak xác thực danh tính, từ Frontend SPA (React, Vue), Mobile App (Flutter) cho đến Backend REST API (FastAPI, Spring Boot).
- Roles & Groups: Quản lý và phân quyền người dùng. Bạn có thể gán quyền toàn cục (Realm Roles) hoặc cấp quyền cục bộ theo từng ứng dụng cụ thể (Client Roles).
- Identity Providers (IdP): Cầu nối xác thực ngoại bộ. Giúp người dùng đăng nhập qua Google, GitHub, Microsoft 365 hoặc đồng bộ với hệ thống LDAP / Active Directory sẵn có.
2. Cơ chế Authorization Code Flow với PKCE (OIDC)
Đây là luồng chuẩn bảo mật cao nhất hiện nay cho các ứng dụng web và mobile. Quá trình đăng nhập diễn ra qua 6 bước:
- Người dùng bấm nút "Đăng nhập" trên ứng dụng web (Client).
- Trình duyệt chuyển hướng sang Keycloak qua endpoint
/realms/{realm-name}/protocol/openid-connect/authkèm theocode_challenge(PKCE). - Người dùng nhập thông tin đăng nhập và xác thực 2FA/OTP (nếu được kích hoạt).
- Keycloak xác thực thành công và trả về mã ủy quyền (Authorization Code) vào redirect URI.
- Backend của Client gửi Authorization Code cùng
code_verifiervề Keycloak để đổi lấy cặp ID Token và Access Token (định dạng JWT). - Client lưu token, duy trì phiên đăng nhập và hoàn toàn không cần lưu giữ mật khẩu gốc của người dùng.
3. Cấu hình Production với PostgreSQL và Systemd trên Fedora
Database H2 mặc định của chế độ dev chỉ lưu dữ liệu tạm thời trong RAM hoặc file cục bộ. Khi đưa lên môi trường thực tế (production), bạn bắt buộc phải dùng PostgreSQL để đảm bảo tính sẵn sàng và toàn vẹn dữ liệu.
Cài đặt và khởi tạo PostgreSQL trên Fedora:
sudo dnf install -y postgresql-server postgresql-contrib
sudo postgresql-setup --initdb
sudo systemctl enable --now postgresql
# Tạo user và database cho Keycloak
sudo -u postgres psql -c "CREATE DATABASE keycloak;"
sudo -u postgres psql -c "CREATE USER keycloak WITH ENCRYPTED PASSWORD 'KeycloakDBPass456!';"
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE keycloak TO keycloak;"
Tiếp đến, chỉnh sửa file cấu hình /opt/keycloak/conf/keycloak.conf:
# Database
db=postgres
db-username=keycloak
db-password=KeycloakDBPass456!
db-url=jdbc:postgresql://localhost:5432/keycloak
# HTTP & Proxy
http-enabled=true
http-port=8080
proxy-headers=xforwarded
hostname=sso.yourcompany.com
Để bảo mật, không bao giờ chạy Keycloak dưới quyền root. Hãy tạo một system user riêng:
sudo useradd -r -d /opt/keycloak -s /sbin/nologin keycloak
sudo chown -R keycloak:keycloak /opt/keycloak
Tạo file cấu hình dịch vụ Systemd tại /etc/systemd/system/keycloak.service. Bước kc.sh build sẽ biên dịch trước các cấu hình tĩnh giúp rút ngắn thời gian khởi động dịch vụ từ 15-20s xuống còn dưới 3s:
[Unit]
Description=Keycloak Identity Provider
After=network.target postgresql.service
[Service]
Type=exec
User=keycloak
Group=keycloak
Environment="KEYCLOAK_ADMIN=admin"
Environment="KEYCLOAK_ADMIN_PASSWORD=YourRootPassword"
ExecStartPre=/opt/keycloak/bin/kc.sh build
ExecStart=/opt/keycloak/bin/kc.sh start --optimized
TimeoutStartSec=600
TimeoutStopSec=60
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
Nạp lại cấu hình và kích hoạt service khởi động cùng hệ điều hành:
sudo systemctl daemon-reload
sudo systemctl enable --now keycloak
sudo systemctl status keycloak
Nâng cao: Tích hợp ứng dụng Web và Reverse Proxy Nginx
1. Thiết lập Realm và Client trên giao diện Admin
- Nhấp vào menu thả xuống ở góc trái trên cùng, chọn Create Realm > Đặt tên
Internal-Company. - Vào mục Clients > Chọn Create Client:
- Client type:
OpenID Connect - Client ID:
web-portal - Client authentication: Bật
On(nếu là backend API hoặc ứng dụng SSR) hoặcOff(nếu là SPA React/Vue hoặc mobile app). - Valid redirect URIs:
https://app.yourcompany.com/callback - Web origins:
https://app.yourcompany.com
2. Cấu hình Nginx Reverse Proxy với SSL
Keycloak cần đứng sau một Reverse Proxy để xử lý SSL termination và định tuyến lưu lượng HTTPS. Tạo file cấu hình tại /etc/nginx/conf.d/keycloak.conf:
server {
listen 80;
server_name sso.yourcompany.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name sso.yourcompany.com;
ssl_certificate /etc/letsencrypt/live/sso.yourcompany.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sso.yourcompany.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
}
}
3. Code mẫu xác thực JWT Token trong Backend (Python FastAPI)
Dưới đây là đoạn middleware mẫu giúp backend xác thực chữ ký số và giải mã Access Token gửi từ client:
import jwt
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
import requests
app = FastAPI()
security = HTTPBearer()
KEYCLOAK_URL = "https://sso.yourcompany.com/realms/Internal-Company"
# Trong môi trường production, bạn nên cache kết quả JWKS certs để tránh gọi HTTP liên tục
jwks_url = f"{KEYCLOAK_URL}/protocol/openid-connect/certs"
jwks = requests.get(jwks_url).json()
def verify_token(credentials: HTTPAuthorizationCredentials = Depends(security)):
token = credentials.credentials
try:
# Lấy signing key tương ứng từ JWKS
header = jwt.get_unverified_header(token)
key = [k for k in jwks['keys'] if k['kid'] == header['kid']][0]
public_key = jwt.algorithms.RSAAlgorithm.from_jwk(key)
payload = jwt.decode(
token,
public_key,
algorithms=["RS256"],
audience="account"
)
return payload
except Exception:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Token không hợp lệ hoặc đã hết hạn"
)
@app.get("/api/v1/protected-data")
def get_data(user: dict = Depends(verify_token)):
return {"status": "success", "user": user.get("preferred_username", "Unknown")}
Tips thực tế và xử lý lỗi thường gặp
- Tận dụng cập nhật nhanh trên Fedora: Fedora luôn sở hữu các bản OpenJDK và công cụ mạng mới nhất. Bạn có thể kiểm tra trực tiếp kết nối LDAP/PostgreSQL bằng
nchoặctcpdumpmà không lo thiếu dependencies hay phải cài repo ngoài. - Lỗi "Invalid parameter: redirect_uri": Đây là lỗi hay gặp nhất khi mới tích hợp. Nguyên nhân do URL gửi trong request không khớp từng ký tự với mục Valid redirect URIs trên Keycloak (kể cả dấu
/ở cuối hoặchttpvshttps). Tuyệt đối không dùng ký tự wildcard*trên production để phòng ngừa lỗ hổng Open Redirect. - Tối ưu RAM và JVM Heap: Mặc định Quarkus chiếm khoảng 400MB – 600MB RAM khi khởi động. Với hệ thống phục vụ trên 1.000 người dùng đồng thời (CCU), bạn nên gán cố định heap size bằng biến
JAVA_OPTS_KC_HEAP="-Xms1024m -Xmx2048m"trong file service để tránh lỗi OutOfMemory. - Khắc phục lỗi 502 Bad Gateway do Header quá lớn: Header chứa Cookie xác thực và Access Token của Keycloak có thể nặng tới 8KB – 16KB. Nếu Nginx báo lỗi
502 Bad Gateway, hãy tăngproxy_buffer_size 128k;vàproxy_buffers 4 256k;như mẫu cấu hình Nginx ở trên.
