<?php
declare(strict_types=1);
namespace App\EventSubscriber;
use App\Entity\User;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class SessionTwoFactorMethodSubscriber implements EventSubscriberInterface
{
public const SESSION_KEY = '_2fa_method';
public function __construct(
private readonly TokenStorageInterface $tokenStorage,
private readonly RequestStack $requestStack,
private readonly LoggerInterface $logger,
) {}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::REQUEST => ['onKernelRequest', 1024], // Very high priority — before Scheb listeners
];
}
public function onKernelRequest(RequestEvent $event): void
{
if (!$event->isMainRequest()) {
return;
}
$token = $this->tokenStorage->getToken();
if (!$token) {
return;
}
$user = $token->getUser();
if (!$user instanceof User) {
return;
}
$request = $this->requestStack->getCurrentRequest();
if (!$request || !$request->hasSession()) {
return;
}
$sessionMethod = $request->getSession()->get(self::SESSION_KEY);
if ($sessionMethod !== null) {
$user->setSessionTwoFactorMethod($sessionMethod);
$this->logger->debug('[2FA Session] Hydrated session 2FA method onto User entity', [
'user_id' => $user->getId(),
'session_method' => $sessionMethod,
]);
}
}
}