vendor/ezsystems/ezplatform-page-builder/src/lib/Security/EditorialMode/TokenManager.php line 24

Open in your IDE?
  1. <?php
  2. /**
  3.  * @copyright Copyright (C) eZ Systems AS. All rights reserved.
  4.  * @license For full copyright and license information view LICENSE file distributed with this source code.
  5.  */
  6. declare(strict_types=1);
  7. namespace EzSystems\EzPlatformPageBuilder\Security\EditorialMode;
  8. use Lexik\Bundle\JWTAuthenticationBundle\Encoder\JWTEncoderInterface;
  9. use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
  10. use Ramsey\Uuid\Uuid;
  11. use Symfony\Component\HttpFoundation\RequestStack;
  12. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  13. use Symfony\Component\Security\Core\User\UserInterface;
  14. /**
  15.  * JSON Web Token manager.
  16.  *
  17.  * In comparison to the default implementation delivered as part of JWTAuthenticationBundle it doesn't dispatch events
  18.  * and decorates token payload (overrides TTL, adds client ip).
  19.  */
  20. final class TokenManager implements JWTTokenManagerInterface
  21. {
  22.     /** @var \Lexik\Bundle\JWTAuthenticationBundle\Encoder\JWTEncoderInterface */
  23.     private $jwtEncoder;
  24.     /** @var \Symfony\Component\HttpFoundation\RequestStack */
  25.     private $requestStack;
  26.     /** @var string */
  27.     private $userIdentityField;
  28.     /** @var string */
  29.     private $userIdClaim;
  30.     /** @var int */
  31.     private $ttl;
  32.     /** @var bool */
  33.     private $verifyIp;
  34.     /**
  35.      * @param \Lexik\Bundle\JWTAuthenticationBundle\Encoder\JWTEncoderInterface $jwtEncoder
  36.      * @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
  37.      * @param string $userIdClaim
  38.      * @param int $ttl
  39.      * @param bool $verifyIp
  40.      */
  41.     public function __construct(
  42.         JWTEncoderInterface $jwtEncoder,
  43.         RequestStack $requestStack,
  44.         string $userIdClaim,
  45.         int $ttl,
  46.         bool $verifyIp true
  47.     ) {
  48.         $this->jwtEncoder $jwtEncoder;
  49.         $this->requestStack $requestStack;
  50.         $this->userIdentityField 'username';
  51.         $this->userIdClaim $userIdClaim;
  52.         $this->ttl $ttl;
  53.         $this->verifyIp $verifyIp;
  54.     }
  55.     /**
  56.      * {@inheritdoc}
  57.      */
  58.     public function create(UserInterface $user)
  59.     {
  60.         return $this->jwtEncoder->encode($this->createPayload($user));
  61.     }
  62.     /**
  63.      * {@inheritdoc}
  64.      */
  65.     public function decode(TokenInterface $token)
  66.     {
  67.         return $this->decodeFromString($token->getCredentials());
  68.     }
  69.     /**
  70.      * Decodes JWT from string.
  71.      *
  72.      * @param string $token
  73.      *
  74.      * @return array|bool
  75.      *
  76.      * @throws \Lexik\Bundle\JWTAuthenticationBundle\Exception\JWTDecodeFailureException
  77.      */
  78.     public function decodeFromString(string $token)
  79.     {
  80.         if (!($payload $this->jwtEncoder->decode($token))) {
  81.             return false;
  82.         }
  83.         if (!$this->isValidClientIp($payload['ip'] ?? null)) {
  84.             return false;
  85.         }
  86.         return $payload;
  87.     }
  88.     /**
  89.      * {@inheritdoc}
  90.      */
  91.     public function setUserIdentityField($field)
  92.     {
  93.         $this->userIdentityField $field;
  94.     }
  95.     /**
  96.      * {@inheritdoc}
  97.      */
  98.     public function getUserIdentityField()
  99.     {
  100.         return $this->userIdentityField;
  101.     }
  102.     /**
  103.      * {@inheritdoc}
  104.      */
  105.     public function getUserIdClaim()
  106.     {
  107.         return $this->userIdClaim;
  108.     }
  109.     /**
  110.      * Validates client ip if enabled.
  111.      *
  112.      * @param string|null $ip
  113.      *
  114.      * @return bool
  115.      */
  116.     private function isValidClientIp(?string $ip): bool
  117.     {
  118.         if ($this->verifyIp) {
  119.             $request $this->requestStack->getCurrentRequest();
  120.             if ($ip === null || $ip !== $request->getClientIp()) {
  121.                 return false;
  122.             }
  123.         }
  124.         return true;
  125.     }
  126.     /**
  127.      * Creates token payload.
  128.      *
  129.      * @param \Symfony\Component\Security\Core\User\UserInterface $user
  130.      *
  131.      * @return array
  132.      */
  133.     private function createPayload(UserInterface $user): array
  134.     {
  135.         $expiresAt time() + $this->ttl;
  136.         $clientIp $this->requestStack->getCurrentRequest()->getClientIp();
  137.         return [
  138.             'exp' => $expiresAt,
  139.             'jti' => (string)Uuid::uuid4(),
  140.             'ip' => $clientIp,
  141.             'mt' => microtime(),
  142.             $this->getUserIdClaim() => $user->getUsername(),
  143.         ];
  144.     }
  145. }