fix(auth): Session ueberlebt Netz-Aussetzer; Zahlungsmethoden laden nach Re-Login neu

Kunde meldete haeufig 'Sitzung abgelaufen' und danach dauerhaft rotes
'Sitzung abgelaufen' bei den Zahlungsmethoden trotz erfolgreichem Login.

Token-Refresh:
- _performRefresh wertete JEDEN Fehler als tote Session (Logout + Refresh-
  Token geloescht) - auch Mobilfunk-/VPN-Aussetzer. Jetzt gilt nur noch eine
  echte Ablehnung durch Keycloak (OAuth invalid_grant o. ae.) als abgelaufen;
  voruebergehende Fehler behalten die Session, nutzen den noch gueltigen
  Access-Token weiter oder werfen AuthTemporarilyUnavailableException
- Interceptor schickt Requests nicht mehr tokenlos weiter (ergab 401 ->
  irrefuehrendes 'Sitzung abgelaufen'), sondern bricht als Verbindungsfehler ab
- restoreSession verwirft den Refresh-Token bei fehlendem Netz nicht mehr

Zahlungsmethoden:
- Cubit lud nur einmal beim App-Start (vor dem Login -> 401) und blieb danach
  fuer immer im Fehlerzustand. Jetzt Reload bei jedem Wechsel auf Authenticated
- Fehlerkarte in der Uebersicht hat einen 'Erneut laden'-Button

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Dennis Nemec
2026-09-17 11:59:56 +03:00
parent a027c93c62
commit 7cf17466b3
5 changed files with 129 additions and 13 deletions

View File

@ -4,6 +4,7 @@ import 'package:hl_lieferservice/bloc/app_bloc.dart';
import 'package:hl_lieferservice/data/cache/attachment_cache.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_state.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/main.dart' show locator;
@ -142,8 +143,18 @@ class _DeliveryAppState extends State<DeliveryApp> {
}
if (state is AppConfigLoaded) {
return LoginEnforcer(
child: CarSelectionEnforcer(child: Home()),
// Stammdaten nach JEDEM erfolgreichen (Re-)Login neu laden.
// Der Cubit lädt zwar beim App-Start — aber ohne Session
// endet das in 401 („Sitzung abgelaufen") und blieb bisher
// für immer im Fehlerzustand hängen, auch nach dem Login.
return BlocListener<AuthBloc, AuthState>(
listenWhen: (prev, curr) =>
curr is Authenticated && prev is! Authenticated,
listener: (context, _) =>
context.read<PaymentMethodsCubit>().load(),
child: LoginEnforcer(
child: CarSelectionEnforcer(child: Home()),
),
);
}