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:
@@ -169,13 +169,21 @@ try {
|
||||
// ---------------------------------------------------------------
|
||||
$cookies = [];
|
||||
$csrf = konto_csrf("{$baseUrl}/login.php", $cookies);
|
||||
// Das Login-Formular kennt kein Kundenkuerzel mehr: wer bei mehreren
|
||||
// Mandanten Mitglied ist, waehlt nach dem Passwort per Klarnamen aus.
|
||||
$login = konto_request("{$baseUrl}/login.php", $cookies, 'POST', http_build_query([
|
||||
'csrf_token' => $csrf,
|
||||
'email' => "kontocheck-{$suffix}@test.local",
|
||||
'password' => $altesPasswort,
|
||||
'tenant_slug' => "kontocheck-a-{$suffix}",
|
||||
]));
|
||||
pruefe('Login leitet auf index.php statt konto.php', $login['location'] === 'index.php');
|
||||
pruefe('Login mit mehreren Mandanten fuehrt zur Mandantenauswahl', $login['location'] === 'mandant-auswahl.php');
|
||||
|
||||
$csrf = konto_csrf("{$baseUrl}/mandant-auswahl.php", $cookies);
|
||||
$ersteWahl = konto_request("{$baseUrl}/mandant-auswahl.php", $cookies, 'POST', http_build_query([
|
||||
'csrf_token' => $csrf,
|
||||
'tenant_id' => (string)$tenantAId,
|
||||
]));
|
||||
pruefe('Mandantenwahl nach dem Login leitet auf index.php statt konto.php', $ersteWahl['location'] === 'index.php');
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// 3. Verifikation wird fuer Einladungen erzwungen
|
||||
@@ -281,7 +289,6 @@ try {
|
||||
'csrf_token' => $csrf,
|
||||
'email' => "kontocheck-{$suffix}@test.local",
|
||||
'password' => $altesPasswort,
|
||||
'tenant_slug' => "kontocheck-a-{$suffix}",
|
||||
]));
|
||||
pruefe('Login mit altem Passwort schlaegt fehl', $altLogin['location'] === null);
|
||||
|
||||
@@ -291,9 +298,8 @@ try {
|
||||
'csrf_token' => $csrf,
|
||||
'email' => "kontocheck-{$suffix}@test.local",
|
||||
'password' => $neuesPasswort,
|
||||
'tenant_slug' => "kontocheck-a-{$suffix}",
|
||||
]));
|
||||
pruefe('Login mit neuem Passwort funktioniert', $neuLogin['location'] === 'index.php');
|
||||
pruefe('Login mit neuem Passwort funktioniert', $neuLogin['location'] === 'mandant-auswahl.php');
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Reset-Link bestaetigt die Adresse mit
|
||||
|
||||
Reference in New Issue
Block a user