src/EventSubscriber/LogoutSubscriber.php line 50

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the nellapp-core package.
  4.  *
  5.  * (c) Benjamin Georgeault
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace App\EventSubscriber;
  11. use App\Entity\Account\SsoAppSession;
  12. use App\Entity\Account\User;
  13. use App\Repository\Account\SsoAppSessionRepository;
  14. use Nellapp\Bundle\SDKBundle\Routing\UrlGeneratorInterface;
  15. use Psr\Log\LoggerInterface;
  16. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  17. use Symfony\Component\HttpFoundation\RedirectResponse;
  18. use Symfony\Component\HttpFoundation\Request;
  19. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  20. use Symfony\Component\Security\Http\Event\LogoutEvent;
  21. use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
  22. use Symfony\Contracts\HttpClient\HttpClientInterface;
  23. /**
  24.  * Class LogoutSubscriber
  25.  *
  26.  * @author Benjamin Georgeault
  27.  */
  28. class LogoutSubscriber implements EventSubscriberInterface
  29. {
  30.     public function __construct(
  31.         private SsoAppSessionRepository $ssoAppSessionRepository,
  32.         private HttpClientInterface     $httpClient,
  33.         private UrlGeneratorInterface   $internalUrlGenerator,
  34.         private LoggerInterface         $logger,
  35.     )
  36.     {
  37.     }
  38.     public static function getSubscribedEvents(): array
  39.     {
  40.         return [
  41.             LogoutEvent::class => 'logout',
  42.         ];
  43.     }
  44.     public function logout(LogoutEvent $event): void
  45.     {
  46.         if (null === $user $this->getUser($event->getToken())) {
  47.             return;
  48.         }
  49.         $request $event->getRequest();
  50.         $this->triggerGlobalLogout($user$request);
  51.         if (!$request->query->has('target')) {
  52.             return;
  53.         }
  54.         if (!filter_var($target $request->query->get('target'), FILTER_VALIDATE_URL)) {
  55.             return;
  56.         }
  57.         $event->setResponse(new RedirectResponse($target));
  58.     }
  59.     private function getUser(TokenInterface $token): ?User
  60.     {
  61.         if (($user $token->getUser()) instanceof User) {
  62.             return $user;
  63.         }
  64.         return null;
  65.     }
  66.     private function triggerGlobalLogout(User $userRequest $request): void
  67.     {
  68.         $deviceId $request->cookies->get('DEVICE_ID');
  69.         if (!$deviceId) {
  70.             return;
  71.         }
  72.         $sessions $this->ssoAppSessionRepository->findActiveByUserAndDevice($user$deviceId);
  73.         /** Should only have one active session by app and device */
  74.         /** @var SsoAppSession $session */
  75.         foreach ($sessions as $session) {
  76.             $app $session->getApp();
  77.             $payload = [
  78.                 'sessionIds' => [$session->getSessionId()],
  79.             ];
  80.             try {
  81.                 if ($this->internalUrlGenerator->exist($app->getQueueName(), 'api_account_global_logout')) {
  82.                     $this->httpClient->request(
  83.                         'POST',
  84.                         $this->internalUrlGenerator->generate($app->getQueueName(), 'api_account_global_logout'),
  85.                         [
  86.                             'json' => $payload,
  87.                             'headers' => [
  88.                                 'Authorization' => 'Core ' $app->getSecret(),
  89.                             ]
  90.                         ]
  91.                     );
  92.                 }
  93.             } catch (TransportExceptionInterface $e) {
  94.                 $this->logger->error($e);
  95.             }
  96.             $this->ssoAppSessionRepository->revokeSession($session);
  97.         }
  98.     }
  99. }