fixing Keycloak Auth

This commit is contained in:
2025-10-02 00:52:24 +02:00
parent 72036207b0
commit 3e3af214e6
21 changed files with 1155 additions and 438 deletions
+458
View File
@@ -0,0 +1,458 @@
# 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
1. **Keycloak Server** (Port 8180 extern, 8080 intern)
- OAuth2/OpenID Connect Provider
- PostgreSQL Backend
- Realm: `meldestelle`
2. **API Gateway**
- OAuth2 Resource Server
- JWT-Validierung via JWK-Set
- Rollenbasierte Autorisierung
3. **PostgreSQL Database**
- Keycloak-Schema: `keycloak`
- Automatische Schema-Initialisierung
## Konfiguration
### Docker Compose
#### Keycloak Service
```yaml
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)
```json
{
"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)
```json
{
"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`
```kotlin
@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`
```yaml
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:
```sql
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:
```dockerfile
FROM quay.io/keycloak/keycloak:26.0.7 AS builder
RUN /opt/keycloak/bin/kc.sh build --db=postgres
```
**Verwendung in docker-compose.yml**:
```yaml
keycloak:
build:
context: .
dockerfile: dockerfiles/infrastructure/keycloak/Dockerfile
```
### Umgebungsvariablen für Produktion
Erstellen Sie eine `.env` Datei:
```env
# 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:
1. **Empfohlen**: Reverse Proxy (nginx, Traefik)
```yaml
KC_PROXY: edge
KC_HTTP_ENABLED: true
KC_HOSTNAME_STRICT_HTTPS: false
```
2. **Direkt mit Keycloak**:
```yaml
KC_HTTPS_CERTIFICATE_FILE: /path/to/cert.pem
KC_HTTPS_CERTIFICATE_KEY_FILE: /path/to/key.pem
KC_HTTP_ENABLED: false
```
## Betrieb
### Start
```bash
# 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
```bash
# Keycloak Readiness
curl http://localhost:8180/health/ready
# Keycloak Liveness
curl http://localhost:8180/health/live
# Metrics
curl http://localhost:8180/metrics
```
### Logs
```bash
# 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**:
1. Prüfen Sie PostgreSQL Verbindung:
```bash
docker-compose logs postgres
```
2. Schema-Berechtigungen prüfen:
```sql
\dn+ keycloak
```
3. Keycloak Logs prüfen:
```bash
docker-compose logs keycloak
```
### Problem: JWT Validierung schlägt fehl
**Symptom**: 401 Unauthorized trotz gültigem Token
**Lösung**:
1. Issuer URI prüfen:
```bash
curl http://keycloak:8080/realms/meldestelle/.well-known/openid-configuration
```
2. JWK-Set prüfen:
```bash
curl http://keycloak:8080/realms/meldestelle/protocol/openid-connect/certs
```
3. Gateway-Logs prüfen:
```bash
docker-compose logs api-gateway | grep -i jwt
```
### Problem: Realm nicht importiert
**Symptom**: Realm `meldestelle` existiert nicht
**Lösung**:
1. Prüfen Sie Volume-Mount:
```bash
docker-compose config | grep -A 5 "keycloak:" | grep volumes
```
2. Realm-Datei prüfen:
```bash
ls -la docker/services/keycloak/
```
3. Container neu starten:
```bash
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**:
```yaml
gateway:
security:
keycloak:
enabled: true # Custom Filter
```
**Neu**:
```yaml
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: http://keycloak:8080/realms/meldestelle
gateway:
security:
keycloak:
enabled: false # Spring Security oauth2ResourceServer verwenden
```
## Best Practices
### Sicherheit
1.**Verwenden Sie starke Admin-Passwörter**
2.**Aktivieren Sie HTTPS in Produktion**
3.**Regelmäßige Backups der Keycloak-Datenbank**
4.**Überwachen Sie Failed Login Attempts**
5.**Verwenden Sie Service Accounts für Backend-Services**
### Performance
1.**Database Connection Pool anpassen** (KC_DB_POOL_MAX_SIZE)
2.**JVM Memory optimieren** (JAVA_OPTS_APPEND)
3.**Pre-built Image verwenden** (Dockerfile)
4.**Cache aktivieren** (KC_CACHE=ispn)
### Monitoring
1.**Metrics überwachen** (/metrics Endpoint)
2.**Health Checks konfigurieren**
3.**Event Logging aktivieren**
4.**Admin Events protokollieren**
## Weitere Ressourcen
- [Keycloak Official Documentation](https://www.keycloak.org/documentation)
- [Spring Security OAuth2 Resource Server](https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/index.html)
- [OpenID Connect Specification](https://openid.net/specs/openid-connect-core-1_0.html)
## Support
Bei Problemen oder Fragen:
1. Prüfen Sie die Logs
2. Konsultieren Sie dieses Dokument
3. Kontaktieren Sie das Development Team