verify-otp.php 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. <?php
  2. declare(strict_types=1);
  3. use App\App\Bootstrap;
  4. use App\Security\Csrf;
  5. use App\Security\FormAccess;
  6. use App\Security\RateLimiter;
  7. require dirname(__DIR__) . '/src/autoload.php';
  8. Bootstrap::init();
  9. if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
  10. Bootstrap::jsonResponse(['ok' => false, 'message' => 'Method not allowed'], 405);
  11. }
  12. $csrf = $_POST['csrf'] ?? '';
  13. if (!Csrf::validate(is_string($csrf) ? $csrf : null)) {
  14. Bootstrap::jsonResponse(['ok' => false, 'message' => 'Ungueltiges CSRF-Token.'], 419);
  15. }
  16. if (trim((string) ($_POST['website'] ?? '')) !== '') {
  17. Bootstrap::jsonResponse(['ok' => false, 'message' => 'Anfrage blockiert.'], 400);
  18. }
  19. $email = strtolower(trim((string) ($_POST['email'] ?? '')));
  20. if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
  21. Bootstrap::jsonResponse(['ok' => false, 'message' => 'Bitte gueltige E-Mail eingeben.'], 422);
  22. }
  23. $code = trim((string) ($_POST['otp_code'] ?? ''));
  24. $app = Bootstrap::config('app');
  25. $limiter = new RateLimiter();
  26. $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
  27. $rateKey = sprintf('otp-verify:%s:%s', $ip, $email);
  28. if (!$limiter->allow($rateKey, (int) $app['rate_limit']['requests'], (int) $app['rate_limit']['window_seconds'])) {
  29. Bootstrap::jsonResponse(['ok' => false, 'message' => 'Zu viele Anfragen. Bitte spaeter erneut versuchen.'], 429);
  30. }
  31. $formAccess = new FormAccess();
  32. $result = $formAccess->verifyOtp($email, $code);
  33. if (($result['ok'] ?? false) !== true) {
  34. $reason = (string) ($result['reason'] ?? '');
  35. Bootstrap::jsonResponse([
  36. 'ok' => false,
  37. 'message' => (string) ($result['message'] ?? 'Code konnte nicht bestaetigt werden.'),
  38. 'auth_required' => in_array($reason, ['auth_required', 'expired', 'attempt_limit'], true),
  39. 'auth_expired' => false,
  40. 'attempts_left' => isset($result['attempts_left']) ? (int) $result['attempts_left'] : null,
  41. ], (int) ($result['status_code'] ?? 422));
  42. }
  43. Bootstrap::jsonResponse([
  44. 'ok' => true,
  45. 'message' => 'E-Mail erfolgreich bestaetigt.',
  46. ]);