src/EventSubscriber/TwoFactorSetupSubscriber.php line 39

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\EventSubscriber;
  4. use App\Entity\User;
  5. use Psr\Log\LoggerInterface;
  6. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  7. use Symfony\Component\HttpFoundation\RedirectResponse;
  8. use Symfony\Component\HttpKernel\Event\RequestEvent;
  9. use Symfony\Component\HttpKernel\KernelEvents;
  10. use Symfony\Component\Routing\RouterInterface;
  11. use Symfony\Component\Security\Core\Security;
  12. class TwoFactorSetupSubscriber implements EventSubscriberInterface
  13. {
  14. protected $logger;
  15. protected $security;
  16. protected $router;
  17. public function __construct(
  18. LoggerInterface $logger,
  19. Security $security,
  20. RouterInterface $router
  21. ) {
  22. $this->logger = $logger;
  23. $this->security = $security;
  24. $this->router = $router;
  25. }
  26. public static function getSubscribedEvents(): array
  27. {
  28. return [
  29. KernelEvents::REQUEST => [['onKernelRequest', 4]],
  30. ];
  31. }
  32. public function onKernelRequest(RequestEvent $event): void
  33. {
  34. $request = $event->getRequest();
  35. $path = $request->getPathInfo();
  36. // Only intercept /app routes — not login, 2fa, logout, setup itself, or API
  37. $allowedPaths = ['/2fa', '/2fa/check', '/2fa/resend', '/logout', '/app/2fa/setup', '/app/security/enable-2fa', '/security_questions', '/reset', '/forgot', '/resetting'];
  38. foreach ($allowedPaths as $allowed) {
  39. if (str_starts_with($path, $allowed)) {
  40. return;
  41. }
  42. }
  43. if (!str_starts_with($path, '/app')) {
  44. return;
  45. }
  46. $user = $this->security->getUser();
  47. if (!$user instanceof User) {
  48. return;
  49. }
  50. // Skip admins
  51. if (in_array(User::ROLE_ADMIN, $user->getRoles()) || in_array(User::ROLE_SUPER_ADMIN, $user->getRoles())) {
  52. return;
  53. }
  54. if (!$user->getEmailAuthEnabled()) {
  55. $this->logger->debug('***** TwoFactorSetupSubscriber: user has no 2FA, redirecting to setup');
  56. $event->setResponse(new RedirectResponse($this->router->generate('app_2fa_setup')));
  57. }
  58. }
  59. }