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:
2026-08-23 23:51:45 +02:00
co-authored by Claude Opus 5
parent 86334c2752
commit a2dcc4df65
14 changed files with 1335 additions and 5 deletions
+10
View File
@@ -5,6 +5,7 @@ declare(strict_types=1);
require_once __DIR__ . '/bootstrap.php';
require_once __DIR__ . '/saas-auth.php';
require_once __DIR__ . '/audit.php';
require_once __DIR__ . '/totp.php';
/**
* Platform-admin access is deliberately a separate concept from
@@ -44,6 +45,15 @@ function app_require_platform_admin(PDO $pdo): array
exit('Kein Zugriff.');
}
// Das Back-Office sieht alle Mandanten - fuer diese Konten laesst sich ein
// zweiter Faktor erzwingen. Bewusst als Weiterleitung auf die Einrichtung
// statt als harte Sperre: sonst koennte der Schalter den einzigen
// Platform-Admin dauerhaft aussperren.
if (app_totp_required_for_platform_admins() && !app_totp_is_active($pdo, (int)$user['user_id'])) {
header('Location: zwei-faktor-einrichten.php');
exit;
}
return $user;
}