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

@ -5,5 +5,25 @@
abstract interface class AuthTokenProvider {
/// Liefert einen aktuell gültigen Access-Token oder `null`, wenn
/// keine Session aktiv ist. Darf bei Bedarf einen Refresh anstoßen.
///
/// Wirft [AuthTemporarilyUnavailableException], wenn zwar eine Session
/// existiert, der Token aber wegen eines **vorübergehenden** Problems
/// (Netz/VPN/Timeout) gerade nicht erneuert werden konnte.
Future<String?> currentAccessToken();
}
/// Der Access-Token konnte gerade nicht erneuert werden, obwohl die Session
/// (Refresh-Token) weiterhin gültig sein dürfte — typisch: Mobilfunk-/VPN-
/// Aussetzer, Timeout, Login-Server kurz nicht erreichbar.
///
/// Bewusst **kein** „Session abgelaufen": der Aufrufer soll den Request als
/// Verbindungsfehler behandeln und später erneut versuchen, statt den Fahrer
/// auszuloggen.
class AuthTemporarilyUnavailableException implements Exception {
const AuthTemporarilyUnavailableException(this.cause);
final Object cause;
@override
String toString() => 'AuthTemporarilyUnavailableException($cause)';
}