vendor/gesdinet/jwt-refresh-token-bundle/Security/Http/Authenticator/RefreshTokenAuthenticator.php line 41

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the GesdinetJWTRefreshTokenBundle package.
  4.  *
  5.  * (c) Gesdinet <http://www.gesdinet.com/>
  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 Gesdinet\JWTRefreshTokenBundle\Security\Http\Authenticator;
  11. use Gesdinet\JWTRefreshTokenBundle\Event\RefreshTokenNotFoundEvent;
  12. use Gesdinet\JWTRefreshTokenBundle\Http\RefreshAuthenticationFailureResponse;
  13. use Gesdinet\JWTRefreshTokenBundle\Model\RefreshTokenInterface;
  14. use Gesdinet\JWTRefreshTokenBundle\Model\RefreshTokenManagerInterface;
  15. use Gesdinet\JWTRefreshTokenBundle\Request\Extractor\ExtractorInterface;
  16. use Gesdinet\JWTRefreshTokenBundle\Security\Exception\InvalidTokenException;
  17. use Gesdinet\JWTRefreshTokenBundle\Security\Exception\MissingTokenException;
  18. use Gesdinet\JWTRefreshTokenBundle\Security\Exception\TokenNotFoundException;
  19. use Gesdinet\JWTRefreshTokenBundle\Security\Http\Authenticator\Token\PostRefreshTokenAuthenticationToken;
  20. use Symfony\Component\HttpFoundation\Request;
  21. use Symfony\Component\HttpFoundation\Response;
  22. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  23. use Symfony\Component\Security\Core\Exception\AuthenticationException;
  24. use Symfony\Component\Security\Core\Exception\LogicException;
  25. use Symfony\Component\Security\Core\User\UserProviderInterface;
  26. use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
  27. use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
  28. use Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
  29. use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
  30. use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
  31. use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
  32. use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
  33. use Symfony\Component\Security\Http\Authenticator\Passport\UserPassportInterface;
  34. use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
  35. use Symfony\Component\Security\Http\HttpUtils;
  36. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  37. class RefreshTokenAuthenticator extends AbstractAuthenticator implements AuthenticationEntryPointInterface
  38. {
  39.     private RefreshTokenManagerInterface $refreshTokenManager;
  40.     private EventDispatcherInterface $eventDispatcher;
  41.     private ExtractorInterface $extractor;
  42.     private UserProviderInterface $userProvider;
  43.     private AuthenticationSuccessHandlerInterface $successHandler;
  44.     private AuthenticationFailureHandlerInterface $failureHandler;
  45.     private array $options;
  46.     private ?HttpUtils $httpUtils;
  47.     public function __construct(
  48.         RefreshTokenManagerInterface $refreshTokenManager,
  49.         EventDispatcherInterface $eventDispatcher,
  50.         ExtractorInterface $extractor,
  51.         UserProviderInterface $userProvider,
  52.         AuthenticationSuccessHandlerInterface $successHandler,
  53.         AuthenticationFailureHandlerInterface $failureHandler,
  54.         array $options,
  55.         ?HttpUtils $httpUtils null
  56.     ) {
  57.         $this->refreshTokenManager $refreshTokenManager;
  58.         $this->eventDispatcher $eventDispatcher;
  59.         $this->extractor $extractor;
  60.         $this->userProvider $userProvider;
  61.         $this->successHandler $successHandler;
  62.         $this->failureHandler $failureHandler;
  63.         $this->options array_merge([
  64.             'check_path' => null// @todo in 2.0, change the default to `/login_check`
  65.             'ttl' => 2592000,
  66.             'ttl_update' => false,
  67.             'token_parameter_name' => 'refresh_token',
  68.         ], $options);
  69.         $this->httpUtils $httpUtils;
  70.         if (null === $httpUtils) {
  71.             trigger_deprecation('gesdinet/jwt-refresh-token-bundle''1.1''Not passing an instance of "%s" to the "%s" constructor is deprecated, it will be required in 2.0.'HttpUtils::class, self::class);
  72.         }
  73.     }
  74.     public function supports(Request $request): bool
  75.     {
  76.         if (null !== $this->httpUtils && null !== $this->options['check_path']) {
  77.             return $this->httpUtils->checkRequestPath($request$this->options['check_path']);
  78.         }
  79.         trigger_deprecation('gesdinet/jwt-refresh-token-bundle''1.1''Checking if the refresh token is in the request in %s() is deprecated, as of 2.0 only the request path will be checked.'__METHOD__);
  80.         return null !== $this->extractor->getRefreshToken($request$this->options['token_parameter_name']);
  81.     }
  82.     public function authenticate(Request $request): Passport
  83.     {
  84.         $token $this->extractor->getRefreshToken($request$this->options['token_parameter_name']);
  85.         if (null === $token) {
  86.             throw new MissingTokenException();
  87.         }
  88.         $refreshToken $this->refreshTokenManager->get($token);
  89.         if (null === $refreshToken) {
  90.             throw new TokenNotFoundException();
  91.         }
  92.         if (!$refreshToken->isValid()) {
  93.             throw new InvalidTokenException(sprintf('Refresh token "%s" is invalid.'$refreshToken->getRefreshToken()));
  94.         }
  95.         if ($this->options['ttl_update']) {
  96.             $expirationDate = new \DateTime();
  97.             $expirationDate->modify(sprintf('+%d seconds'$this->options['ttl']));
  98.             $refreshToken->setValid($expirationDate);
  99.             $this->refreshTokenManager->save($refreshToken);
  100.         }
  101.         $method method_exists($this->userProvider'loadUserByIdentifier') ? 'loadUserByIdentifier' 'loadUserByUsername';
  102.         $passport = new SelfValidatingPassport(new UserBadge($refreshToken->getUsername(), [$this->userProvider$method]));
  103.         $passport->setAttribute('refreshToken'$refreshToken);
  104.         return $passport;
  105.     }
  106.     /**
  107.      * @deprecated to be removed in 2.0, use `createToken()` instead
  108.      */
  109.     public function createAuthenticatedToken(PassportInterface $passportstring $firewallName): TokenInterface
  110.     {
  111.         if (!$passport instanceof UserPassportInterface) {
  112.             throw new LogicException(sprintf('Passport does not contain a user, overwrite "createToken()" in "%s" to create a custom authentication token.', static::class));
  113.         }
  114.         trigger_deprecation('gesdinet/jwt-refresh-token-bundle''1.0''"%s()" is deprecated, use "%s::createToken()" instead.'__METHOD____CLASS__);
  115.         return $this->createToken($passport$firewallName);
  116.     }
  117.     public function createToken(Passport $passportstring $firewallName): TokenInterface
  118.     {
  119.         /** @var RefreshTokenInterface|null $refreshToken */
  120.         $refreshToken $passport->getAttribute('refreshToken');
  121.         if (null === $refreshToken) {
  122.             throw new LogicException('Passport does not contain the refresh token.');
  123.         }
  124.         return new PostRefreshTokenAuthenticationToken(
  125.             $passport->getUser(),
  126.             $firewallName,
  127.             $passport->getUser()->getRoles(),
  128.             $refreshToken
  129.         );
  130.     }
  131.     public function onAuthenticationSuccess(Request $requestTokenInterface $tokenstring $firewallName): ?Response
  132.     {
  133.         return $this->successHandler->onAuthenticationSuccess($request$token);
  134.     }
  135.     public function onAuthenticationFailure(Request $requestAuthenticationException $exception): ?Response
  136.     {
  137.         return $this->failureHandler->onAuthenticationFailure($request$exception);
  138.     }
  139.     public function start(Request $requestAuthenticationException $authException null): ?Response
  140.     {
  141.         $event = new RefreshTokenNotFoundEvent(
  142.             new MissingTokenException('JWT Refresh Token not found'0$authException),
  143.             new RefreshAuthenticationFailureResponse($authException $authException->getMessageKey() : 'Authentication error')
  144.         );
  145.         $this->eventDispatcher->dispatch($event'gesdinet.refresh_token_not_found');
  146.         return $event->getResponse();
  147.     }
  148. }