vendor/symfony/security-http/LoginLink/LoginLinkHandler.php line 47

  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\LoginLink;
  11. use Symfony\Component\HttpFoundation\Request;
  12. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  13. use Symfony\Component\Routing\RequestContext;
  14. use Symfony\Component\Security\Core\Exception\UserNotFoundException;
  15. use Symfony\Component\Security\Core\Signature\Exception\ExpiredSignatureException;
  16. use Symfony\Component\Security\Core\Signature\Exception\InvalidSignatureException;
  17. use Symfony\Component\Security\Core\Signature\SignatureHasher;
  18. use Symfony\Component\Security\Core\User\UserInterface;
  19. use Symfony\Component\Security\Core\User\UserProviderInterface;
  20. use Symfony\Component\Security\Http\LoginLink\Exception\ExpiredLoginLinkException;
  21. use Symfony\Component\Security\Http\LoginLink\Exception\InvalidLoginLinkException;
  22. /**
  23.  * @author Ryan Weaver <ryan@symfonycasts.com>
  24.  */
  25. final class LoginLinkHandler implements LoginLinkHandlerInterface
  26. {
  27.     private UrlGeneratorInterface $urlGenerator;
  28.     private UserProviderInterface $userProvider;
  29.     private array $options;
  30.     private SignatureHasher $signatureHasher;
  31.     public function __construct(UrlGeneratorInterface $urlGeneratorUserProviderInterface $userProviderSignatureHasher $signatureHasher, array $options)
  32.     {
  33.         $this->urlGenerator $urlGenerator;
  34.         $this->userProvider $userProvider;
  35.         $this->signatureHasher $signatureHasher;
  36.         $this->options array_merge([
  37.             'route_name' => null,
  38.             'lifetime' => 600,
  39.         ], $options);
  40.     }
  41.     public function createLoginLink(UserInterface $userRequest $request nullint $lifetime null): LoginLinkDetails
  42.     {
  43.         $expires time() + ($lifetime ?: $this->options['lifetime']);
  44.         $expiresAt = new \DateTimeImmutable('@'.$expires);
  45.         $parameters = [
  46.             'user' => $user->getUserIdentifier(),
  47.             'expires' => $expires,
  48.             'hash' => $this->signatureHasher->computeSignatureHash($user$expires),
  49.         ];
  50.         if ($request) {
  51.             $currentRequestContext $this->urlGenerator->getContext();
  52.             $this->urlGenerator->setContext(
  53.                 (new RequestContext())
  54.                     ->fromRequest($request)
  55.                     ->setParameter('_locale'$request->getLocale())
  56.             );
  57.         }
  58.         try {
  59.             $url $this->urlGenerator->generate(
  60.                 $this->options['route_name'],
  61.                 $parameters,
  62.                 UrlGeneratorInterface::ABSOLUTE_URL
  63.             );
  64.         } finally {
  65.             if ($request) {
  66.                 $this->urlGenerator->setContext($currentRequestContext);
  67.             }
  68.         }
  69.         return new LoginLinkDetails($url$expiresAt);
  70.     }
  71.     public function consumeLoginLink(Request $request): UserInterface
  72.     {
  73.         $userIdentifier $request->get('user');
  74.         if (!$hash $request->get('hash')) {
  75.             throw new InvalidLoginLinkException('Missing "hash" parameter.');
  76.         }
  77.         if (!$expires $request->get('expires')) {
  78.             throw new InvalidLoginLinkException('Missing "expires" parameter.');
  79.         }
  80.         try {
  81.             $this->signatureHasher->acceptSignatureHash($userIdentifier$expires$hash);
  82.             $user $this->userProvider->loadUserByIdentifier($userIdentifier);
  83.             $this->signatureHasher->verifySignatureHash($user$expires$hash);
  84.         } catch (UserNotFoundException $e) {
  85.             throw new InvalidLoginLinkException('User not found.'0$e);
  86.         } catch (ExpiredSignatureException $e) {
  87.             throw new ExpiredLoginLinkException(ucfirst(str_ireplace('signature''login link'$e->getMessage())), 0$e);
  88.         } catch (InvalidSignatureException $e) {
  89.             throw new InvalidLoginLinkException(ucfirst(str_ireplace('signature''login link'$e->getMessage())), 0$e);
  90.         }
  91.         return $user;
  92.     }
  93. }