<?php
namespace App\EventSubscriber;
use App\Entity\UserInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Security;
class MFACheckSubscriber implements EventSubscriberInterface
{
/** @var Security */
private $security;
/** @var RequestStack */
private $requestStack;
/**
* @param Security $security
* @param RequestStack $requestStack
*/
public function __construct(Security $security, RequestStack $requestStack)
{
$this->security = $security;
$this->requestStack = $requestStack;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [
KernelEvents::REQUEST => 'onKernelRequest',
];
}
/**
* @param RequestEvent $event
*/
public function onKernelRequest(RequestEvent $event)
{
/** @var UserInterface|null $user */
if (!$user = $this->security->getUser()) {
return;
}
$request = $event->getRequest();
$currentPath = $request->getPathInfo();
$excludedPatterns = [
'/api/me',
'/api/mfa',
'/api/users', // Admin access only
];
foreach ($excludedPatterns as $pattern) {
if (0 === strpos($currentPath, $pattern)) {
return;
}
}
$cookies = $request->cookies;
$mfaVerified = 'true' === $cookies->get('streamer:isMFAVerified', 'false');
if ($user->isMFAEnabled() && !$mfaVerified) {
// MFA is required but not verified, return a 403 Forbidden response
$response = new JsonResponse(['message' => 'MFA verification required.'], JsonResponse::HTTP_FORBIDDEN);
$event->setResponse($response);
$event->stopPropagation();
}
}
}