Phase B Fixes: AppAuth-Stored-State + LAN-Cleartext + force prompt=login

Drei zusammenhängende Korrekturen, die den OIDC-Flow auf realen Geräten
durchgehen lassen:

1. taskAffinity="" raus aus MainActivity — sonst landet die
   RedirectUriReceiverActivity beim Rücksprung aus Samsung Internet
   Custom Tabs (FLAG_ACTIVITY_NEW_TASK) in einem zweiten Task und
   zweitem App-Prozess, AppAuth findet seinen in-memory PKCE-State
   nicht und meldet 'No stored state - unable to handle response'.

2. network_security_config.xml: base-config cleartextTrafficPermitted
   statt einzelner localhost/10.0.2.2-Domains. Notwendig für Tests
   gegen die LAN-IP des Dev-Macs (z.B. 192.168.x.x); AndroidConfig kann
   keine IP-Wildcards. Klar als Dev-only markiert.

3. promptValues=['login'] auf der AuthorizationTokenRequest — verhindert
   den Instant-SSO-Cookie-Redirect-Race, bei dem Chrome Custom Tabs
   schliesst, bevor der Redirect-Intent ankommt; AppAuth wuerde sonst
   'User cancelled flow' melden, obwohl der Nutzer nicht abgebrochen
   hat. UX-mässig auch gewollt: jeder Login frisch (Account-Wechsel
   am gleichen Geraet ist denkbar), Restore laeuft über den Refresh-
   Token aus der Secure Storage.
This commit is contained in:
Dennis Nemec
2026-05-15 11:16:18 +02:00
parent 08824290ff
commit cb22fff407
3 changed files with 40 additions and 21 deletions

View File

@ -84,6 +84,14 @@ class KeycloakOidcTokenProvider implements AuthTokenProvider {
// würde sonst abbrechen. In Produktion (HTTPS) ist das ein
// No-Op und kann bleiben.
allowInsecureConnections: true,
// Wichtig auf Android: ohne `prompt=login` würde Keycloak bei
// bestehender SSO-Session sofort 302 nach holzleitner://...
// antworten, Chrome schließt den Custom Tab dabei so schnell,
// dass der Redirect-Intent unsere RedirectUriReceiverActivity
// gar nicht erreicht — AppAuth meldet stattdessen
// "User cancelled flow". Erzwingen der Login-Maske → echter
// User-Click → sauberer Intent-Dispatch.
promptValues: const ['login'],
),
);