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).
I found a valid solution here, but it uses classes that have been removed in Symfony 3 : Symfony2 custom connection by web service
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 :
<?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->encoder = $encoder;
}
public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
{
$user = new WebserviceUser($token->getUsername(), $token->getCredentials(), null, ['ROLE_ADMIN']);
// HERE : call the external REST API
if ($token->getCredentials() === 'toto') {
$token = new UsernamePasswordToken(
$user,
$user->getPassword(),
'main',
$user->getRoles()
);
return $token;
}
throw new CustomUserMessageAuthenticationException('Invalid username or password');
}
public function supportsToken(TokenInterface $token, $providerKey)
{
return $token instanceof UsernamePasswordToken
&& $token->getProviderKey() === $providerKey;
}
public function createToken(Request $request, $username, $password, $providerKey)
{
return new UsernamePasswordToken($username, $password, $providerKey);
}
}