I was working on custom web service authentication, that requires username as password combination, like this "username_password" to be passed via POST method.
Here's what I'v got:
I created Web service User, and User provider classes, by following this documentation, and configured security.yml according to this guide.
But since I need to pass password to UserProvider, I folowed this solution provided in answer, by passing request service to UserProvider class and got this:
class WebserviceUserProvider implements UserProviderInterface
{
private $request;
private $buzz;
private $password;
public function __construct(ContainerInterface $container)
{
$this->request = $container->get('request');
$this->buzz = $container->get('buzz');
}
public function loadUserByUsername($username)
{
if ($this->request->get('_password')) {
$this->password = $this->request->get('_password');
}
//remote air.salda.lt login service
$userData = $this->buzz->post(
'http://remote.service.url',
array(),
array("UID" => $username.'_'.$this->password)
);
if ($userData->getContent() == 'OK') {
$password = $this->password;
$salt = '';
//here should be additional logic to fetch user roles from db, specific to application
$roles = array('ROLE_USER');
return new WebserviceUser($username, $password, $salt, $roles);
}
throw new UsernameNotFoundException(
sprintf('Username "%s" does not exist.', $username)
);
}
public function refreshUser(UserInterface $user)
{
if (!$user instanceof WebserviceUser) {
throw new UnsupportedUserException(
sprintf('Instances of "%s" are not supported.', get_class($user))
);
}
$this->password = $user->getPassword();
return $this->loadUserByUsername($user->getUsername());
}
public function supportsClass($class)
{
return $class === 'Cc\ClientControlBundle\Security\User\WebserviceUser';
}
}
Notice in "loadUserByUsername" method
if ($this->request->get('_password')) {
$this->password = $this->request->get('_password');
}
And in "refreshUser" method
$this->password = $user->getPassword();
I done this because, when getting password from request first time it works fine, but when "refreshUser" happens, request object seems to be missing password, so by saving password globally in a class, I can access it later.
This solution works, but to me it's seems like a hack, I would really like to solve this problem properly, but I don't know how, maybe by using Custom Authenticator Provider? Thought it seems really complicated. Some advices and guidance would help.