vendor/symfony/security-http/RememberMe/AbstractRememberMeHandler.php line 31

  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.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 Symfony\Component\Security\Http\RememberMe;
  11. use Psr\Log\LoggerInterface;
  12. use Symfony\Component\HttpFoundation\Cookie;
  13. use Symfony\Component\HttpFoundation\RequestStack;
  14. use Symfony\Component\Security\Core\Exception\AuthenticationException;
  15. use Symfony\Component\Security\Core\User\UserInterface;
  16. use Symfony\Component\Security\Core\User\UserProviderInterface;
  17. /**
  18.  * @author Wouter de Jong <wouter@wouterj.nl>
  19.  */
  20. abstract class AbstractRememberMeHandler implements RememberMeHandlerInterface
  21. {
  22.     private UserProviderInterface $userProvider;
  23.     protected $requestStack;
  24.     protected $options;
  25.     protected $logger;
  26.     public function __construct(UserProviderInterface $userProviderRequestStack $requestStack, array $options = [], LoggerInterface $logger null)
  27.     {
  28.         $this->userProvider $userProvider;
  29.         $this->requestStack $requestStack;
  30.         $this->options $options + [
  31.             'name' => 'REMEMBERME',
  32.             'lifetime' => 31536000,
  33.             'path' => '/',
  34.             'domain' => null,
  35.             'secure' => false,
  36.             'httponly' => true,
  37.             'samesite' => null,
  38.             'always_remember_me' => false,
  39.             'remember_me_parameter' => '_remember_me',
  40.         ];
  41.         $this->logger $logger;
  42.     }
  43.     /**
  44.      * Checks if the RememberMeDetails is a valid cookie to login the given User.
  45.      *
  46.      * This method should also:
  47.      * - Create a new remember-me cookie to be sent with the response (using {@see createCookie()});
  48.      * - If you store the token somewhere else (e.g. in a database), invalidate the stored token.
  49.      *
  50.      * @throws AuthenticationException If the remember-me details are not accepted
  51.      */
  52.     abstract protected function processRememberMe(RememberMeDetails $rememberMeDetailsUserInterface $user): void;
  53.     public function consumeRememberMeCookie(RememberMeDetails $rememberMeDetails): UserInterface
  54.     {
  55.         try {
  56.             $user $this->userProvider->loadUserByIdentifier($rememberMeDetails->getUserIdentifier());
  57.         } catch (AuthenticationException $e) {
  58.             throw $e;
  59.         }
  60.         if (!$user instanceof UserInterface) {
  61.             throw new \LogicException(sprintf('The UserProviderInterface implementation must return an instance of UserInterface, but returned "%s".'get_debug_type($user)));
  62.         }
  63.         $this->processRememberMe($rememberMeDetails$user);
  64.         $this->logger?->info('Remember-me cookie accepted.');
  65.         return $user;
  66.     }
  67.     public function clearRememberMeCookie(): void
  68.     {
  69.         $this->logger?->debug('Clearing remember-me cookie.', ['name' => $this->options['name']]);
  70.         $this->createCookie(null);
  71.     }
  72.     /**
  73.      * Creates the remember-me cookie using the correct configuration.
  74.      *
  75.      * @param RememberMeDetails|null $rememberMeDetails The details for the cookie, or null to clear the remember-me cookie
  76.      */
  77.     protected function createCookie(?RememberMeDetails $rememberMeDetails)
  78.     {
  79.         $request $this->requestStack->getMainRequest();
  80.         if (!$request) {
  81.             throw new \LogicException('Cannot create the remember-me cookie; no master request available.');
  82.         }
  83.         // the ResponseListener configures the cookie saved in this attribute on the final response object
  84.         $request->attributes->set(ResponseListener::COOKIE_ATTR_NAME, new Cookie(
  85.             $this->options['name'],
  86.             $rememberMeDetails?->toString(),
  87.             $rememberMeDetails?->getExpires() ?? 1,
  88.             $this->options['path'],
  89.             $this->options['domain'],
  90.             $this->options['secure'] ?? $request->isSecure(),
  91.             $this->options['httponly'],
  92.             false,
  93.             $this->options['samesite']
  94.         ));
  95.     }
  96. }