vendor/symfony/security-http/EventListener/PasswordMigratingListener.php line 45

  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\User\LegacyPasswordAuthenticatedUserInterface;
  14. use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
  15. use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
  16. use Symfony\Component\Security\Http\Authenticator\Passport\Badge\PasswordUpgradeBadge;
  17. use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
  18. use Symfony\Component\Security\Http\Event\LoginSuccessEvent;
  19. /**
  20.  * @author Wouter de Jong <wouter@wouterj.nl>
  21.  *
  22.  * @final
  23.  */
  24. class PasswordMigratingListener implements EventSubscriberInterface
  25. {
  26.     private PasswordHasherFactoryInterface $hasherFactory;
  27.     public function __construct(PasswordHasherFactoryInterface $hasherFactory)
  28.     {
  29.         $this->hasherFactory $hasherFactory;
  30.     }
  31.     public function onLoginSuccess(LoginSuccessEvent $event): void
  32.     {
  33.         $passport $event->getPassport();
  34.         if (!$passport->hasBadge(PasswordUpgradeBadge::class)) {
  35.             return;
  36.         }
  37.         /** @var PasswordUpgradeBadge $badge */
  38.         $badge $passport->getBadge(PasswordUpgradeBadge::class);
  39.         $plaintextPassword $badge->getAndErasePlaintextPassword();
  40.         if ('' === $plaintextPassword) {
  41.             return;
  42.         }
  43.         $user $passport->getUser();
  44.         if (!$user instanceof PasswordAuthenticatedUserInterface || null === $user->getPassword()) {
  45.             return;
  46.         }
  47.         $passwordHasher $this->hasherFactory->getPasswordHasher($user);
  48.         if (!$passwordHasher->needsRehash($user->getPassword())) {
  49.             return;
  50.         }
  51.         $passwordUpgrader $badge->getPasswordUpgrader();
  52.         if (null === $passwordUpgrader) {
  53.             if (!$passport->hasBadge(UserBadge::class)) {
  54.                 return;
  55.             }
  56.             /** @var UserBadge $userBadge */
  57.             $userBadge $passport->getBadge(UserBadge::class);
  58.             $userLoader $userBadge->getUserLoader();
  59.             if (\is_array($userLoader) && $userLoader[0] instanceof PasswordUpgraderInterface) {
  60.                 $passwordUpgrader $userLoader[0];
  61.             } elseif (!$userLoader instanceof \Closure
  62.                 || !($passwordUpgrader = (new \ReflectionFunction($userLoader))->getClosureThis()) instanceof PasswordUpgraderInterface
  63.             ) {
  64.                 return;
  65.             }
  66.         }
  67.         $salt null;
  68.         if ($user instanceof LegacyPasswordAuthenticatedUserInterface) {
  69.             $salt $user->getSalt();
  70.         }
  71.         $passwordUpgrader->upgradePassword($user$passwordHasher->hash($plaintextPassword$salt));
  72.     }
  73.     public static function getSubscribedEvents(): array
  74.     {
  75.         return [LoginSuccessEvent::class => 'onLoginSuccess'];
  76.     }
  77. }