<?phpnamespace App\Infrastructure\EventSubscriber;use App\Database\Domain\Entity\User\UserAccessToken;use App\Database\Domain\Repository\AccessTokenRepository;use App\Infrastructure\Security\AuthManager;use Symfony\Component\DependencyInjection\ContainerInterface;use Symfony\Component\EventDispatcher\EventSubscriberInterface;use Symfony\Component\HttpFoundation\RedirectResponse;use Symfony\Component\HttpKernel\Event\RequestEvent;use Symfony\Component\HttpKernel\KernelEvents;use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;class AuthByApiTokenSubscriber implements EventSubscriberInterface{ private ContainerInterface $container; private AuthManager $authManager; private AccessTokenRepository $accessTokenRepository; public function __construct( ContainerInterface $container, AuthManager $authManager, AccessTokenRepository $accessTokenRepository ) { $this->container = $container; $this->authManager = $authManager; $this->accessTokenRepository = $accessTokenRepository; } public function onKernelRequest(RequestEvent $event): void { $request = $event->getRequest(); // Handle referral code if ($request->query->has('referral_code')) { $code = $request->query->get('referral_code'); $request->getSession()->set('referral_code', $code); } // Skip API routes if (strpos($request->getPathInfo(), 'api') !== false) { return; } $tokenStorage = $this->container->get('security.token_storage'); $token = $tokenStorage->getToken(); $router = $this->container->get('router'); $logoutResponse = new RedirectResponse($router->generate('user_logout')); // Check if we have authentication cookies $hasAuthCookies = $request->cookies->has('token') && $request->cookies->has('token-expires-at'); // Case 1: User is authenticated but cookies are missing - logout if ($token && $token->getUser() && !is_string($token->getUser()) && !$hasAuthCookies) { $event->setResponse($logoutResponse); return; } // Case 2: We have auth cookies - attempt to authenticate/validate if ($hasAuthCookies) { $cookieToken = $request->cookies->get('token'); /** @var UserAccessToken|null $accessToken */ $accessToken = $this->accessTokenRepository->findOneBy(['token' => $cookieToken]); // Invalid token - logout only if user was previously authenticated if ((!$accessToken || !$accessToken->isValid())) { if ($token && $token->getUser()) { $event->setResponse($logoutResponse); } return; } // Valid token - authenticate the user if ($accessToken->isValid()) { // Only create new token if not already properly authenticated $currentUser = $token ? $token->getUser() : null; $needsAuthentication = !$currentUser || is_string($currentUser) || $currentUser->getId() !== $accessToken->getUser()->getId(); if ($needsAuthentication) { $user = $accessToken->getUser(); $newToken = new UsernamePasswordToken( $user, null, 'main', $user->getRoles() ); $tokenStorage->setToken($newToken); // Ensure the session is started and store the token $session = $request->getSession(); $session->set('_security_main', serialize($newToken)); // Handle redirect after login $loginUrl = $session->get('login_url'); if ($loginUrl) { $session->remove('login_url'); $event->setResponse(new RedirectResponse($loginUrl)); } } } } } public static function getSubscribedEvents(): array { return [ KernelEvents::REQUEST => ['onKernelRequest', 7] ]; }}