title: Upgrade to new symfony authenticator system: can't log in anymore
body: <p>Following an upgrade from Symfony 4 to the latest Symfony 5 version, I've tried upgrading my registration and login form guard thingies to become authenticator thingies.</p>
  <p>After trying a lot of stuff, and using the <code>make:user</code> and <code>make:auth</code> commands again and again, I'm now in a situation where I have no warning, no error, just when I try to log in, nothing happens: it doesn't matter whether the username/password combination is correct or not, I just get back to the login form.</p>
  <p>Here are the files I believe could be relevant to the issue:</p>
  <p>config/packages/security.yaml</p>
  <pre><code>security:
      enable_authenticator_manager: true
  
      password_hashers:
          App\Entity\Player:
              algorithm: auto
  
      providers:
          app_user_provider:
              entity:
                  class: App\Entity\Player
                  property: email
  
      firewalls:
          dev:
              pattern: ^/(_(profiler|wdt)|css|images|js)/
              security: false
          main:
              lazy: true
              provider: app_user_provider
              custom_authenticator: App\Security\LoginFormAuthenticator
              logout:
                  path: app_logout
              remember_me:
                  secret: '%kernel.secret%'
                  lifetime: 604800
                  path: /
                  always_remember_me: true
              switch_user: true
  
      access_control:
          # - { path: ^/admin, roles: ROLE_ADMIN }
          # - { path: ^/profile, roles: ROLE_USER }
  </code></pre>
  <p>src/Controller/SecurityController.php</p>
  <pre><code>&lt;?php
  
      namespace App\Controller;
  
      use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
      use Symfony\Component\HttpFoundation\Response;
      use Symfony\Component\Routing\Annotation\Route;
      use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
  
      class SecurityController extends AbstractController
      {
          /**
           * @Route(&quot;/login&quot;, name=&quot;app_login&quot;)
           */
          public function login(AuthenticationUtils $authenticationUtils): Response
          {
              // If the user is logged in, redirect them to their profile page.
              if ($this-&gt;getUser()) {
                  return $this-&gt;redirectToRoute('player_control_panel');
              }
  
              // get the login error if there is one
              $error = $authenticationUtils-&gt;getLastAuthenticationError();
              // last username entered by the user
              $lastUsername = $authenticationUtils-&gt;getLastUsername();
  
              return $this-&gt;render('security/login.html.twig', ['last_username' =&gt; $lastUsername, 'error' =&gt; $error]);
          }
  
          /**
           * @Route(&quot;/logout&quot;, name=&quot;app_logout&quot;)
           */
          public function logout()
          {
              throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
          }
      }
  </code></pre>
  <p>src/Entity/Player.php</p>
  <pre><code>&lt;?php
  
  namespace App\Entity;
  
  use App\Repository\PlayerRepository;
  use Doctrine\ORM\Mapping as ORM;
  use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
  use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
  use Symfony\Component\Security\Core\User\UserInterface;
  
  /**
   * @ORM\Entity(repositoryClass=PlayerRepository::class)
   * @UniqueEntity(fields={&quot;email&quot;}, message=&quot;There is already an account with this email&quot;)
   */
  class Player implements UserInterface, PasswordAuthenticatedUserInterface
  {
      /**
       * @ORM\Id
       * @ORM\GeneratedValue
       * @ORM\Column(type=&quot;integer&quot;)
       */
      private $id;
  
      /**
       * @ORM\Column(type=&quot;string&quot;, length=180, unique=true)
       */
      private $email;
  
      /**
       * @ORM\Column(type=&quot;json&quot;)
       */
      private $roles = [];
  
      /**
       * @var string The hashed password
       * @ORM\Column(type=&quot;string&quot;)
       */
      private $password;
  
      /**
       * @ORM\Column(type=&quot;boolean&quot;)
       */
      private $isVerified = false;
  
      public function getId(): ?int
      {
          return $this-&gt;id;
      }
  
      public function getEmail(): ?string
      {
          return $this-&gt;email;
      }
  
      public function setEmail(string $email): self
      {
          $this-&gt;email = $email;
  
          return $this;
      }
  
      /**
       * A visual identifier that represents this user.
       *
       * @see UserInterface
       */
      public function getUserIdentifier(): string
      {
          return (string) $this-&gt;email;
      }
  
      /**
       * @deprecated since Symfony 5.3, use getUserIdentifier instead
       */
      public function getUsername(): string
      {
          return (string) $this-&gt;email;
      }
  
      /**
       * @see UserInterface
       */
      public function getRoles(): array
      {
          $roles = $this-&gt;roles;
          // guarantee every user at least has ROLE_USER
          $roles[] = 'ROLE_USER';
  
          return array_unique($roles);
      }
  
      public function setRoles(array $roles): self
      {
          $this-&gt;roles = $roles;
  
          return $this;
      }
  
      /**
       * @see PasswordAuthenticatedUserInterface
       */
      public function getPassword(): string
      {
          return $this-&gt;password;
      }
  
      public function setPassword(string $password): self
      {
          $this-&gt;password = $password;
  
          return $this;
      }
  
      /**
       * Returning a salt is only needed, if you are not using a modern
       * hashing algorithm (e.g. bcrypt or sodium) in your security.yaml.
       *
       * @see UserInterface
       */
      public function getSalt(): ?string
      {
          return null;
      }
  
      /**
       * @see UserInterface
       */
      public function eraseCredentials()
      {
          // If you store any temporary, sensitive data on the user, clear it here
          // $this-&gt;plainPassword = null;
      }
  
      public function isVerified(): bool
      {
          return $this-&gt;isVerified;
      }
  
      public function setIsVerified(bool $isVerified): self
      {
          $this-&gt;isVerified = $isVerified;
  
          return $this;
      }
  }
  </code></pre>
  <p>src/Security/LoginFormAuthenticator.php</p>
  <pre><code>&lt;?php
  
  namespace App\Security;
  
  use Symfony\Component\HttpFoundation\RedirectResponse;
  use Symfony\Component\HttpFoundation\Request;
  use Symfony\Component\HttpFoundation\Response;
  use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  use Symfony\Component\Security\Core\Security;
  use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;
  use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
  use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
  use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
  use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
  use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
  use Symfony\Component\Security\Http\Util\TargetPathTrait;
  
  class LoginFormAuthenticator extends AbstractLoginFormAuthenticator
  {
      use TargetPathTrait;
  
      public const LOGIN_ROUTE = 'app_login';
  
      private UrlGeneratorInterface $urlGenerator;
  
      public function __construct(UrlGeneratorInterface $urlGenerator)
      {
          $this-&gt;urlGenerator = $urlGenerator;
      }
  
      public function authenticate(Request $request): PassportInterface
      {
          $email = $request-&gt;request-&gt;get('email', '');
  
          $request-&gt;getSession()-&gt;set(Security::LAST_USERNAME, $email);
  
          return new Passport(
              new UserBadge($email),
              new PasswordCredentials($request-&gt;request-&gt;get('password', '')),
              [
                  new CsrfTokenBadge('authenticate', $request-&gt;request-&gt;get('_csrf_token')),
              ]
          );
      }
  
      public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
      {
          $request-&gt;getSession()-&gt;getFlashBag()-&gt;add('success', &quot;You are now signed in. Greetings, commander.&quot;);
  
          if ($targetPath = $this-&gt;getTargetPath($request-&gt;getSession(), $firewallName)) {
              return new RedirectResponse($targetPath);
          }
  
          return new RedirectResponse($this-&gt;urlGenerator-&gt;generate('app_index'));
      }
  
      protected function getLoginUrl(Request $request): string
      {
          return $this-&gt;urlGenerator-&gt;generate(self::LOGIN_ROUTE);
      }
  }
  </code></pre>
  <p>I just can't see what's going wrong, if you have an idea, or even if you can just give me an idea of how I could get an idea of what's going wrong, I'd appreciate it. Thank you!</p>