10 KiB
Keycloak Integration - Setup und Konfiguration
Übersicht
Dieses Dokument beschreibt die vollständige Keycloak-Integration für das Meldestelle-System, einschließlich Authentifizierung, Konfiguration und Best Practices.
Architektur
Authentifizierungsansatz
Das System verwendet Spring Security OAuth2 Resource Server für die JWT-Validierung:
-
✅ Empfohlener Ansatz: Spring Security
oauth2ResourceServer- Kryptographisch sichere JWT-Signaturvalidierung
- Automatische JWK-Set-Aktualisierung
- Standardkonform (RFC 7519, RFC 7517)
- Integriert mit Spring Security Authorization
-
❌ NICHT verwendet: Custom JWT Filter
- Frühere Implementierungen wurden entfernt
- Hatten Sicherheitslücken (fehlende Signaturvalidierung)
Komponenten
-
Keycloak Server (Port 8180 extern, 8080 intern)
- OAuth2/OpenID Connect Provider
- PostgreSQL Backend
- Realm:
meldestelle
-
API Gateway
- OAuth2 Resource Server
- JWT-Validierung via JWK-Set
- Rollenbasierte Autorisierung
-
PostgreSQL Database
- Keycloak-Schema:
keycloak - Automatische Schema-Initialisierung
- Keycloak-Schema:
Konfiguration
Docker Compose
Keycloak Service
keycloak:
image: quay.io/keycloak/keycloak:26.0.7
environment:
# Admin-Zugangsdaten (IN PRODUKTION ÄNDERN!)
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
# Datenbank
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://postgres:5432/meldestelle
KC_DB_SCHEMA: keycloak
# Connection Pool Optimierung
KC_DB_POOL_INITIAL_SIZE: 5
KC_DB_POOL_MIN_SIZE: 5
KC_DB_POOL_MAX_SIZE: 20
# JVM Optimierung
JAVA_OPTS_APPEND: >-
-XX:MaxRAMPercentage=75.0
-XX:+UseG1GC
-XX:+UseStringDeduplication
Produktionsmodus
Der Service läuft im Produktionsmodus (start --optimized):
- Schnellerer Start durch Pre-Build
- Optimierte Performance
- Geeignet für Produktionsumgebungen
Wichtig: Für Entwicklung kann auf start-dev umgestellt werden.
Realm-Konfiguration
Datei: docker/services/keycloak/meldestelle-realm.json
Realm: meldestelle
- Display Name: Meldestelle Authentication
- Sprachen: Deutsch (Standard), Englisch
- SSL: External (hinter Reverse Proxy)
Sicherheitseinstellungen
-
Brute Force Protection: Aktiviert
- Max. 5 Fehlversuche
- 15 Minuten Sperrzeit
-
Password Policy:
- Mindestens 8 Zeichen
- Mind. 1 Ziffer, 1 Kleinbuchstabe, 1 Großbuchstabe, 1 Sonderzeichen
- Nicht identisch mit Username
Token-Einstellungen
- Access Token Lifespan: 5 Minuten (300 Sek.)
- SSO Session Idle: 30 Minuten (1800 Sek.)
- SSO Session Max: 10 Stunden (36000 Sek.)
- Refresh Token: Einmalige Verwendung
Clients
1. api-gateway (Confidential Client)
{
"clientId": "api-gateway",
"protocol": "openid-connect",
"publicClient": false,
"bearerOnly": false,
"standardFlowEnabled": true,
"directAccessGrantsEnabled": true,
"serviceAccountsEnabled": true
}
Verwendung: Backend-Service-to-Service Kommunikation
Secret: Muss in Keycloak UI generiert und konfiguriert werden
2. web-app (Public Client)
{
"clientId": "web-app",
"publicClient": true,
"standardFlowEnabled": true,
"attributes": {
"pkce.code.challenge.method": "S256"
}
}
Verwendung: Frontend Single-Page Application (mit PKCE)
Rollen
| Rolle | Beschreibung | Verwendung |
|---|---|---|
ADMIN |
Vollzugriff | Systemadministration |
USER |
Standardbenutzer | Normale Anwendungsfunktionen |
MONITORING |
Überwachung | Metriken und Health Checks |
GUEST |
Gast | Minimaler Zugriff |
Standard-Benutzer
Username: admin
Passwort: Change_Me_In_Production! (temporär, muss beim ersten Login geändert werden)
Rollen: ADMIN, USER
Spring Security Konfiguration
Gateway SecurityConfig
Datei: infrastructure/gateway/src/main/kotlin/.../SecurityConfig.kt
@Bean
fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
return http
.oauth2ResourceServer { oauth2 ->
oauth2.jwt { jwt ->
jwt.jwtDecoder(jwtDecoder())
}
}
.authorizeExchange { exchanges ->
exchanges
.pathMatchers("/api/admin/**").hasRole("ADMIN")
.pathMatchers("/api/monitoring/**").hasAnyRole("ADMIN", "MONITORING")
.anyExchange().authenticated()
}
.build()
}
Application Properties
Datei: application-keycloak.yml
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: http://keycloak:8080/realms/meldestelle
jwk-set-uri: http://keycloak:8080/realms/meldestelle/protocol/openid-connect/certs
gateway:
security:
keycloak:
enabled: false # Custom filter deaktiviert - oauth2ResourceServer wird verwendet
Datenbank-Setup
PostgreSQL Schema
Datei: docker/services/postgres/01-init-keycloak-schema.sql
Das Schema wird automatisch beim ersten Start von PostgreSQL erstellt:
CREATE SCHEMA IF NOT EXISTS keycloak;
GRANT ALL PRIVILEGES ON SCHEMA keycloak TO meldestelle;
Keycloak erstellt seine Tabellen automatisch im keycloak Schema.
Produktion Deployment
Dockerfile
Optional: dockerfiles/infrastructure/keycloak/Dockerfile
Pre-built optimiertes Image für schnelleren Start:
FROM quay.io/keycloak/keycloak:26.0.7 AS builder
RUN /opt/keycloak/bin/kc.sh build --db=postgres
Verwendung in docker-compose.yml:
keycloak:
build:
context: .
dockerfile: dockerfiles/infrastructure/keycloak/Dockerfile
Umgebungsvariablen für Produktion
Erstellen Sie eine .env Datei:
# Keycloak Admin (ÄNDERN!)
KEYCLOAK_ADMIN=admin
KEYCLOAK_ADMIN_PASSWORD=<starkes_passwort>
# Datenbank
POSTGRES_USER=meldestelle
POSTGRES_PASSWORD=<db_passwort>
POSTGRES_DB=meldestelle
# Keycloak Konfiguration
KC_HOSTNAME_STRICT=true
KC_HOSTNAME_STRICT_HTTPS=true
KC_HTTP_ENABLED=false
KC_PROXY=edge
# JVM Memory (optional)
KC_DB_POOL_MAX_SIZE=50
SSL/TLS
Für HTTPS in Produktion:
-
Empfohlen: Reverse Proxy (nginx, Traefik)
KC_PROXY: edge KC_HTTP_ENABLED: true KC_HOSTNAME_STRICT_HTTPS: false -
Direkt mit Keycloak:
KC_HTTPS_CERTIFICATE_FILE: /path/to/cert.pem KC_HTTPS_CERTIFICATE_KEY_FILE: /path/to/key.pem KC_HTTP_ENABLED: false
Betrieb
Start
# Alle Services starten
docker-compose up -d
# Nur Infrastruktur (inkl. Keycloak)
docker-compose up -d postgres redis keycloak consul
Keycloak Admin Console
URL: http://localhost:8180 Username: admin Passwort: admin (Standard)
Health Checks
# Keycloak Readiness
curl http://localhost:8180/health/ready
# Keycloak Liveness
curl http://localhost:8180/health/live
# Metrics
curl http://localhost:8180/metrics
Logs
# Keycloak Logs anzeigen
docker-compose logs -f keycloak
# Letzte 100 Zeilen
docker-compose logs --tail=100 keycloak
Troubleshooting
Problem: Keycloak startet nicht
Symptom: Container stoppt sofort nach Start
Lösung:
-
Prüfen Sie PostgreSQL Verbindung:
docker-compose logs postgres -
Schema-Berechtigungen prüfen:
\dn+ keycloak -
Keycloak Logs prüfen:
docker-compose logs keycloak
Problem: JWT Validierung schlägt fehl
Symptom: 401 Unauthorized trotz gültigem Token
Lösung:
-
Issuer URI prüfen:
curl http://keycloak:8080/realms/meldestelle/.well-known/openid-configuration -
JWK-Set prüfen:
curl http://keycloak:8080/realms/meldestelle/protocol/openid-connect/certs -
Gateway-Logs prüfen:
docker-compose logs api-gateway | grep -i jwt
Problem: Realm nicht importiert
Symptom: Realm meldestelle existiert nicht
Lösung:
-
Prüfen Sie Volume-Mount:
docker-compose config | grep -A 5 "keycloak:" | grep volumes -
Realm-Datei prüfen:
ls -la docker/services/keycloak/ -
Container neu starten:
docker-compose restart keycloak
Migration von alter Implementierung
Entfernte Komponenten
Die folgenden Dateien wurden entfernt (waren unsicher/redundant):
-
❌
infrastructure/gateway/security/KeycloakJwtAuthenticationFilter.kt- Grund: Keine kryptographische Signaturvalidierung
- Ersetzt durch: Spring Security oauth2ResourceServer
-
❌
infrastructure/gateway/filter/KeycloakJwtAuthenticationFilter.kt- Grund: Redundant zu oauth2ResourceServer
- Ersetzt durch: Spring Security oauth2ResourceServer
Konfigurationsänderungen
Alt:
gateway:
security:
keycloak:
enabled: true # Custom Filter
Neu:
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: http://keycloak:8080/realms/meldestelle
gateway:
security:
keycloak:
enabled: false # Spring Security oauth2ResourceServer verwenden
Best Practices
Sicherheit
- ✅ Verwenden Sie starke Admin-Passwörter
- ✅ Aktivieren Sie HTTPS in Produktion
- ✅ Regelmäßige Backups der Keycloak-Datenbank
- ✅ Überwachen Sie Failed Login Attempts
- ✅ Verwenden Sie Service Accounts für Backend-Services
Performance
- ✅ Database Connection Pool anpassen (KC_DB_POOL_MAX_SIZE)
- ✅ JVM Memory optimieren (JAVA_OPTS_APPEND)
- ✅ Pre-built Image verwenden (Dockerfile)
- ✅ Cache aktivieren (KC_CACHE=ispn)
Monitoring
- ✅ Metrics überwachen (/metrics Endpoint)
- ✅ Health Checks konfigurieren
- ✅ Event Logging aktivieren
- ✅ Admin Events protokollieren
Weitere Ressourcen
Support
Bei Problemen oder Fragen:
- Prüfen Sie die Logs
- Konsultieren Sie dieses Dokument
- Kontaktieren Sie das Development Team