65 lines
4.4 KiB
Markdown
65 lines
4.4 KiB
Markdown
# Authentication cache boundary hardening
|
|
|
|
The authentication cache is an optimization, never an additional authentication
|
|
method or permission source. The September 2026 review found and reproduced
|
|
three violations of that boundary in isolated SQLite tests.
|
|
|
|
| Finding | Consequence | Resolution |
|
|
| --- | --- | --- |
|
|
| Service-account credentials passed through ordinary principal-summary refresh | A narrowed service-account ceiling could be replaced by backing membership roles; the service-account identifier and authentication method were lost. | Dedicated service-account resolution retains its provenance and checks the current ceiling/lifecycle on every request. It does not enter the interactive principal-summary cache. |
|
|
| A warmed API-key summary accepted the same secret through a session cookie | The warm path accepted a cookie-authenticated mutation without the CSRF rule applied to real browser sessions; the cold path rejected the credential. | API keys require an explicit Bearer or X-API-Key header on both paths. Session cookies still require matching CSRF cookie/header/hash for mutations. |
|
|
| Tenant-key intersection excluded only the historical `system:` spelling | Module-native system permissions and retained module wildcards could survive the tenant-only intersection. | Resolve wildcard grants to concrete registered tenant permissions and exclude system permissions by catalogue and compatibility aliases. |
|
|
|
|
No existing secrets, sessions, assignments, or database schema are changed.
|
|
Normal header-authenticated API keys and concrete tenant aliases remain
|
|
compatible. Clients relying on API keys in browser cookies, implicit unknown
|
|
wildcards, or accidental instance-level rights must correct their authentication
|
|
method or permission configuration; these are not preserved as compatibility
|
|
exceptions. Stored grants are not rewritten. Service-account access continues
|
|
to narrow immediately when its ceiling is reduced or its lifecycle blocks use.
|
|
|
|
Regression coverage is in `tests/test_auth_cache_security.py` and
|
|
`tests/test_permission_catalog_contract.py`; the tests exercise the full
|
|
credential resolver with principal caching enabled, not only the lower-level
|
|
API-key lookup. They also verify that valid session CSRF and concrete legacy
|
|
tenant aliases still work.
|
|
|
|
## Remaining coordinated password-change workflow
|
|
|
|
`Account.password_reset_required` is currently advisory metadata, not an
|
|
enforced sign-in restriction. The administrator UI states this limitation,
|
|
but the authentication-fields documentation previously claimed mandatory
|
|
replacement; its English and German text now reflects the implementation.
|
|
A generated password is disclosed once but is not a single-use login secret.
|
|
|
|
A follow-up must deliver the password-change endpoint, current-password
|
|
verification and replacement policy, CSRF and attempt limits, session
|
|
revocation/rotation and cache invalidation, a restricted reset-required
|
|
principal, and the corresponding accessible UI/recovery path together.
|
|
Enabling only a rejection gate would lock affected accounts out without any
|
|
supported way to finish the change. This review does not enable such a gate or
|
|
change existing passwords.
|
|
|
|
## Betriebshinweise
|
|
|
|
API-Schlüssel werden ausschließlich über `Authorization: Bearer` oder
|
|
`X-API-Key` gesendet, nicht über das Sitzungscookie. Ändernde Cookie-Anfragen
|
|
benötigen weiterhin einen passenden CSRF-Header samt Cookie und serverseitigem
|
|
Prüfwert. Dienstkonten behalten ihre eigene Herkunft und werden bei jeder
|
|
Anfrage gegen den aktuellen Berechtigungsrahmen und Lebenszyklus geprüft.
|
|
Mitgliedschaftsrollen oder zwischengespeicherte interaktive Rechte dürfen diesen
|
|
Rahmen nicht ersetzen.
|
|
|
|
Mandantenschlüssel erhalten keine instanzweiten Rechte, auch nicht unter
|
|
modulbezogenen Berechtigungsnamen. Platzhalter werden in konkrete registrierte
|
|
Mandantenrechte aufgelöst. Bestehende konkrete Mandantenrechte und ihre
|
|
Kompatibilitätsnamen bleiben erhalten; gespeicherte Geheimnisse und
|
|
Rollenzuweisungen werden nicht geändert.
|
|
|
|
Das Kennzeichen `password_reset_required` erzwingt derzeit keinen
|
|
Passwortwechsel. Ein einmal angezeigtes Anfangspasswort bleibt zur Anmeldung
|
|
verwendbar. Die Nachfolgeumsetzung muss Passwortänderung, eng begrenzten
|
|
Zwischenzugriff, Sitzungswechsel beziehungsweise Widerruf und eine bedienbare
|
|
Wiederherstellung gemeinsam liefern; eine alleinige Zugriffssperre würde
|
|
betroffene Konten ohne durchführbaren Passwortwechsel aussperren.
|