src/EventListener/JWTListener.php line 82

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\EventListener;
  4. use App\Entity\MobileJwtToken;
  5. use App\Entity\User\ShopUser;
  6. use App\Repository\MobileJwtTokenRepository;
  7. use Doctrine\ORM\EntityManagerInterface;
  8. use Lexik\Bundle\JWTAuthenticationBundle\Encoder\JWTEncoderInterface;
  9. use Lexik\Bundle\JWTAuthenticationBundle\Event\AuthenticationSuccessEvent;
  10. use Lexik\Bundle\JWTAuthenticationBundle\Event\JWTAuthenticatedEvent;
  11. use Safe\DateTime;
  12. use Symfony\Component\HttpFoundation\JsonResponse;
  13. use Symfony\Component\HttpFoundation\RequestStack;
  14. use Symfony\Component\Security\Core\Exception\AuthenticationException;
  15. use function in_array;
  16. use function is_array;
  17. use function substr;
  18. class JWTListener
  19. {
  20.     public function __construct(private RequestStack $requestStack, private EntityManagerInterface $entityManagerInterface, private JWTEncoderInterface $jWTEncoderInterface, private MobileJwtTokenRepository $mobileJwtTokenRepository)
  21.     {
  22.     }
  23.     public function onJWTAuthenticated(JWTAuthenticatedEvent $event): void
  24.     {
  25.         //this is triggered when a protected route is accessed with a valid JWT token in the header,
  26.         //we need to check if this token exists in our mobile_jwt_token table first. Only if it exists, we consider this token valid
  27.         $payload $event->getPayload();
  28.         if (isset($payload)) {
  29.             if (isset($payload['roles'])) {
  30.                 if (in_array('ROLE_ADMINISTRATION_ACCESS'$payload['roles'])) {
  31.                       return;
  32.                 }
  33.             }
  34.         }
  35.         $currentRequest $this->requestStack->getCurrentRequest();
  36.         if ($currentRequest === null) {
  37.             $event->stopPropagation();
  38.             throw new AuthenticationException('token invalid (failed to access request header)');
  39.         }
  40.         $authorizationInHeader $currentRequest->headers->get('authorization');
  41.         if ($authorizationInHeader === null) {
  42.             $event->stopPropagation();
  43.             throw new AuthenticationException('token invalid (failed to access request header)');
  44.         }
  45.         $tokenString substr($authorizationInHeader7);
  46.         /** @var ShopUser|null $shopUser */
  47.         $shopUser $this->entityManagerInterface->getRepository(ShopUser::class)->findOneBy(['username' => $payload['username']]);
  48.         if ($shopUser === null) {
  49.             $event->stopPropagation();
  50.             throw new AuthenticationException('token invalid (shopUser was not found)');
  51.         }
  52.          $mobileJwtToken $this->mobileJwtTokenRepository->findOneBy(['token' => $tokenString'shopUser' => $shopUser->getId()]);
  53.         if ($mobileJwtToken === null) {
  54.             $event->stopPropagation();
  55.             throw new AuthenticationException('token invalid (token not found in db)');
  56.         }
  57.         return;
  58.     }
  59.     public function onAuthenticationSuccess(AuthenticationSuccessEvent $event): void
  60.     {
  61.         //When a user logs in successfully from the API, a JWT is created and saved in the mobile_JWT_token table
  62.         $payload $event->getData();
  63.         $userData $event->getUser();
  64.         if ($userData !== null) {
  65.             $userRoles $userData->getRoles();
  66.             if ($userRoles !== null && is_array($userRoles)) {
  67.                 if (in_array('ROLE_ADMINISTRATION_ACCESS'$userRoles)) {
  68.                     return;
  69.                 }
  70.             }
  71.         }
  72.         $token $payload['token'];
  73.         /** @var ShopUser $shopUser */
  74.         $shopUser $event->getUser();
  75.         $error false;
  76.         if ($token === null || empty($token)) {
  77.             $error true;
  78.         }
  79.         $decodedToken $this->jWTEncoderInterface->decode($token);
  80.         if (! isset($decodedToken['exp'])) {
  81.             $error true;
  82.         } else {
  83.             if (empty($decodedToken['exp'])) {
  84.                 $error true;
  85.             }
  86.         }
  87.         if ($error) {
  88.             $event->stopPropagation();
  89.             $response $event->getResponse();
  90.             if ($response instanceof JsonResponse) {
  91.                 $responseData = ['code' => 401'message' => 'token invalid / failed to parse token'];
  92.                 $response->setData($responseData);
  93.                 $response->setStatusCode(401);
  94.             }
  95.             return;
  96.         }
  97.         $tokenExpiresOn DateTime::createFromFormat('U'$decodedToken['exp']);
  98.         $currentDateTime = new DateTime();
  99.         $mobileJwtToken = new MobileJwtToken($currentDateTime);
  100.         $mobileJwtToken->setToken($token);
  101.         $mobileJwtToken->setExpiresOn($tokenExpiresOn);
  102.         $mobileJwtToken->setShopUser($shopUser);
  103.         $this->entityManagerInterface->persist($mobileJwtToken);
  104.         $this->entityManagerInterface->flush();
  105.     }
  106. }