docs: finalize Keycloak hardening and validate updated Realm config

Documented the completed Keycloak hardening steps, including PKCE S256 support, CORS security improvements, strengthened password policy, and logout redirect URI configurations. Verified and updated the `meldestelle-realm.json` and roadmap to reflect these changes.

Signed-off-by: Stefan Mogeritsch <stefan.mo.co@gmail.com>
This commit is contained in:
Stefan Mogeritsch 2026-03-09 11:10:21 +01:00
parent f47e5f6415
commit 440ab4b141
4 changed files with 105 additions and 11 deletions

View File

@ -93,8 +93,7 @@
"http://localhost:8081",
"http://localhost:3000",
"https://app.meldestelle.at",
"http://localhost:8080",
"*"
"http://localhost:8080"
],
"protocol": "openid-connect",
"bearerOnly": false,
@ -111,7 +110,8 @@
"client.secret.creation.time": "0",
"oauth2.device.authorization.grant.enabled": "false",
"backchannel.logout.session.required": "true",
"backchannel.logout.revoke.offline.tokens": "false"
"backchannel.logout.revoke.offline.tokens": "false",
"post.logout.redirect.uris": "http://localhost:8081/*##http://localhost:3000/*##https://app.meldestelle.at/*"
},
"protocolMappers": [
{
@ -202,12 +202,12 @@
"http://localhost:8080",
"http://localhost:4000",
"http://localhost:3000",
"https://app.meldestelle.at",
"*"
"https://app.meldestelle.at"
],
"protocol": "openid-connect",
"attributes": {
"pkce.code.challenge.method": "S256"
"pkce.code.challenge.method": "S256",
"post.logout.redirect.uris": "http://localhost:8080/*##http://localhost:4000/*##http://localhost:3000/*##https://app.meldestelle.at/*"
}
},
{
@ -229,6 +229,47 @@
"directAccessGrantsEnabled": true,
"serviceAccountsEnabled": false,
"fullScopeAllowed": true
},
{
"clientId": "frontend-client",
"name": "Meldestelle Desktop & Mobile Client",
"description": "Public PKCE client for the KMP Compose Desktop/Mobile application",
"enabled": true,
"publicClient": true,
"protocol": "openid-connect",
"standardFlowEnabled": true,
"implicitFlowEnabled": false,
"directAccessGrantsEnabled": false,
"serviceAccountsEnabled": false,
"authorizationServicesEnabled": false,
"attributes": {
"pkce.code.challenge.method": "S256",
"post.logout.redirect.uris": "meldestelle://callback##http://localhost:*##https://app.meldestelle.at/*"
},
"redirectUris": [
"meldestelle://callback",
"http://localhost:*",
"https://app.meldestelle.at/*"
],
"webOrigins": [
"http://localhost:8080",
"http://localhost:4000",
"https://app.meldestelle.at"
],
"defaultClientScopes": [
"web-origins",
"acr",
"roles",
"profile",
"basic",
"email"
],
"optionalClientScopes": [
"address",
"phone",
"offline_access",
"microprofile-jwt"
]
}
],
"users": [
@ -266,7 +307,7 @@
"requiredCredentials": [
"password"
],
"passwordPolicy": "length(8)",
"passwordPolicy": "length(10) and digits(1) and upperCase(1) and specialChars(1) and notUsername(undefined)",
"otpPolicyType": "totp",
"otpPolicyAlgorithm": "HmacSHA1",
"otpPolicyInitialCounter": 0,
@ -354,4 +395,4 @@
"clientSessionMaxLifespan": "0",
"clientOfflineSessionIdleTimeout": "0"
}
}
}

View File

@ -28,7 +28,8 @@ Das Ziel dieser Phase ist es, die Entwicklungsumgebung (Build, Docker, Dependenc
### 1.2 Infrastruktur & Docker (DevOps)
- [ ] **Gateway CircuitBreaker:** Behebung des `ClassNotFoundException` / `NoSuchMethodError` im Gateway (vermutlich Folge des Spring Cloud Konflikts).
- [ ] **Docker Stabilität:** Sicherstellen, dass `docker compose up` zuverlässig alle Services (Consul, Keycloak, Postgres) startet und vernetzt.
- [ ] **Keycloak Config:** Validierung der Realm-Konfiguration (`meldestelle`) und der Client-Scopes für den `ping-service`.
- [x] **Keycloak Config:** Validierung der Realm-Konfiguration (`meldestelle`) und der Client-Scopes für den
`ping-service`. _(verifiziert 2026-03-09: frontend-client + PKCE + CORS-Härtung + Password-Policy umgesetzt)_
---

View File

@ -43,9 +43,12 @@ last_update: 2026-03-09
- Prüfen, ob wir Redis durch Valkey (Open Source Fork) ersetzen, um Lizenzprobleme zu vermeiden.
- Update `docker-compose.yaml`.
- _(verifiziert 2026-03-09: valkey/valkey:9-alpine läuft produktiv in dc-infra.yaml)_
- [ ] **Keycloak Härtung:** _(offen — Priorität: technische Stabilisierung)_
- [x] **Keycloak Härtung:** _(verifiziert 2026-03-09)_
- Export der Realm-Config (`meldestelle-realm.json`) und Mounten im Container (statt manueller Config).
- Sicherstellen, dass `frontend-client` korrekte Redirect-URIs für Desktop & Web hat.
- `frontend-client` (PKCE S256, Custom URI Scheme `meldestelle://callback`) hinzugefügt.
- Wildcard `*` aus `webOrigins` aller Clients entfernt (CORS-Härtung).
- Password-Policy auf `length(10) + digits + upperCase + specialChars` gestärkt.
- `post.logout.redirect.uris` für alle Clients konfiguriert.
### 2.2 Observability
- [ ] **Zipkin Integration:** _(offen — Priorität: technische Stabilisierung)_

View File

@ -0,0 +1,49 @@
# Journal - 2026-03-09
## 📝 Zusammenfassung
Keycloak-Härtung der Realm-Konfiguration (`meldestelle-realm.json`). Aufbauend auf dem Infrastruktur-Fix vom
2026-03-06 (korrektes `start --optimized`, Healthcheck) wurden nun die Client-Konfigurationen und
Sicherheitseinstellungen auf einen produktionsreifen Stand gebracht.
## 🛠️ Änderungen
### 1. `config/docker/keycloak/meldestelle-realm.json`
#### Wildcard aus `webOrigins` entfernt
- **Vorher:** `api-gateway` und `web-app` hatten `"*"` in `webOrigins` (CORS-Sicherheitslücke).
- **Nachher:** Nur explizit erlaubte Origins (`localhost:*`, `app.meldestelle.at`).
#### Neuer Client: `frontend-client` (KMP Desktop & Mobile)
- **Public Client** mit **PKCE S256** (kein Client-Secret nötig, sicher für native Apps).
- **Redirect URIs:** `meldestelle://callback` (Custom URI Scheme für Desktop), `http://localhost:*` (Dev),
`https://app.meldestelle.at/*` (Prod).
- **Kein `directAccessGrantsEnabled`** — verhindert Password-Grant-Flow (unsicher für native Apps).
#### Password-Policy gestärkt
- **Vorher:** `length(8)` — zu schwach.
- **Nachher:** `length(10) and digits(1) and upperCase(1) and specialChars(1) and notUsername(undefined)`.
#### `post.logout.redirect.uris` konfiguriert
- Alle relevanten Clients (`api-gateway`, `web-app`, `frontend-client`) haben nun korrekte Logout-Redirect-URIs gemäß
OIDC Back-Channel Logout Standard.
## 📚 Gelerntes / Entscheidungen
- **`meldestelle://callback`** als Custom URI Scheme: Für KMP Compose Desktop ist ein eigenes URI-Schema der sichere
Standard (kein offener HTTP-Port nötig). Muss im OS registriert werden.
- **PKCE S256 ist Pflicht für Public Clients:** Verhindert Authorization Code Interception Attacks. Keycloak `26.x`
unterstützt dies nativ.
- **`frontend-client` vs. `web-app`:** Klare Trennung: `web-app` für Browser-basierte Web-App, `frontend-client` für
native KMP Desktop/Mobile-App.
## 🔜 Nächste Schritte
- **Micrometer Upgrade** (`1.16.1`) — Quick-Win in `libs.versions.toml`.
- **Zipkin Integration** — Tracing vom Gateway bis zur DB aktivieren.
- **OIDC Client im Frontend** — Login-Flow mit `ktor-client-auth` und `frontend-client` implementieren.
- **TLS/HTTPS** — Langfristig: `KC_HOSTNAME_STRICT_HTTPS=true` setzen, sobald TLS eingerichtet ist.