<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Authentication\Provider;
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\AccountStatusException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAccountStatusException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', UserAuthenticationProvider::class);
/**
* UserProviderInterface retrieves users for UsernamePasswordToken tokens.
*
* @author Fabien Potencier <[email protected]>
*
* @deprecated since Symfony 5.3, use the new authenticator system instead
*/
abstract class UserAuthenticationProvider implements AuthenticationProviderInterface
{
private $hideUserNotFoundExceptions;
private $userChecker;
private $providerKey;
/**
* @throws \InvalidArgumentException
*/
public function __construct(UserCheckerInterface $userChecker, string $providerKey, bool $hideUserNotFoundExceptions = true)
{
if (empty($providerKey)) {
throw new \InvalidArgumentException('$providerKey must not be empty.');
}
$this->userChecker = $userChecker;
$this->providerKey = $providerKey;
$this->hideUserNotFoundExceptions = $hideUserNotFoundExceptions;
}
/**
* {@inheritdoc}
*/
public function authenticate(TokenInterface $token)
{
if (!$this->supports($token)) {
throw new AuthenticationException('The token is not supported by this authentication provider.');
}
$username = method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername();
if ('' === $username || null === $username) {
$username = AuthenticationProviderInterface::USERNAME_NONE_PROVIDED;
}
try {
$user = $this->retrieveUser($username, $token);
} catch (UserNotFoundException $e) {
if ($this->hideUserNotFoundExceptions) {
throw new BadCredentialsException('Bad credentials.', 0, $e);
}
$e->setUserIdentifier($username);
throw $e;
}
if (!$user instanceof UserInterface) {
throw new AuthenticationServiceException('retrieveUser() must return a UserInterface.');
}
try {
$this->userChecker->checkPreAuth($user);
$this->checkAuthentication($user, $token);
$this->userChecker->checkPostAuth($user);
} catch (AccountStatusException|BadCredentialsException $e) {
if ($this->hideUserNotFoundExceptions && !$e instanceof CustomUserMessageAccountStatusException) {
throw new BadCredentialsException('Bad credentials.', 0, $e);
}
throw $e;
}
if ($token instanceof SwitchUserToken) {
$roles = $user->getRoles();
$roles[] = 'ROLE_PREVIOUS_ADMIN';
$authenticatedToken = new SwitchUserToken($user, $token->getCredentials(), $this->providerKey, $roles, $token->getOriginalToken());
} else {
$authenticatedToken = new UsernamePasswordToken($user, $token->getCredentials(), $this->providerKey, $user->getRoles());
}
$authenticatedToken->setAttributes($token->getAttributes());
return $authenticatedToken;
}
/**
* {@inheritdoc}
*/
public function supports(TokenInterface $token)
{
return $token instanceof UsernamePasswordToken && $this->providerKey === $token->getFirewallName();
}
/**
* Retrieves the user from an implementation-specific location.
*
* @return UserInterface
*
* @throws AuthenticationException if the credentials could not be validated
*/
abstract protected function retrieveUser(string $username, UsernamePasswordToken $token);
/**
* Does additional checks on the user and token (like validating the
* credentials).
*
* @throws AuthenticationException if the credentials could not be validated
*/
abstract protected function checkAuthentication(UserInterface $user, UsernamePasswordToken $token);
}