Die Anmeldung galt fest 7 Tage - und die Frist lief ab dem *Anmelden*, nicht
ab der letzten Nutzung. Wer die App taeglich benutzte, flog trotzdem
punktgenau nach einer Woche hinaus.
Beides ist jetzt geregelt:
- Einstellungen -> Anmeldung: 7 Tage bis 1 Jahr oder unbegrenzt. Gilt fuer
Website und App gemeinsam, weil beide dasselbe Token bekommen - auch nach
Single Sign-on.
- POST /auth/refresh schiebt die Frist beim Start nach vorn. Damit zaehlt die
eingestellte Dauer ab dem letzten Besuch, und eine geaenderte Einstellung
greift ohne Neuanmeldung.
"Unbegrenzt" heisst ein Token ganz ohne exp. Das ist bewusst folgenreich: Es
gibt keine Sperrliste, eine erteilte Anmeldung laesst sich nicht einzeln
zurueckziehen. Die Oberflaeche sagt das dazu und nennt den einzigen Ausweg
(JWT_SECRET aendern).
/auth/refresh nimmt bewusst nur JWTs an, keine langlebigen API-Token: aus
einem jederzeit widerrufbaren Zugang (Home Assistant) waere sonst ein
unwiderruflicher geworden.
Der Rueckfallwert aus der Umgebung steigt von 7 auf 30 Tage - er gilt nur noch,
solange nichts eingestellt ist.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
In Authentik hat jede Anwendung standardmaessig ihren eigenen Issuer, abgeleitet
aus dem Application-Slug. Web- und App-Client brauchen dort aber zwei getrennte
Anwendungen, weil ein Provider entweder vertraulich ODER oeffentlich ist.
Bisher wurde das App-Token gegen den Issuer und den Schluesselsatz der
Web-Anwendung geprueft - die App-Anmeldung waere damit an der iss-Pruefung
gescheitert. Discovery und JWKS werden jetzt je Adresse gepuffert statt je
Anbieter, und OIDC_<KUERZEL>_NATIVE_DISCOVERY_URL benennt die Anwendung des
App-Clients. Ohne die Variable bleibt es bei einer gemeinsamen Adresse.
Ausserdem im README: der Signing Key muss gesetzt sein, sonst signiert Authentik
mit HS256 und das Token wird abgelehnt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Neben dem Passwort-Login gibt es jetzt einen zweiten, gleichberechtigten Weg:
OpenID Connect gegen einen selbst gehosteten Anmeldedienst. Ohne Konfiguration
aendert sich nichts - keine SSO-Knoepfe, Passwort-Login wie bisher.
Der Anmeldedienst ist NUR fuer die Anmeldung zustaendig. Danach stellt Vorrania
sein eigenes Token aus wie beim Passwort-Login, deshalb bleiben deps.py, die
Rollenpruefung und die langlebigen API-Tokens unveraendert.
Backend
- Anbieter kommen aus der Umgebung (OIDC_PROVIDERS + OIDC_<KUERZEL>_*). Ein
zweiter Anbieter ist damit reine Konfiguration, ohne Codeaenderung.
- Browser-Weg (vertraulicher Client) und App-Weg (oeffentlicher Client, PKCE)
enden beide im selben Token-Schema.
- state/nonce/PKCE-Verifier liegen in einer kurzlebigen Tabelle statt in einem
Cookie: Starlettes CORS-Schicht spiegelt bei allow_origins=["*"] zusammen mit
allow_credentials die Herkunft zurueck, sobald ein Request ein Cookie traegt.
Ohne Cookie entsteht diese Wechselwirkung erst gar nicht - und der Ablauf
bleibt mit der db-Fixture pruefbar.
- Zuordnung ueber die sub des Anbieters; die Erstverknuepfung laeuft ueber die
BESTAETIGTE E-Mail-Adresse. Rollen kommen nie aus dem Anbieter, und ein
gleichlautender preferred_username uebernimmt nie ein bestehendes Konto.
- users.password_hash darf jetzt leer sein (reine SSO-Konten). verify_password
faengt das ab, sonst antwortete der Login mit 500 statt 401.
Verknuepfen bestehender Konten
- Neue Seite "Mein Konto" (fuer alle Benutzer, nicht nur Admins): verknuepfen
und wieder loesen. Die Berechtigung stammt aus der laufenden Sitzung, es
braucht also weder eine hinterlegte Adresse noch Admin-Rechte.
- Der Start laeuft ueber POST, weil eine Seitennavigation das Bearer-Token
nicht mitschicken kann.
- Die letzte Anmeldemoeglichkeit eines Kontos laesst sich nicht loesen.
iOS
- AppAuth (erste Paketabhaengigkeit) mit PKCE im System-Browser, nie in einem
eingebetteten WebView, und ohne Client-Secret.
- offline_access nur im App-Weg: der Browser-Weg braucht kein Refresh-Token und
bekaeme sonst einen ueberfluessigen Zustimmungsdialog.
- Anmeldezustand je Serverprofil im Keychain; abgelaufene Token erneuert die App
still im Hintergrund. Gleichzeitige 401er teilen sich eine Erneuerung.
Deployment
- docker-compose reicht die ganze .env durch. Einzeln aufzuzaehlen ginge nur mit
fest verdrahteten Kuerzeln - genau das soll ein weiterer Anbieter nicht
erfordern.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Auf ausdruecklichen Wunsch jetzt auch die internen Bezeichner, weil die
Installation noch keine echten Daten enthaelt: POSTGRES_USER/PASSWORD/DB, der
Volume-Name, die Standard-DATABASE_URL, der localStorage-Schluessel und die
iOS-Zeichenketten inklusive Keychain-Konto.
Das setzt eine leere Datenbank voraus: Der neue Volume-Name legt eine neue,
leere Datenbank an. Die alte bleibt als verwaistes Volume liegen und muss von
Hand entfernt werden.
Die Warnung in docker-compose.yml bleibt stehen, damit eine spaetere
Umbenennung nicht versehentlich mit Daten im Volume passiert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Anzeigename, Paketname, Token-Key, DB-/Volume-Namen auf project_good
- README Clone-Abschnitt mit git.scarriffle.com/Scarriffle/project-good
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>