title: Custom authentication in a Symfony 3 using external REST API
body: <p>I would like to write a basic login form, which authenticates users by sending a request to an external REST API. The external API receives the login/password and return 200 (ok) if the credentials are correct.
  However, I can't implement it via the UserProviderInterface, because the external REST API give me the password in the reply. (I can't fill the user password in the loadUserByUsername method).</p>
  
  <p>I found a valid solution here, but it uses classes that have been removed in Symfony 3 : <a href="https://stackoverflow.com/questions/29645313/symfony2-custom-connection-by-web-service">Symfony2 custom connection by web service</a></p>
  
  <p>I made a test with a custom Authenticator, which only checks that the password is "toto", but I get a redirection loop and my dummy UserProvider is still called :</p>
  
  <pre><code>&lt;?php
  namespace AppBundle\Security\User;
  
  use Symfony\Component\HttpFoundation\Request;
  use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
  use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
  use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
  use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
  use Symfony\Component\Security\Core\User\UserProviderInterface;
  use Symfony\Component\Security\Http\Authentication\SimpleFormAuthenticatorInterface;
  
  class WebserviceAuthenticator implements SimpleFormAuthenticatorInterface
  {
      private $encoder;
  
      public function __construct(UserPasswordEncoderInterface $encoder)
      {
          $this-&gt;encoder = $encoder;
      }
  
      public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
      {
          $user = new WebserviceUser($token-&gt;getUsername(), $token-&gt;getCredentials(), null, ['ROLE_ADMIN']);
  
          // HERE : call the external REST API
          if ($token-&gt;getCredentials() === 'toto') {
              $token = new UsernamePasswordToken(
                  $user,
                  $user-&gt;getPassword(),
                  'main',
                  $user-&gt;getRoles()
              );
              return $token;
          }
          throw new CustomUserMessageAuthenticationException('Invalid username or password');
      }
  
      public function supportsToken(TokenInterface $token, $providerKey)
      {
          return $token instanceof UsernamePasswordToken
          &amp;&amp; $token-&gt;getProviderKey() === $providerKey;
      }
  
      public function createToken(Request $request, $username, $password, $providerKey)
      {
          return new UsernamePasswordToken($username, $password, $providerKey);
      }
  }
  </code></pre>