Default to user provider, if available, in password upgrader
This commit is contained in:
parent
0302332238
commit
e39e844606
@ -15,6 +15,7 @@ CHANGELOG
|
||||
* Added `LoginThrottlingListener`.
|
||||
* Added `LoginLinkAuthenticator`.
|
||||
* Moved methods `supports()` and `authenticate()` from `AbstractListener` to `FirewallListenerInterface`.
|
||||
* [BC break] `PasswordUpgradeBadge::getPasswordUpgrader()` changed its return type to return null or a `PasswordUpgraderInterface` implementation.
|
||||
|
||||
5.1.0
|
||||
-----
|
||||
|
@ -30,10 +30,10 @@ class PasswordUpgradeBadge implements BadgeInterface
|
||||
private $passwordUpgrader;
|
||||
|
||||
/**
|
||||
* @param string $plaintextPassword The presented password, used in the rehash
|
||||
* @param PasswordUpgraderInterface $passwordUpgrader The password upgrader, usually the UserProvider
|
||||
* @param string $plaintextPassword The presented password, used in the rehash
|
||||
* @param PasswordUpgraderInterface|null $passwordUpgrader The password upgrader, defaults to the UserProvider if null
|
||||
*/
|
||||
public function __construct(string $plaintextPassword, PasswordUpgraderInterface $passwordUpgrader)
|
||||
public function __construct(string $plaintextPassword, ?PasswordUpgraderInterface $passwordUpgrader = null)
|
||||
{
|
||||
$this->plaintextPassword = $plaintextPassword;
|
||||
$this->passwordUpgrader = $passwordUpgrader;
|
||||
@ -51,7 +51,7 @@ class PasswordUpgradeBadge implements BadgeInterface
|
||||
return $password;
|
||||
}
|
||||
|
||||
public function getPasswordUpgrader(): PasswordUpgraderInterface
|
||||
public function getPasswordUpgrader(): ?PasswordUpgraderInterface
|
||||
{
|
||||
return $this->passwordUpgrader;
|
||||
}
|
||||
|
@ -13,7 +13,9 @@ namespace Symfony\Component\Security\Http\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
|
||||
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\PasswordUpgradeBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\UserPassportInterface;
|
||||
use Symfony\Component\Security\Http\Event\LoginSuccessEvent;
|
||||
|
||||
@ -53,7 +55,19 @@ class PasswordMigratingListener implements EventSubscriberInterface
|
||||
return;
|
||||
}
|
||||
|
||||
$badge->getPasswordUpgrader()->upgradePassword($user, $passwordEncoder->encodePassword($plaintextPassword, $user->getSalt()));
|
||||
$passwordUpgrader = $badge->getPasswordUpgrader();
|
||||
if (null === $passwordUpgrader) {
|
||||
/** @var UserBadge $userBadge */
|
||||
$userBadge = $passport->getBadge(UserBadge::class);
|
||||
$userLoader = $userBadge->getUserLoader();
|
||||
if (\is_array($userLoader) && $userLoader[0] instanceof PasswordUpgraderInterface) {
|
||||
$passwordUpgrader = $userLoader[0];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$passwordUpgrader->upgradePassword($user, $passwordEncoder->encodePassword($plaintextPassword, $user->getSalt()));
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
|
@ -16,6 +16,9 @@ use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||
use Symfony\Component\Security\Http\Event\CheckPassportEvent;
|
||||
|
||||
/**
|
||||
* Configures the user provider as user loader, if no user load
|
||||
* has been explicitly set.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*
|
||||
* @final
|
||||
|
@ -18,6 +18,7 @@ use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
|
||||
use Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface;
|
||||
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\PasswordUpgradeBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||
@ -34,9 +35,14 @@ class PasswordMigratingListenerTest extends TestCase
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->encoderFactory = $this->createMock(EncoderFactoryInterface::class);
|
||||
$this->listener = new PasswordMigratingListener($this->encoderFactory);
|
||||
$this->user = $this->createMock(UserInterface::class);
|
||||
$this->user->expects($this->any())->method('getPassword')->willReturn('old-encoded-password');
|
||||
$encoder = $this->createMock(PasswordEncoderInterface::class);
|
||||
$encoder->expects($this->any())->method('needsRehash')->willReturn(true);
|
||||
$encoder->expects($this->any())->method('encodePassword')->with('pa$$word', null)->willReturn('new-encoded-password');
|
||||
$this->encoderFactory = $this->createMock(EncoderFactoryInterface::class);
|
||||
$this->encoderFactory->expects($this->any())->method('getEncoder')->with($this->user)->willReturn($encoder);
|
||||
$this->listener = new PasswordMigratingListener($this->encoderFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -61,16 +67,8 @@ class PasswordMigratingListenerTest extends TestCase
|
||||
yield [$this->createEvent($this->createMock(PassportInterface::class))];
|
||||
}
|
||||
|
||||
public function testUpgrade()
|
||||
public function testUpgradeWithUpgrader()
|
||||
{
|
||||
$encoder = $this->createMock(PasswordEncoderInterface::class);
|
||||
$encoder->expects($this->any())->method('needsRehash')->willReturn(true);
|
||||
$encoder->expects($this->any())->method('encodePassword')->with('pa$$word', null)->willReturn('new-encoded-password');
|
||||
|
||||
$this->encoderFactory->expects($this->any())->method('getEncoder')->with($this->user)->willReturn($encoder);
|
||||
|
||||
$this->user->expects($this->any())->method('getPassword')->willReturn('old-encoded-password');
|
||||
|
||||
$passwordUpgrader = $this->createPasswordUpgrader();
|
||||
$passwordUpgrader->expects($this->once())
|
||||
->method('upgradePassword')
|
||||
@ -81,6 +79,20 @@ class PasswordMigratingListenerTest extends TestCase
|
||||
$this->listener->onLoginSuccess($event);
|
||||
}
|
||||
|
||||
public function testUpgradeWithoutUpgrader()
|
||||
{
|
||||
$userLoader = $this->createMock(MigratingUserProvider::class);
|
||||
$userLoader->expects($this->any())->method('loadUserByUsername')->willReturn($this->user);
|
||||
|
||||
$userLoader->expects($this->once())
|
||||
->method('upgradePassword')
|
||||
->with($this->user, 'new-encoded-password')
|
||||
;
|
||||
|
||||
$event = $this->createEvent(new SelfValidatingPassport(new UserBadge('test', [$userLoader, 'loadUserByUsername']), [new PasswordUpgradeBadge('pa$$word')]));
|
||||
$this->listener->onLoginSuccess($event);
|
||||
}
|
||||
|
||||
private function createPasswordUpgrader()
|
||||
{
|
||||
return $this->createMock(PasswordUpgraderInterface::class);
|
||||
@ -91,3 +103,7 @@ class PasswordMigratingListenerTest extends TestCase
|
||||
return new LoginSuccessEvent($this->createMock(AuthenticatorInterface::class), $passport, $this->createMock(TokenInterface::class), new Request(), null, 'main');
|
||||
}
|
||||
}
|
||||
|
||||
abstract class MigratingUserProvider implements UserProviderInterface, PasswordUpgraderInterface
|
||||
{
|
||||
}
|
||||
|
Reference in New Issue
Block a user