vendor/scheb/2fa-bundle/Security/Http/Firewall/ExceptionListener.php line 34

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Scheb\TwoFactorBundle\Security\Http\Firewall;
  4. use Scheb\TwoFactorBundle\Security\Authentication\Token\TwoFactorTokenInterface;
  5. use Scheb\TwoFactorBundle\Security\Http\Authentication\AuthenticationRequiredHandlerInterface;
  6. use Scheb\TwoFactorBundle\Security\TwoFactor\Event\TwoFactorAuthenticationEvent;
  7. use Scheb\TwoFactorBundle\Security\TwoFactor\Event\TwoFactorAuthenticationEvents;
  8. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  9. use Symfony\Component\HttpKernel\Event\ExceptionEvent;
  10. use Symfony\Component\HttpKernel\KernelEvents;
  11. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  12. use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  13. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  14. /**
  15.  * @final
  16.  */
  17. class ExceptionListener implements EventSubscriberInterface
  18. {
  19.     // Just before the firewall's Symfony\Component\Security\Http\Firewall\ExceptionListener
  20.     private const LISTENER_PRIORITY 2;
  21.     public function __construct(
  22.         private string $firewallName,
  23.         private TokenStorageInterface $tokenStorage,
  24.         private AuthenticationRequiredHandlerInterface $authenticationRequiredHandler,
  25.         private EventDispatcherInterface $eventDispatcher,
  26.     ) {
  27.     }
  28.     public function onKernelException(ExceptionEvent $event): void
  29.     {
  30.         $exception $event->getThrowable();
  31.         do {
  32.             if ($exception instanceof AccessDeniedException) {
  33.                 $this->handleAccessDeniedException($event);
  34.                 return;
  35.             }
  36.             $exception $exception->getPrevious();
  37.         } while (null !== $exception);
  38.     }
  39.     private function handleAccessDeniedException(ExceptionEvent $exceptionEvent): void
  40.     {
  41.         $token $this->tokenStorage->getToken();
  42.         if (!($token instanceof TwoFactorTokenInterface)) {
  43.             return;
  44.         }
  45.         if ($token->getFirewallName() !== $this->firewallName) {
  46.             return;
  47.         }
  48.         $request $exceptionEvent->getRequest();
  49.         $event = new TwoFactorAuthenticationEvent($request$token);
  50.         $this->eventDispatcher->dispatch($eventTwoFactorAuthenticationEvents::REQUIRE);
  51.         $response $this->authenticationRequiredHandler->onAuthenticationRequired($request$token);
  52.         $exceptionEvent->allowCustomResponseCode();
  53.         $exceptionEvent->setResponse($response);
  54.     }
  55.     /**
  56.      * {@inheritdoc}
  57.      */
  58.     public static function getSubscribedEvents(): array
  59.     {
  60.         return [
  61.             KernelEvents::EXCEPTION => ['onKernelException'self::LISTENER_PRIORITY],
  62.         ];
  63.     }
  64. }