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

Open in your IDE?
  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\Encoder\EncoderFactoryInterface;
  14. use Symfony\Component\Security\Core\Exception\BadCredentialsException;
  15. use Symfony\Component\Security\Core\User\LegacyPasswordAuthenticatedUserInterface;
  16. use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
  17. use Symfony\Component\Security\Http\Authenticator\Passport\Badge\PasswordUpgradeBadge;
  18. use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\CustomCredentials;
  19. use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
  20. use Symfony\Component\Security\Http\Authenticator\Passport\UserPassportInterface;
  21. use Symfony\Component\Security\Http\Event\CheckPassportEvent;
  22. /**
  23.  * This listeners uses the interfaces of authenticators to
  24.  * determine how to check credentials.
  25.  *
  26.  * @author Wouter de Jong <wouter@driveamber.com>
  27.  *
  28.  * @final
  29.  */
  30. class CheckCredentialsListener implements EventSubscriberInterface
  31. {
  32.     private $hasherFactory;
  33.     /**
  34.      * @param PasswordHasherFactoryInterface $hasherFactory
  35.      */
  36.     public function __construct($hasherFactory)
  37.     {
  38.         if ($hasherFactory instanceof EncoderFactoryInterface) {
  39.             trigger_deprecation('symfony/security-core''5.3''Passing a "%s" instance to the "%s" constructor is deprecated, use "%s" instead.'EncoderFactoryInterface::class, __CLASS__PasswordHasherFactoryInterface::class);
  40.         }
  41.         $this->hasherFactory $hasherFactory;
  42.     }
  43.     public function checkPassport(CheckPassportEvent $event): void
  44.     {
  45.         $passport $event->getPassport();
  46.         if ($passport instanceof UserPassportInterface && $passport->hasBadge(PasswordCredentials::class)) {
  47.             // Use the password hasher to validate the credentials
  48.             $user $passport->getUser();
  49.             if (!$user instanceof PasswordAuthenticatedUserInterface) {
  50.                 trigger_deprecation('symfony/security-http''5.3''Not implementing the "%s" interface in class "%s" while using password-based authentication is deprecated.'PasswordAuthenticatedUserInterface::class, get_debug_type($user));
  51.             }
  52.             /** @var PasswordCredentials $badge */
  53.             $badge $passport->getBadge(PasswordCredentials::class);
  54.             if ($badge->isResolved()) {
  55.                 return;
  56.             }
  57.             $presentedPassword $badge->getPassword();
  58.             if ('' === $presentedPassword) {
  59.                 throw new BadCredentialsException('The presented password cannot be empty.');
  60.             }
  61.             if (null === $user->getPassword()) {
  62.                 throw new BadCredentialsException('The presented password is invalid.');
  63.             }
  64.             $salt method_exists($user'getSalt') ? $user->getSalt() : '';
  65.             if ($salt && !$user instanceof LegacyPasswordAuthenticatedUserInterface) {
  66.                 trigger_deprecation('symfony/security-http''5.3''Returning a string from "getSalt()" without implementing the "%s" interface is deprecated, the "%s" class should implement it.'LegacyPasswordAuthenticatedUserInterface::class, get_debug_type($user));
  67.             }
  68.             // @deprecated since Symfony 5.3
  69.             if ($this->hasherFactory instanceof EncoderFactoryInterface) {
  70.                 if (!$this->hasherFactory->getEncoder($user)->isPasswordValid($user->getPassword(), $presentedPassword$salt)) {
  71.                     throw new BadCredentialsException('The presented password is invalid.');
  72.                 }
  73.             } else {
  74.                 if (!$this->hasherFactory->getPasswordHasher($user)->verify($user->getPassword(), $presentedPassword$salt)) {
  75.                     throw new BadCredentialsException('The presented password is invalid.');
  76.                 }
  77.             }
  78.             $badge->markResolved();
  79.             if (!$passport->hasBadge(PasswordUpgradeBadge::class)) {
  80.                 $passport->addBadge(new PasswordUpgradeBadge($presentedPassword));
  81.             }
  82.             return;
  83.         }
  84.         if ($passport->hasBadge(CustomCredentials::class)) {
  85.             /** @var CustomCredentials $badge */
  86.             $badge $passport->getBadge(CustomCredentials::class);
  87.             if ($badge->isResolved()) {
  88.                 return;
  89.             }
  90.             $badge->executeCustomChecker($passport->getUser());
  91.             return;
  92.         }
  93.     }
  94.     public static function getSubscribedEvents(): array
  95.     {
  96.         return [CheckPassportEvent::class => 'checkPassport'];
  97.     }
  98. }