Phase B: Keycloak OIDC (PKCE) statt Cookie-Session-Login

App-Code:
- KeycloakOidcTokenProvider: PKCE-Login via flutter_appauth, Refresh via
  Refresh-Token aus flutter_secure_storage, Session-Restore beim
  App-Start, Logout.
- AuthSessionEvent als Provider→Bloc-Brücke (LoggedIn/LoggedOut/
  SessionExpired) auf einem Broadcast-Stream.
- AuthBloc komplett umgebaut: nimmt jetzt den KeycloakOidcTokenProvider
  statt UserInfoService, mappt eingehende Provider-Events auf eigene
  Zustände. Authenticated.fromClaims() liest personalnummer + Name aus
  dem ID-Token-Payload.
- LoginPage: kein Browser+Deep-Link mehr — Button feuert
  LoginRequested, der Provider übernimmt den restlichen Flow.
- network_locator: produktiver KeycloakOidcTokenProvider, doppelt
  registriert (KeycloakOidcTokenProvider für AuthBloc,
  AuthTokenProvider für Interceptor).
- Auth-State trägt zusätzlich personalnummer/displayName/email; das
  Legacy-User-Objekt + sessionId bleiben temporär drin, damit die
  alten ERPframe-Services (Phase D) noch kompilieren.

Plattform-Setup:
- Android: appAuthRedirectScheme=holzleitner in build.gradle.kts,
  NetworkSecurityConfig erlaubt HTTP zu localhost/10.0.2.2/127.0.0.1.
- iOS: holzleitner als URL-Scheme im Info.plist, ATS-Ausnahme für
  localhost (HTTP-Keycloak im Dev-Setup).

Out of scope:
- Keine echte App-Run-Smoke — kommt mit dem User-Test.
- iOS-pod-install läuft beim ersten 'flutter run ios' automatisch.
- Old ERPframe-Services bleiben aktiv und werfen ab jetzt 401 (kein
  Cookie-Session-Token mehr) — wird in Phase D entfernt.
This commit is contained in:
Dennis Nemec
2026-05-14 22:59:36 +02:00
parent 8cf4045e44
commit 6d7e58fc0f
15 changed files with 738 additions and 281 deletions

View File

@ -28,6 +28,12 @@ android {
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
// flutter_appauth liest diesen Placeholder und registriert
// dynamisch eine RedirectUriReceiverActivity, die den
// OIDC-Callback im Custom-Scheme `holzleitner://` abfängt.
// Muss mit der RedirectUri im Keycloak-Client matchen.
manifestPlaceholders["appAuthRedirectScheme"] = "holzleitner"
}
buildTypes {

View File

@ -17,7 +17,8 @@
<application
android:label="hl_lieferservice"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
android:icon="@mipmap/ic_launcher"
android:networkSecurityConfig="@xml/network_security_config">
<activity
android:name=".MainActivity"
android:exported="true"

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Erlaubt HTTP-Klartext-Zugriff auf die lokalen Dev-Hosts:
- 10.0.2.2: Android-Emulator-Loopback zum Mac-Host
- localhost / 127.0.0.1: Geräte-internes Loopback
- 192.168.x.x: spätere Tests gegen LAN-IP des Entwickler-Macs
In Produktion entfernen, sobald Backend nur noch über HTTPS
erreichbar ist.
-->
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="false">10.0.2.2</domain>
<domain includeSubdomains="false">localhost</domain>
<domain includeSubdomains="false">127.0.0.1</domain>
</domain-config>
</network-security-config>