<?php
declare(strict_types=1);
namespace App\EventListener;
use App\Entity\Security\RefreshToken;
use App\Processor\Orm\RemoveEntityProcessor;
use App\Service\Slack\SlackService;
use App\Service\Slack\SlackServiceInterface;
use Doctrine\ORM\EntityManagerInterface;
use Gesdinet\JWTRefreshTokenBundle\Event\RefreshAuthenticationFailureEvent;
use Gesdinet\JWTRefreshTokenBundle\Security\Exception\TokenNotFoundException;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
class RefreshTokenListener implements EventSubscriberInterface
{
private ?Request $request;
public function __construct(
private EntityManagerInterface $entityManager,
private RequestStack $requestStack,
private LoggerInterface $channelLoginLogger,
private SlackService $slackService,
private RemoveEntityProcessor $removeEntityProcessor,
) {
$this->request = $this->requestStack->getCurrentRequest();
}
public static function getSubscribedEvents()
{
return [
'gesdinet.refresh_token_failure' => 'onRefreshTokenFailure',
];
}
public function onRefreshTokenFailure(RefreshAuthenticationFailureEvent $event): void
{
if (true !== $event->getException() instanceof TokenNotFoundException) {
return;
}
$data = json_decode($this->request->getContent() ?? '', true);
$refreshToken = $data['refresh_token'] ?? null;
if (null === $refreshToken) {
return;
}
$this->channelLoginLogger->info('Login using refresh token failed : ', [
'user-agent' => $this->request->headers->get('user-agent'),
'source' => $this->request->headers->get('source'),
'ip' => $this->request->getClientIp(),
'refreshToken' => $refreshToken,
]);
$this->removeEntityProcessor->disableSoftDeleteFilter();
$repository = $this->entityManager->getRepository(RefreshToken::class);
$refreshTokenObject = $repository->findOneByRefreshToken($refreshToken);
if (null === $refreshTokenObject) {
return;
}
$userName = $refreshTokenObject->getUsername();
$this->channelLoginLogger->info('Deleting all refresh tokens related to user : ', ['userName' => $userName]);
$this->entityManager->createQuery('DELETE FROM App\Entity\Security\RefreshToken rt WHERE rt.username = :username')
->setParameter('username', $userName)
->execute()
;
$this->slackService->sendMessage(SlackServiceInterface::BUG_REPORTS_CHANNEL, "Token refresh failed for user {$userName} : with token : {$refreshToken}");
$this->removeEntityProcessor->enableSoftDeleteFilter();
}
}