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

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.     /**
  22.      * @var string
  23.      */
  24.     private $firewallName;
  25.     /**
  26.      * @var TokenStorageInterface
  27.      */
  28.     private $tokenStorage;
  29.     /**
  30.      * @var AuthenticationRequiredHandlerInterface
  31.      */
  32.     private $authenticationRequiredHandler;
  33.     /**
  34.      * @var EventDispatcherInterface
  35.      */
  36.     private $eventDispatcher;
  37.     public function __construct(
  38.         string $firewallName,
  39.         TokenStorageInterface $tokenStorage,
  40.         AuthenticationRequiredHandlerInterface $authenticationRequiredHandler,
  41.         EventDispatcherInterface $eventDispatcher
  42.     ) {
  43.         $this->firewallName $firewallName;
  44.         $this->tokenStorage $tokenStorage;
  45.         $this->authenticationRequiredHandler $authenticationRequiredHandler;
  46.         $this->eventDispatcher $eventDispatcher;
  47.     }
  48.     public function onKernelException(ExceptionEvent $event): void
  49.     {
  50.         $exception $event->getThrowable();
  51.         do {
  52.             if ($exception instanceof AccessDeniedException) {
  53.                 $this->handleAccessDeniedException($event);
  54.                 return;
  55.             }
  56.         } while (null !== $exception $exception->getPrevious());
  57.     }
  58.     private function handleAccessDeniedException(ExceptionEvent $exceptionEvent): void
  59.     {
  60.         $token $this->tokenStorage->getToken();
  61.         if (!($token instanceof TwoFactorTokenInterface && $token->getProviderKey(true) === $this->firewallName)) {
  62.             return;
  63.         }
  64.         /** @var TwoFactorTokenInterface $token */
  65.         $request $exceptionEvent->getRequest();
  66.         $event = new TwoFactorAuthenticationEvent($request$token);
  67.         $this->eventDispatcher->dispatch($eventTwoFactorAuthenticationEvents::REQUIRE);
  68.         $response $this->authenticationRequiredHandler->onAuthenticationRequired($request$token);
  69.         $exceptionEvent->setResponse($response);
  70.     }
  71.     public static function getSubscribedEvents(): array
  72.     {
  73.         return [
  74.             KernelEvents::EXCEPTION => ['onKernelException'self::LISTENER_PRIORITY],
  75.         ];
  76.     }
  77. }