feat: implement OIDC PKCE flow for Keycloak login with frontend-client
Completed OIDC Authorization Code Flow with PKCE (S256) for JS and JVM platforms. - Added `launchOidcFlow`, `consumePendingOidcCallback`, and `getOidcRedirectUri` with platform-specific implementations. - Integrated SHA-256 and Base64URL helpers for PKCE. - Updated `LoginViewModel` with OIDC logic (key handling, token exchange, state validation). - Enhanced `LoginScreen` with an OIDC login button and loading spinner. - Verified implementation with system hardening roadmap tasks. Includes browser redirects for JS, localhost HTTP callback for JVM, and built-in Keycloak URL construction. Signed-off-by: Stefan Mogeritsch <stefan.mo.co@gmail.com>
This commit is contained in:
@@ -57,7 +57,8 @@ Anbindung des Frontends an den neuen Service.
|
||||
|
||||
### 3.1 HTTP Client & Sync (Frontend Expert)
|
||||
- [ ] **Ktor Client:** Konfiguration des HTTP-Clients für die Kommunikation mit dem Gateway (`http://localhost:8080`).
|
||||
- [ ] **Auth:** Implementierung des OIDC-Flows im Frontend (Login via Keycloak), Speichern des Tokens.
|
||||
- [x] **Auth:** Implementierung des OIDC-Flows im Frontend (Login via Keycloak), Speichern des Tokens. _(verifiziert
|
||||
2026-03-09: PKCE S256 + frontend-client + JVM/JS actual-Implementierungen)_
|
||||
- [ ] **Integration:** Aufruf von `/api/ping` und `/api/ping/secure` und Anzeige im UI.
|
||||
|
||||
### 3.2 Offline-Sync Basis (Frontend Expert)
|
||||
|
||||
@@ -68,5 +68,10 @@ last_update: 2026-03-09
|
||||
- Prüfen der `kotlinx-browser` Version.
|
||||
|
||||
### 3.2 Auth Integration
|
||||
- [ ] **OIDC Client:** _(offen — abhängig von Keycloak Härtung)_
|
||||
- Implementierung des Login-Flows mit `ktor-client-auth` und Keycloak.
|
||||
|
||||
- [x] **OIDC Client:** _(verifiziert 2026-03-09)_
|
||||
- PKCE Authorization Code Flow (S256) mit `frontend-client`.
|
||||
- Pure Kotlin SHA-256 + PkceHelper (commonMain, kein expect/actual).
|
||||
- JVM: lokaler Callback-Server (Port 18080) + `Desktop.browse()`.
|
||||
- JS: Seiten-Redirect + URL-Parsing beim App-Start + `replaceState`-Bereinigung.
|
||||
- `LoginViewModel` + `LoginScreen` um OIDC-Button erweitert.
|
||||
|
||||
@@ -74,7 +74,44 @@ Propagation-Konfiguration im Gateway.
|
||||
- Redundante direkte `micrometer-tracing-bridge-brave`-Dependency entfernt
|
||||
(bereits transitiv via `monitoring-client` vorhanden).
|
||||
|
||||
## ✅ OIDC Client im Frontend (2026-03-09, gleiche Session)
|
||||
|
||||
Login-Flow mit PKCE Authorization Code Flow (S256) für `frontend-client` implementiert.
|
||||
|
||||
### Neue Dateien
|
||||
|
||||
- **`frontend/core/auth/src/commonMain/.../Sha256.kt`**: Pure Kotlin SHA-256 (FIPS 180-4) + Base64URL-Encoding — kein
|
||||
expect/actual, läuft auf JVM/JS/Wasm.
|
||||
- **`frontend/core/auth/src/commonMain/.../PkceHelper.kt`**: Code Verifier, Code Challenge (S256), State Generator.
|
||||
- **`frontend/core/auth/src/commonMain/.../OidcCallback.kt`**: `OidcCallbackResult` sealed class + expect
|
||||
`launchOidcFlow()`, `consumePendingOidcCallback()`, `getOidcRedirectUri()`.
|
||||
- **`frontend/core/auth/src/jvmMain/.../OidcCallback.jvm.kt`**: Eingebetteter `HttpServer` (Port 18080) +
|
||||
`Desktop.browse()` + `CompletableDeferred` (Timeout 5 min).
|
||||
- **`frontend/core/auth/src/jsMain/.../OidcCallback.js.kt`**: `window.location.href` Redirect + URL-Parameter-Parsing
|
||||
beim App-Start + History-Bereinigung via `replaceState`.
|
||||
|
||||
### Geänderte Dateien
|
||||
|
||||
- **`frontend/core/domain/.../AppConstants.kt`**: `KEYCLOAK_CLIENT_ID` → `frontend-client`, OIDC-Konstanten ergänzt.
|
||||
- **`frontend/core/auth/src/commonMain/.../AuthApiClient.kt`**: `buildAuthorizationUrl()` (PKCE URL-Builder) +
|
||||
`exchangeCodeForToken()` (Code → Token).
|
||||
- **`frontend/core/auth/src/commonMain/.../LoginViewModel.kt`**: `isOidcLoading`-State, `startOidcFlow()`,
|
||||
`handleOidcCallbackResult()`, JS-Init-Callback-Check.
|
||||
- **`frontend/core/auth/src/commonMain/.../LoginScreen.kt`**: Divider + `OutlinedButton` „Mit Keycloak anmelden" mit
|
||||
Spinner bei laufendem Flow.
|
||||
|
||||
### Architektur-Entscheidungen
|
||||
|
||||
- **Kein `ktor-client-auth`**: Der OIDC-Flow wird manuell implementiert — `ktor-client-auth` unterstützt Authorization
|
||||
Code + PKCE nicht nativ für KMP.
|
||||
- **Pure Kotlin SHA-256**: Kein `expect/actual` nötig — `kotlin.math` + reine Bitoperationen reichen aus.
|
||||
- **JVM-Callback-Server** auf `localhost:18080`: Standard-Muster für Desktop-Apps (RFC 8252 „OAuth 2.0 for Native
|
||||
Apps").
|
||||
- **JS-Redirect-Flow**: Kein Popup — volle Seitenweiterleitung. Code Verifier wird in `sessionStorage` gespeichert (nur
|
||||
aktueller Tab).
|
||||
- **State-Validierung**: CSRF-Schutz via State-Parameter-Vergleich im ViewModel.
|
||||
|
||||
## 🔜 Nächste Schritte
|
||||
|
||||
- **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.
|
||||
- **Gateway CircuitBreaker** — Verifizieren ob durch Spring Cloud 2025.0.1 bereits behoben.
|
||||
|
||||
Reference in New Issue
Block a user