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:
@ -3,34 +3,34 @@ import 'package:holzleitner_api/holzleitner_api.dart';
|
||||
|
||||
import 'auth_token_provider.dart';
|
||||
import 'backend_config.dart';
|
||||
import 'dev_password_grant_token_provider.dart';
|
||||
import 'holzleitner_api_factory.dart';
|
||||
import 'keycloak_oidc_token_provider.dart';
|
||||
|
||||
/// Registriert das HTTP-/API-Subsystem im globalen GetIt-Locator.
|
||||
///
|
||||
/// Aufruf bewusst nicht im AppBloc-Lifecycle, sondern in `main()` vor
|
||||
/// dem `runApp` — die API-Klassen sind über die gesamte App-Lebensdauer
|
||||
/// stabil und brauchen keine Reaktion auf App-Events.
|
||||
/// stabil.
|
||||
///
|
||||
/// Phase A nutzt die `DevPasswordGrantTokenProvider`-Implementation.
|
||||
/// Phase B wird hier den OIDC-PKCE-Provider einhängen und die
|
||||
/// Dev-Implementation komplett entfernen.
|
||||
/// Phase B: produktiver `KeycloakOidcTokenProvider`. Die alte
|
||||
/// `DevPasswordGrantTokenProvider`-Implementation bleibt im Code (für
|
||||
/// das reine dart-Smoke-Tool, siehe `tool/smoke_test_api.dart`).
|
||||
void registerNetworking({
|
||||
required GetIt locator,
|
||||
BackendConfig config = BackendConfig.localDev,
|
||||
String testfahrerUsername = 'testfahrer',
|
||||
String testfahrerPassword = 'test',
|
||||
}) {
|
||||
locator.registerSingleton<BackendConfig>(config);
|
||||
|
||||
locator.registerSingleton<AuthTokenProvider>(
|
||||
DevPasswordGrantTokenProvider(
|
||||
tokenEndpoint: config.keycloakTokenEndpoint,
|
||||
clientId: config.keycloakClientId,
|
||||
username: testfahrerUsername,
|
||||
password: testfahrerPassword,
|
||||
),
|
||||
final provider = KeycloakOidcTokenProvider(
|
||||
config: config,
|
||||
issuerUrl: config.keycloakIssuerUrl,
|
||||
redirectUrl: config.keycloakRedirectUrl,
|
||||
);
|
||||
// Doppelt registrieren: einmal unter der konkreten Klasse (für
|
||||
// den AuthBloc, der Login/Logout/Restore aufruft) und einmal hinter
|
||||
// dem Interface (für den HTTP-Interceptor).
|
||||
locator.registerSingleton<KeycloakOidcTokenProvider>(provider);
|
||||
locator.registerSingleton<AuthTokenProvider>(provider);
|
||||
|
||||
locator.registerSingleton<HolzleitnerApi>(
|
||||
buildHolzleitnerApi(
|
||||
|
||||
Reference in New Issue
Block a user