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:
@ -1,9 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:hl_lieferservice/bloc/app_bloc.dart';
|
||||
import 'package:hl_lieferservice/data/network/keycloak_oidc_token_provider.dart';
|
||||
import 'package:hl_lieferservice/feature/authentication/bloc/auth_bloc.dart';
|
||||
import 'package:hl_lieferservice/feature/authentication/bloc/auth_event.dart';
|
||||
import 'package:hl_lieferservice/feature/authentication/presentation/login_enforcer.dart';
|
||||
import 'package:hl_lieferservice/feature/authentication/service/userinfo.dart';
|
||||
import 'package:hl_lieferservice/main.dart' show locator;
|
||||
import 'package:hl_lieferservice/feature/car_selection/bloc/bloc.dart';
|
||||
import 'package:hl_lieferservice/feature/car_selection/presentation/car_selection_enforcer.dart';
|
||||
import 'package:hl_lieferservice/feature/car_selection/repository/car_selection_repository.dart';
|
||||
@ -36,7 +38,6 @@ class _DeliveryAppState extends State<DeliveryApp> {
|
||||
return BlocBuilder<AppBloc, AppState>(
|
||||
builder: (context, state) {
|
||||
if (state is AppConfigLoaded) {
|
||||
final currentAppState = state;
|
||||
return MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider(create: (context) => NavigationBloc()),
|
||||
@ -44,11 +45,14 @@ class _DeliveryAppState extends State<DeliveryApp> {
|
||||
BlocProvider(
|
||||
create:
|
||||
(context) => AuthBloc(
|
||||
service: UserInfoService(
|
||||
url: currentAppState.config.backendUrl,
|
||||
),
|
||||
operationBloc: context.read<OperationBloc>(),
|
||||
),
|
||||
tokenProvider:
|
||||
locator<KeycloakOidcTokenProvider>(),
|
||||
operationBloc: context.read<OperationBloc>(),
|
||||
)
|
||||
// Beim ersten Build: prüfen, ob ein
|
||||
// Refresh-Token aus der Secure Storage da ist,
|
||||
// und ggf. direkt einloggen.
|
||||
..add(const RestoreSessionRequested()),
|
||||
),
|
||||
BlocProvider(
|
||||
create:
|
||||
|
||||
Reference in New Issue
Block a user