The password is erased as another listener already used this badge

116 Views Asked by At

During an update from Symfony 4 to 6, I ran into a problem with the security component.

When trying to access a route after I successfully log in via the HTTP auth under this firewall:

security.yaml:

        xxx:
            pattern: ^/xxx
            provider: chain_provider
            http_basic: ~

where chain_provider is:

    providers:
        fos_userbundle:
            id: fos_user.user_provider.username_email
        in_memory:
            memory:
                users:
                    {...}
        chain_provider:
            chain:
                providers: [ in_memory, fos_userbundle ]

and password_hashers:

    password_hashers:
        FOS\UserBundle\Model\UserInterface: bcrypt
        Symfony\Component\Security\Core\User\InMemoryUser: bcrypt

I get this error: The password is erased as another listener already used this badge.

It is thrown at vendor/symfony/security-http/Authenticator/Passport/Badge/PasswordUpgradeBadge.php:45:

    public function getAndErasePlaintextPassword(): string
    {
        $password = $this->plaintextPassword;
        if (null === $password) {
            throw new LogicException('The password is erased as another listener already used this badge.');
        }

        $this->plaintextPassword = null;

        return $password;
    }

Which is being called at vendor/symfony/security-http/EventListener/PasswordMigratingListener.php:46:

    public function onLoginSuccess(LoginSuccessEvent $event): void
    {
        $passport = $event->getPassport();
        if (!$passport->hasBadge(PasswordUpgradeBadge::class)) {
            return;
        }

        /** @var PasswordUpgradeBadge $badge */
        $badge = $passport->getBadge(PasswordUpgradeBadge::class);
        $plaintextPassword = $badge->getAndErasePlaintextPassword();
        ...

It only does work, after it throws this error, when I disable the http_basic under the firewall. But I need that in there, of course. Changing the provider does nothing, neither using different hash algorithms.

Also, the password was in plain_text before, which I changed, and now I get that error.

The hashing I did like this: bin/console security:hash-password - for the InMemoryUser:

 --------------- ----------------------------------------------------------------- 
  Key             Value                                                            
 --------------- ----------------------------------------------------------------- 
  Hasher used     Symfony\Component\PasswordHasher\Hasher\MigratingPasswordHasher  
  Password hash   xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx     
 --------------- ----------------------------------------------------------------- 

I do not have any other event listeners neither for logging / users / security.

What am I missing or did wrong?

Why does it use MigratingPasswordHasher with any given hashing algorithm? I tried following the docs https://symfony.com/doc/current/security/passwords.html#password-migration, but with no luck.

1

There are 1 best solutions below

0
On BEST ANSWER

Turned out the problem was somewhere else, when I did bin/console debug:event-dispatcher I had duplicated event dispatchers due to a bug in one of the bundles (it was adding new RegisterListenersPass into a container compiler pass), so it made sense the badge had been already used when it was being called twice.

Be sure to check that if you run into this issue!