vendor/symfony/security-http/EventListener/CheckCredentialsListener.php line 50

  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\EventListener;
  11. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  12. use Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface;
  13. use Symfony\Component\Security\Core\Exception\BadCredentialsException;
  14. use Symfony\Component\Security\Core\User\LegacyPasswordAuthenticatedUserInterface;
  15. use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
  16. use Symfony\Component\Security\Http\Authenticator\Passport\Badge\PasswordUpgradeBadge;
  17. use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\CustomCredentials;
  18. use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
  19. use Symfony\Component\Security\Http\Event\CheckPassportEvent;
  20. /**
  21.  * This listeners uses the interfaces of authenticators to
  22.  * determine how to check credentials.
  23.  *
  24.  * @author Wouter de Jong <wouter@driveamber.com>
  25.  *
  26.  * @final
  27.  */
  28. class CheckCredentialsListener implements EventSubscriberInterface
  29. {
  30.     private PasswordHasherFactoryInterface $hasherFactory;
  31.     public function __construct(PasswordHasherFactoryInterface $hasherFactory)
  32.     {
  33.         $this->hasherFactory $hasherFactory;
  34.     }
  35.     public function checkPassport(CheckPassportEvent $event): void
  36.     {
  37.         $passport $event->getPassport();
  38.         if ($passport->hasBadge(PasswordCredentials::class)) {
  39.             // Use the password hasher to validate the credentials
  40.             $user $passport->getUser();
  41.             if (!$user instanceof PasswordAuthenticatedUserInterface) {
  42.                 throw new \LogicException(sprintf('Class "%s" must implement "%s" for using password-based authentication.'get_debug_type($user), PasswordAuthenticatedUserInterface::class));
  43.             }
  44.             /** @var PasswordCredentials $badge */
  45.             $badge $passport->getBadge(PasswordCredentials::class);
  46.             if ($badge->isResolved()) {
  47.                 return;
  48.             }
  49.             $presentedPassword $badge->getPassword();
  50.             if ('' === $presentedPassword) {
  51.                 throw new BadCredentialsException('The presented password cannot be empty.');
  52.             }
  53.             if (null === $user->getPassword()) {
  54.                 throw new BadCredentialsException('The presented password is invalid.');
  55.             }
  56.             if (!$this->hasherFactory->getPasswordHasher($user)->verify($user->getPassword(), $presentedPassword$user instanceof LegacyPasswordAuthenticatedUserInterface $user->getSalt() : null)) {
  57.                 throw new BadCredentialsException('The presented password is invalid.');
  58.             }
  59.             $badge->markResolved();
  60.             if (!$passport->hasBadge(PasswordUpgradeBadge::class)) {
  61.                 $passport->addBadge(new PasswordUpgradeBadge($presentedPassword));
  62.             }
  63.             return;
  64.         }
  65.         if ($passport->hasBadge(CustomCredentials::class)) {
  66.             /** @var CustomCredentials $badge */
  67.             $badge $passport->getBadge(CustomCredentials::class);
  68.             if ($badge->isResolved()) {
  69.                 return;
  70.             }
  71.             $badge->executeCustomChecker($passport->getUser());
  72.             return;
  73.         }
  74.     }
  75.     public static function getSubscribedEvents(): array
  76.     {
  77.         return [CheckPassportEvent::class => 'checkPassport'];
  78.     }
  79. }