src/Infrastructure/EventSubscriber/AuthByApiTokenSubscriber.php line 46

Open in your IDE?
  1. <?php
  2. namespace App\Infrastructure\EventSubscriber;
  3. use App\Database\Domain\Entity\User\UserAccessToken;
  4. use App\Database\Domain\Repository\AccessTokenRepository;
  5. use App\Infrastructure\Security\AuthManager;
  6. use Symfony\Component\DependencyInjection\ContainerInterface;
  7. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  8. use Symfony\Component\HttpFoundation\RedirectResponse;
  9. use Symfony\Component\HttpKernel\Event\RequestEvent;
  10. use Symfony\Component\HttpKernel\KernelEvents;
  11. use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
  12. class AuthByApiTokenSubscriber implements EventSubscriberInterface
  13. {
  14.     private ContainerInterface $container;
  15.     private AuthManager $authManager;
  16.     private AccessTokenRepository $accessTokenRepository;
  17.     public function __construct(
  18.         ContainerInterface $container,
  19.         AuthManager $authManager,
  20.         AccessTokenRepository $accessTokenRepository
  21.     ) {
  22.         $this->container             $container;
  23.         $this->authManager           $authManager;
  24.         $this->accessTokenRepository $accessTokenRepository;
  25.     }
  26.     public function onKernelRequest(RequestEvent $event): void
  27.     {
  28.         $request $event->getRequest();
  29.         // Handle referral code
  30.         if ($request->query->has('referral_code')) {
  31.             $code $request->query->get('referral_code');
  32.             $request->getSession()->set('referral_code'$code);
  33.         }
  34.         // Skip API routes
  35.         if (strpos($request->getPathInfo(), 'api') !== false) {
  36.             return;
  37.         }
  38.         $tokenStorage $this->container->get('security.token_storage');
  39.         $token $tokenStorage->getToken();
  40.         $router $this->container->get('router');
  41.         $logoutResponse = new RedirectResponse($router->generate('user_logout'));
  42.         // Check if we have authentication cookies
  43.         $hasAuthCookies $request->cookies->has('token') &&
  44.                          $request->cookies->has('token-expires-at');
  45.         // Case 1: User is authenticated but cookies are missing - logout
  46.         if ($token && $token->getUser() && !is_string($token->getUser()) && !$hasAuthCookies) {
  47.             $event->setResponse($logoutResponse);
  48.             return;
  49.         }
  50.         // Case 2: We have auth cookies - attempt to authenticate/validate
  51.         if ($hasAuthCookies) {
  52.             $cookieToken $request->cookies->get('token');
  53.             /** @var UserAccessToken|null $accessToken */
  54.             $accessToken $this->accessTokenRepository->findOneBy(['token' => $cookieToken]);
  55.             // Invalid token - logout only if user was previously authenticated
  56.             if ((!$accessToken || !$accessToken->isValid())) {
  57.                 if ($token && $token->getUser()) {
  58.                     $event->setResponse($logoutResponse);
  59.                 }
  60.                 return;
  61.             }
  62.             // Valid token - authenticate the user
  63.             if ($accessToken->isValid()) {
  64.                 // Only create new token if not already properly authenticated
  65.                 $currentUser $token $token->getUser() : null;
  66.                 $needsAuthentication = !$currentUser ||
  67.                                      is_string($currentUser) ||
  68.                                      $currentUser->getId() !== $accessToken->getUser()->getId();
  69.                 if ($needsAuthentication) {
  70.                     $user $accessToken->getUser();
  71.                     $newToken = new UsernamePasswordToken(
  72.                         $user,
  73.                         null,
  74.                         'main',
  75.                         $user->getRoles()
  76.                     );
  77.                     $tokenStorage->setToken($newToken);
  78.                     // Ensure the session is started and store the token
  79.                     $session $request->getSession();
  80.                     $session->set('_security_main'serialize($newToken));
  81.                     // Handle redirect after login
  82.                     $loginUrl $session->get('login_url');
  83.                     if ($loginUrl) {
  84.                         $session->remove('login_url');
  85.                         $event->setResponse(new RedirectResponse($loginUrl));
  86.                     }
  87.                 }
  88.             }
  89.         }
  90.     }
  91.     public static function getSubscribedEvents(): array
  92.     {
  93.         return [
  94.             KernelEvents::REQUEST => ['onKernelRequest'7]
  95.         ];
  96.     }
  97. }