<?php
namespace App\Event;
use App\Entity\Shop;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Lexik\Bundle\JWTAuthenticationBundle\Event\JWTCreatedEvent;
use Lexik\Bundle\JWTAuthenticationBundle\Event\JWTDecodedEvent;
/**
* @see https://gist.github.com/benjaminrau/865f94d142605eb72a23a34ccdd0617a
*/
class JWTDecodedEventListener
{
/**
* @var EntityManagerInterface
*/
private $entityManager;
/**
* @param EntityManagerInterface $entityManager
*/
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
/**
* @param JWTDecodedEvent $event
*
* @throws \Exception
*
* @return void
*/
public function onLexikJwtAuthenticationOnJwtDecoded(JWTDecodedEvent $event)
{
$payload = $event->getPayload();
/**
* As a mechanism to invalidate issued tokes we force token issue date to be higher than a date stored on User::tokenValidAfter
* By updating the User::tokenValidAfter to current date all previously issued tokens become invalid
*
* Its intended we dont mark as invalid if user isnt found on persistence level because we rely on core JWT
* implementation to handle this case. We want to handle only the validation of tokenValidAfter here.
*
* @var $user User
*/
$user = $this->entityManager->getRepository(User::class)->findOneBy([
'tel' => $payload['username'],
]);
if ($user) {
if (
$user->getTokenValidAfter() instanceof \DateTime &&
$payload['iat'] < $user->getTokenValidAfter()->getTimestamp()
) {
$event->markAsInvalid();
}
} else {
$shop = $this->entityManager->getRepository(Shop::class)->findOneBy([
'email' => $payload['username'],
]);
if ($shop) {
if (
$shop->getTokenValidAfter() instanceof \DateTime &&
$payload['iat'] < $shop->getTokenValidAfter()->getTimestamp()
) {
$event->markAsInvalid();
}
}
}
}
}