<?php
namespace App\EventSubscriber;
use Doctrine\ORM\EntityManagerInterface;
use Scheb\TwoFactorBundle\Security\TwoFactor\Provider\Totp\TotpAuthenticatorInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent;
use Symfony\Component\Security\Http\Event\AuthenticationTokenCreatedEvent;
use Symfony\Component\Security\Http\Event\CheckPassportEvent;
use Symfony\Component\Security\Http\Event\LoginSuccessEvent;
class TotpTokenCreator implements EventSubscriberInterface
{
/**
* @var TotpAuthenticatorInterface
*/
private $totpAuthenticator;
/**
* @var EntityManagerInterface
*/
private $entityManager;
/**
* @var TokenStorageInterface
*/
private $tokenStorage;
/**
* @var RouterInterface
*/
private $router;
private $exclude_routes = [
'app_2fa_showcode',
'app_2fa_png'
];
/**
* @var SessionInterface
*/
private $session;
public function __construct(TotpAuthenticatorInterface $totpAuthenticator, EntityManagerInterface $entityManager, TokenStorageInterface $tokenStorage, RouterInterface $router, SessionInterface $session)
{
$this->totpAuthenticator = $totpAuthenticator;
$this->entityManager = $entityManager;
$this->tokenStorage = $tokenStorage;
$this->router = $router;
$this->session = $session;
}
public function onLoginSuccess(LoginSuccessEvent $event)
{
$passport = $event->getPassport();
$user = $passport->getUser();
if (!$user->isTotpAuthenticationEnabled()) {
$user->setTotpSecret($this->totpAuthenticator->generateSecret());
$this->entityManager->flush();
$this->session->set('newTotp', true);
}
}
public function onKernelRequest(RequestEvent $event)
{
$token = $this->tokenStorage->getToken();
if (!$token) {
return ;
}
$user = $token->getUser();
if (!$user) {
return ;
}
$session_flag = $this->session->has('newTotp');
if ($session_flag === true && null !== $event->getRequest()->attributes->get('_route') && !in_array($event->getRequest()->attributes->get('_route'), $this->exclude_routes)) {
$event->setResponse(new RedirectResponse(
$this->router->generate('app_2fa_showcode')
));
}
}
public static function getSubscribedEvents()
{
return [
LoginSuccessEvent::class => 'onLoginSuccess',
RequestEvent::class => 'onKernelRequest'
];
}
}