Zwei-Faktor-Anmeldung per TOTP
app/totp.php implementiert RFC 6238 selbst statt per Bibliothek: der Algorithmus ist ein HMAC plus eine Truncation, und ein zweiter Faktor ist die letzte Stelle fuer ungepruefte Abhaengigkeiten. Der QR-Code entsteht aus dem ohnehin vorhandenen TCPDF, damit kein externer Dienst das Geheimnis sieht. Beim Login wird die Anmeldung bei aktivem zweitem Faktor nicht abgeschlossen; der Zwischenzustand gewaehrt keinerlei Zugriff und ist byte-identisch zu einem unangemeldeten Aufruf. users.totp_last_step verhindert die Wiederverwendung eines abgefangenen Codes innerhalb seines Gueltigkeitsfensters. Abschalten verlangt Passwort und Code. APP_REQUIRE_2FA_FOR_ADMINS macht den Faktor fuer Platform-Admins verbindlich, per Weiterleitung auf die Einrichtung statt als harte Sperre - sonst koennte der Schalter den einzigen Admin aussperren. Standard aus. check-konto-und-mandantenwechsel erwartete beim Login noch das entfernte Kundenkuerzel-Feld und damit einen direkten Sprung aufs Dashboard; der Check bildet jetzt den tatsaechlichen Weg ueber die Mandantenauswahl ab. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -266,6 +266,49 @@ Stripe-Flow zur Aktualisierung der Zahlungsart. Im Stripe-Dashboard dürfen der
|
||||
zusätzlich freigeschaltet werden; Bestellungen und Kündigungen sollen nur über
|
||||
die dokumentierten Abläufe der Kaffeeliste erfolgen.
|
||||
|
||||
## Zwei-Faktor-Anmeldung
|
||||
|
||||
Jedes Konto kann unter `zwei-faktor-einrichten.php` (verlinkt aus
|
||||
`konto.php`) einen zweiten Faktor per TOTP einrichten — dieselben
|
||||
sechsstelligen Codes, die Aegis, 2FAS, Google Authenticator oder ein
|
||||
Passwortmanager erzeugen.
|
||||
|
||||
`app/totp.php` implementiert RFC 6238 selbst, statt eine Bibliothek zu
|
||||
ziehen: der Algorithmus ist ein HMAC plus eine Truncation, und ein zweiter
|
||||
Faktor ist die letzte Stelle, an der man ungeprüfte Abhängigkeiten haben
|
||||
will. Der QR-Code entsteht aus dem ohnehin vorhandenen TCPDF — kein
|
||||
externer Dienst bekommt das Geheimnis zu sehen.
|
||||
|
||||
Ablauf beim Login: stimmt das Passwort und ist ein zweiter Faktor scharf,
|
||||
wird die Anmeldung **nicht** abgeschlossen. Es entsteht nur ein
|
||||
Zwischenzustand (`totp_pending_user_id`, 15 Minuten gültig), der für sich
|
||||
genommen keinerlei Zugriff gewährt; erst der Code stellt die Sitzung her.
|
||||
Wer mehrere Mandanten hat, kommt auch erst danach zur Mandantenauswahl.
|
||||
|
||||
Weitere Festlegungen:
|
||||
|
||||
- **Wiederherstellungscodes**: zehn Stück, nur direkt nach der Einrichtung
|
||||
im Klartext sichtbar, gespeichert als Hash, jeder genau einmal gültig.
|
||||
Auf der Code-Seite genügt es, statt des App-Codes einen davon einzugeben —
|
||||
Buchstaben im Feld unterscheiden die beiden Fälle.
|
||||
- **Wiederverwendung ausgeschlossen**: `users.totp_last_step` merkt sich den
|
||||
zuletzt eingelösten Zeitschritt. Ohne das ließe sich ein abgefangener Code
|
||||
innerhalb seines Gültigkeitsfensters ein zweites Mal verwenden.
|
||||
- **Toleranz** von einem Zeitschritt (±30 s) für Uhrenabweichungen.
|
||||
- **Rate-Limit** auf der Code-Eingabe: 5 Versuche pro Konto und 20 pro IP je
|
||||
15 Minuten — sechs Ziffern sind sonst schnell durchprobiert.
|
||||
- **Abschalten** verlangt Passwort *und* gültigen Code.
|
||||
|
||||
`APP_REQUIRE_2FA_FOR_ADMINS=1` macht den zweiten Faktor für Platform-Admins
|
||||
verbindlich: das Back-Office leitet dann auf die Einrichtung um, statt hart
|
||||
zu sperren — sonst könnte der Schalter den einzigen Platform-Admin dauerhaft
|
||||
aussperren. **Erst umlegen, nachdem die eigene Einrichtung getestet ist.**
|
||||
|
||||
Abgedeckt von `scripts/check-totp-flow.php` (Algorithmus inklusive der
|
||||
RFC-6238-Testvektoren, Persistenz, Wiederherstellungscodes) und
|
||||
`scripts/check-2fa-http-flow.php` (Anmeldeweg; braucht einen laufenden
|
||||
Webserver).
|
||||
|
||||
## Schutz der offenen Registrierung
|
||||
|
||||
Ab Juli 2026 liefen auf `testumgebung.kaffeeliste.de` täglich 10–20
|
||||
|
||||
Reference in New Issue
Block a user