login consent app sql

This commit is contained in:
2022-05-03 08:54:45 +02:00
parent e7253acfd8
commit f9a6535906
1652 changed files with 187600 additions and 45 deletions

View File

@ -0,0 +1,35 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
/**
* AuthenticationManagerInterface is the interface for authentication managers,
* which process Token authentication.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @internal since Symfony 5.3
*/
interface AuthenticationManagerInterface
{
/**
* Attempts to authenticate a TokenInterface object.
*
* @return TokenInterface
*
* @throws AuthenticationException if the authentication fails
*/
public function authenticate(TokenInterface $token);
}

View File

@ -0,0 +1,133 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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;
use Symfony\Component\PasswordHasher\Exception\InvalidPasswordException;
use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\AuthenticationEvents;
use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent;
use Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent;
use Symfony\Component\Security\Core\Exception\AccountStatusException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\ProviderNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', AuthenticationProviderManager::class);
// Help opcache.preload discover always-needed symbols
class_exists(AuthenticationEvents::class);
class_exists(AuthenticationFailureEvent::class);
class_exists(AuthenticationSuccessEvent::class);
/**
* AuthenticationProviderManager uses a list of AuthenticationProviderInterface
* instances to authenticate a Token.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*
* @deprecated since Symfony 5.3, use the new authenticator system instead
*/
class AuthenticationProviderManager implements AuthenticationManagerInterface
{
private $providers;
private $eraseCredentials;
private $eventDispatcher;
/**
* @param iterable<mixed, AuthenticationProviderInterface> $providers An iterable with AuthenticationProviderInterface instances as values
* @param bool $eraseCredentials Whether to erase credentials after authentication or not
*
* @throws \InvalidArgumentException
*/
public function __construct(iterable $providers, bool $eraseCredentials = true)
{
if (!$providers) {
throw new \InvalidArgumentException('You must at least add one authentication provider.');
}
$this->providers = $providers;
$this->eraseCredentials = $eraseCredentials;
}
public function setEventDispatcher(EventDispatcherInterface $dispatcher)
{
$this->eventDispatcher = $dispatcher;
}
/**
* {@inheritdoc}
*/
public function authenticate(TokenInterface $token)
{
$lastException = null;
$result = null;
foreach ($this->providers as $provider) {
if (!$provider instanceof AuthenticationProviderInterface) {
throw new \InvalidArgumentException(sprintf('Provider "%s" must implement the AuthenticationProviderInterface.', get_debug_type($provider)));
}
if (!$provider->supports($token)) {
continue;
}
try {
$result = $provider->authenticate($token);
if (null !== $result) {
break;
}
} catch (AccountStatusException $e) {
$lastException = $e;
break;
} catch (AuthenticationException $e) {
$lastException = $e;
} catch (InvalidPasswordException $e) {
$lastException = new BadCredentialsException('Bad credentials.', 0, $e);
}
}
if (null !== $result) {
if (true === $this->eraseCredentials) {
$result->eraseCredentials();
}
if (null !== $this->eventDispatcher) {
$this->eventDispatcher->dispatch(new AuthenticationSuccessEvent($result), AuthenticationEvents::AUTHENTICATION_SUCCESS);
}
// @deprecated since Symfony 5.3
if ($result->getUser() instanceof UserInterface && !method_exists($result->getUser(), 'getUserIdentifier')) {
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "getUserIdentifier(): string" in user class "%s" is deprecated. This method will replace "getUsername()" in Symfony 6.0.', get_debug_type($result->getUser()));
}
return $result;
}
if (null === $lastException) {
$lastException = new ProviderNotFoundException(sprintf('No Authentication Provider found for token of class "%s".', \get_class($token)));
}
if (null !== $this->eventDispatcher) {
$this->eventDispatcher->dispatch(new AuthenticationFailureEvent($token, $lastException), AuthenticationEvents::AUTHENTICATION_FAILURE);
}
$lastException->setToken($token);
throw $lastException;
}
}

View File

@ -0,0 +1,59 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
* The default implementation of the authentication trust resolver.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class AuthenticationTrustResolver implements AuthenticationTrustResolverInterface
{
public function isAuthenticated(TokenInterface $token = null): bool
{
return $token && $token->getUser()
// @deprecated since Symfony 5.4, TokenInterface::isAuthenticated() and AnonymousToken no longer exists in 6.0
&& !$token instanceof AnonymousToken && (!method_exists($token, 'isAuthenticated') || $token->isAuthenticated(false));
}
/**
* {@inheritdoc}
*/
public function isAnonymous(TokenInterface $token = null/*, $deprecation = true*/)
{
if (1 === \func_num_args() || false !== func_get_arg(1)) {
trigger_deprecation('symfony/security-core', '5.4', 'The "%s()" method is deprecated, use "isAuthenticated()" or "isFullFledged()" if you want to check if the request is (fully) authenticated.', __METHOD__);
}
return $token instanceof AnonymousToken || ($token && !$token->getUser());
}
/**
* {@inheritdoc}
*/
public function isRememberMe(TokenInterface $token = null)
{
return $token && $token instanceof RememberMeToken;
}
/**
* {@inheritdoc}
*/
public function isFullFledged(TokenInterface $token = null)
{
return $token && !$this->isAnonymous($token, false) && !$this->isRememberMe($token);
}
}

View File

@ -0,0 +1,51 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
* Interface for resolving the authentication status of a given token.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*
* @method bool isAuthenticated(TokenInterface $token = null)
*/
interface AuthenticationTrustResolverInterface
{
/**
* Resolves whether the passed token implementation is authenticated
* anonymously.
*
* If null is passed, the method must return false.
*
* @return bool
*
* @deprecated since Symfony 5.4, use !isAuthenticated() instead
*/
public function isAnonymous(TokenInterface $token = null);
/**
* Resolves whether the passed token implementation is authenticated
* using remember-me capabilities.
*
* @return bool
*/
public function isRememberMe(TokenInterface $token = null);
/**
* Resolves whether the passed token implementation is fully authenticated.
*
* @return bool
*/
public function isFullFledged(TokenInterface $token = null);
}

View File

@ -0,0 +1,69 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\AnonymousToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', AnonymousAuthenticationProvider::class);
/**
* AnonymousAuthenticationProvider validates AnonymousToken instances.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since Symfony 5.3, use the new authenticator system instead
*/
class AnonymousAuthenticationProvider implements AuthenticationProviderInterface
{
/**
* Used to determine if the token is created by the application
* instead of a malicious client.
*
* @var string
*/
private $secret;
/**
* @param string $secret The secret shared with the AnonymousToken
*/
public function __construct(string $secret)
{
$this->secret = $secret;
}
/**
* {@inheritdoc}
*/
public function authenticate(TokenInterface $token)
{
if (!$this->supports($token)) {
throw new AuthenticationException('The token is not supported by this authentication provider.');
}
if ($this->secret !== $token->getSecret()) {
throw new BadCredentialsException('The Token does not contain the expected key.');
}
return $token;
}
/**
* {@inheritdoc}
*/
public function supports(TokenInterface $token)
{
return $token instanceof AnonymousToken;
}
}

View File

@ -0,0 +1,44 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" interface is deprecated, use the new authenticator system instead.', AuthenticationProviderInterface::class);
/**
* AuthenticationProviderInterface is the interface for all authentication
* providers.
*
* Concrete implementations processes specific Token instances.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since Symfony 5.3, use the new authenticator system instead
*/
interface AuthenticationProviderInterface extends AuthenticationManagerInterface
{
/**
* Use this constant for not provided username.
*
* @var string
*/
public const USERNAME_NONE_PROVIDED = 'NONE_PROVIDED';
/**
* Checks whether this provider supports the given token.
*
* @return bool
*/
public function supports(TokenInterface $token);
}

View File

@ -0,0 +1,146 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\PasswordHasher\Hasher\PasswordHasherFactoryInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\LegacyPasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', DaoAuthenticationProvider::class);
/**
* DaoAuthenticationProvider uses a UserProviderInterface to retrieve the user
* for a UsernamePasswordToken.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since Symfony 5.3, use the new authenticator system instead
*/
class DaoAuthenticationProvider extends UserAuthenticationProvider
{
private $hasherFactory;
private $userProvider;
/**
* @param PasswordHasherFactoryInterface $hasherFactory
*/
public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, string $providerKey, $hasherFactory, bool $hideUserNotFoundExceptions = true)
{
parent::__construct($userChecker, $providerKey, $hideUserNotFoundExceptions);
if ($hasherFactory instanceof EncoderFactoryInterface) {
trigger_deprecation('symfony/security-core', '5.3', 'Passing a "%s" instance to the "%s" constructor is deprecated, use "%s" instead.', EncoderFactoryInterface::class, __CLASS__, PasswordHasherFactoryInterface::class);
}
$this->hasherFactory = $hasherFactory;
$this->userProvider = $userProvider;
}
/**
* {@inheritdoc}
*/
protected function checkAuthentication(UserInterface $user, UsernamePasswordToken $token)
{
$currentUser = $token->getUser();
if ($currentUser instanceof UserInterface) {
if ($currentUser->getPassword() !== $user->getPassword()) {
throw new BadCredentialsException('The credentials were changed from another session.');
}
} else {
if ('' === ($presentedPassword = $token->getCredentials())) {
throw new BadCredentialsException('The presented password cannot be empty.');
}
if (null === $user->getPassword()) {
throw new BadCredentialsException('The presented password is invalid.');
}
if (!$user instanceof PasswordAuthenticatedUserInterface) {
trigger_deprecation('symfony/security-core', '5.3', 'Using password-based authentication listeners while not implementing "%s" interface from class "%s" is deprecated.', PasswordAuthenticatedUserInterface::class, get_debug_type($user));
}
$salt = $user->getSalt();
if ($salt && !$user instanceof LegacyPasswordAuthenticatedUserInterface) {
trigger_deprecation('symfony/security-core', '5.3', 'Returning a string from "getSalt()" without implementing the "%s" interface is deprecated, the "%s" class should implement it.', LegacyPasswordAuthenticatedUserInterface::class, get_debug_type($user));
}
// deprecated since Symfony 5.3
if ($this->hasherFactory instanceof EncoderFactoryInterface) {
$encoder = $this->hasherFactory->getEncoder($user);
if (!$encoder->isPasswordValid($user->getPassword(), $presentedPassword, $salt)) {
throw new BadCredentialsException('The presented password is invalid.');
}
if ($this->userProvider instanceof PasswordUpgraderInterface && method_exists($encoder, 'needsRehash') && $encoder->needsRehash($user->getPassword())) {
$this->userProvider->upgradePassword($user, $encoder->encodePassword($presentedPassword, $user->getSalt()));
}
return;
}
$hasher = $this->hasherFactory->getPasswordHasher($user);
if (!$hasher->verify($user->getPassword(), $presentedPassword, $salt)) {
throw new BadCredentialsException('The presented password is invalid.');
}
if ($this->userProvider instanceof PasswordUpgraderInterface && $hasher->needsRehash($user->getPassword())) {
$this->userProvider->upgradePassword($user, $hasher->hash($presentedPassword, $salt));
}
}
}
/**
* {@inheritdoc}
*/
protected function retrieveUser(string $userIdentifier, UsernamePasswordToken $token)
{
$user = $token->getUser();
if ($user instanceof UserInterface) {
return $user;
}
try {
// @deprecated since Symfony 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
if (method_exists($this->userProvider, 'loadUserByIdentifier')) {
$user = $this->userProvider->loadUserByIdentifier($userIdentifier);
} else {
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->userProvider));
$user = $this->userProvider->loadUserByUsername($userIdentifier);
}
if (!$user instanceof UserInterface) {
throw new AuthenticationServiceException('The user provider must return a UserInterface object.');
}
return $user;
} catch (UserNotFoundException $e) {
$e->setUserIdentifier($userIdentifier);
throw $e;
} catch (\Exception $e) {
$e = new AuthenticationServiceException($e->getMessage(), 0, $e);
$e->setToken($token);
throw $e;
}
}
}

View File

@ -0,0 +1,121 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\Ldap\Exception\ConnectionException;
use Symfony\Component\Ldap\LdapInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\LogicException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', LdapBindAuthenticationProvider::class);
/**
* LdapBindAuthenticationProvider authenticates a user against an LDAP server.
*
* The only way to check user credentials is to try to connect the user with its
* credentials to the ldap.
*
* @author Charles Sarrazin <charles@sarraz.in>
*
* @deprecated since Symfony 5.3, use the new authenticator system instead
*/
class LdapBindAuthenticationProvider extends UserAuthenticationProvider
{
private $userProvider;
private $ldap;
private $dnString;
private $queryString;
private $searchDn;
private $searchPassword;
public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, string $providerKey, LdapInterface $ldap, string $dnString = '{user_identifier}', bool $hideUserNotFoundExceptions = true, string $searchDn = '', string $searchPassword = '')
{
parent::__construct($userChecker, $providerKey, $hideUserNotFoundExceptions);
$this->userProvider = $userProvider;
$this->ldap = $ldap;
$this->dnString = $dnString;
$this->searchDn = $searchDn;
$this->searchPassword = $searchPassword;
}
/**
* Set a query string to use in order to find a DN for the user identifier.
*/
public function setQueryString(string $queryString)
{
$this->queryString = $queryString;
}
/**
* {@inheritdoc}
*/
protected function retrieveUser(string $userIdentifier, UsernamePasswordToken $token)
{
if (AuthenticationProviderInterface::USERNAME_NONE_PROVIDED === $userIdentifier) {
throw new UserNotFoundException('User identifier cannot be null.');
}
// @deprecated since Symfony 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
if (method_exists($this->userProvider, 'loadUserByIdentifier')) {
return $this->userProvider->loadUserByIdentifier($userIdentifier);
} else {
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->userProvider));
return $this->userProvider->loadUserByUsername($userIdentifier);
}
}
/**
* {@inheritdoc}
*/
protected function checkAuthentication(UserInterface $user, UsernamePasswordToken $token)
{
// @deprecated since Symfony 5.3, change to $token->getUserIdentifier() in 6.0
$userIdentifier = method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername();
$password = $token->getCredentials();
if ('' === (string) $password) {
throw new BadCredentialsException('The presented password must not be empty.');
}
try {
if ($this->queryString) {
if ('' !== $this->searchDn && '' !== $this->searchPassword) {
$this->ldap->bind($this->searchDn, $this->searchPassword);
} else {
throw new LogicException('Using the "query_string" config without using a "search_dn" and a "search_password" is not supported.');
}
$userIdentifier = $this->ldap->escape($userIdentifier, '', LdapInterface::ESCAPE_FILTER);
$query = str_replace(['{username}', '{user_identifier}'], $userIdentifier, $this->queryString);
$result = $this->ldap->query($this->dnString, $query)->execute();
if (1 !== $result->count()) {
throw new BadCredentialsException('The presented username is invalid.');
}
$dn = $result[0]->getDn();
} else {
$userIdentifier = $this->ldap->escape($userIdentifier, '', LdapInterface::ESCAPE_DN);
$dn = str_replace(['{username}', '{user_identifier}'], $userIdentifier, $this->dnString);
}
$this->ldap->bind($dn, $password);
} catch (ConnectionException $e) {
throw new BadCredentialsException('The presented password is invalid.');
}
}
}

View File

@ -0,0 +1,86 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\PreAuthenticatedToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" class is deprecated, use the new authenticator system instead.', PreAuthenticatedAuthenticationProvider::class);
/**
* Processes a pre-authenticated authentication request.
*
* This authentication provider will not perform any checks on authentication
* requests, as they should already be pre-authenticated. However, the
* UserProviderInterface implementation may still throw a
* UserNotFoundException, for example.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since Symfony 5.3, use the new authenticator system instead
*/
class PreAuthenticatedAuthenticationProvider implements AuthenticationProviderInterface
{
private $userProvider;
private $userChecker;
private $providerKey;
public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, string $providerKey)
{
$this->userProvider = $userProvider;
$this->userChecker = $userChecker;
$this->providerKey = $providerKey;
}
/**
* {@inheritdoc}
*/
public function authenticate(TokenInterface $token)
{
if (!$this->supports($token)) {
throw new AuthenticationException('The token is not supported by this authentication provider.');
}
if (!$user = $token->getUser()) {
throw new BadCredentialsException('No pre-authenticated principal found in request.');
}
$userIdentifier = method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername();
// @deprecated since Symfony 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
if (method_exists($this->userProvider, 'loadUserByIdentifier')) {
$user = $this->userProvider->loadUserByIdentifier($userIdentifier);
} else {
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->userProvider));
$user = $this->userProvider->loadUserByUsername($userIdentifier);
}
$this->userChecker->checkPostAuth($user);
$authenticatedToken = new PreAuthenticatedToken($user, $token->getCredentials(), $this->providerKey, $user->getRoles());
$authenticatedToken->setAttributes($token->getAttributes());
return $authenticatedToken;
}
/**
* {@inheritdoc}
*/
public function supports(TokenInterface $token)
{
return $token instanceof PreAuthenticatedToken && $this->providerKey === $token->getFirewallName();
}
}

View File

@ -0,0 +1,79 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\RememberMeToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\LogicException;
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.', RememberMeAuthenticationProvider::class);
/**
* @deprecated since Symfony 5.3, use the new authenticator system instead
*/
class RememberMeAuthenticationProvider implements AuthenticationProviderInterface
{
private $userChecker;
private $secret;
private $providerKey;
/**
* @param string $secret A secret
* @param string $providerKey A provider secret
*/
public function __construct(UserCheckerInterface $userChecker, string $secret, string $providerKey)
{
$this->userChecker = $userChecker;
$this->secret = $secret;
$this->providerKey = $providerKey;
}
/**
* {@inheritdoc}
*/
public function authenticate(TokenInterface $token)
{
if (!$this->supports($token)) {
throw new AuthenticationException('The token is not supported by this authentication provider.');
}
if ($this->secret !== $token->getSecret()) {
throw new BadCredentialsException('The presented secret does not match.');
}
$user = $token->getUser();
if (!$user instanceof UserInterface) {
throw new LogicException(sprintf('Method "%s::getUser()" must return a "%s" instance, "%s" returned.', get_debug_type($token), UserInterface::class, get_debug_type($user)));
}
$this->userChecker->checkPreAuth($user);
$this->userChecker->checkPostAuth($user);
$authenticatedToken = new RememberMeToken($user, $this->providerKey, $this->secret);
$authenticatedToken->setAttributes($token->getAttributes());
return $authenticatedToken;
}
/**
* {@inheritdoc}
*/
public function supports(TokenInterface $token)
{
return $token instanceof RememberMeToken && $token->getFirewallName() === $this->providerKey;
}
}

View File

@ -0,0 +1,131 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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 <fabien@symfony.com>
*
* @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) {
$authenticatedToken = new SwitchUserToken($user, $token->getCredentials(), $this->providerKey, $user->getRoles(), $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);
}

View File

@ -0,0 +1,75 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\RememberMe;
use Psr\Cache\CacheItemPoolInterface;
/**
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
class CacheTokenVerifier implements TokenVerifierInterface
{
private $cache;
private $outdatedTokenTtl;
private $cacheKeyPrefix;
/**
* @param int $outdatedTokenTtl How long the outdated token should still be considered valid. Defaults
* to 60, which matches how often the PersistentRememberMeHandler will at
* most refresh tokens. Increasing to more than that is not recommended,
* but you may use a lower value.
*/
public function __construct(CacheItemPoolInterface $cache, int $outdatedTokenTtl = 60, string $cacheKeyPrefix = 'rememberme-stale-')
{
$this->cache = $cache;
$this->outdatedTokenTtl = $outdatedTokenTtl;
$this->cacheKeyPrefix = $cacheKeyPrefix;
}
/**
* {@inheritdoc}
*/
public function verifyToken(PersistentTokenInterface $token, string $tokenValue): bool
{
if (hash_equals($token->getTokenValue(), $tokenValue)) {
return true;
}
$cacheKey = $this->getCacheKey($token);
$item = $this->cache->getItem($cacheKey);
if (!$item->isHit()) {
return false;
}
$outdatedToken = $item->get();
return hash_equals($outdatedToken, $tokenValue);
}
/**
* {@inheritdoc}
*/
public function updateExistingToken(PersistentTokenInterface $token, string $tokenValue, \DateTimeInterface $lastUsed): void
{
// When a token gets updated, persist the outdated token for $outdatedTokenTtl seconds so we can
// still accept it as valid in verifyToken
$item = $this->cache->getItem($this->getCacheKey($token));
$item->set($token->getTokenValue());
$item->expiresAfter($this->outdatedTokenTtl);
$this->cache->save($item);
}
private function getCacheKey(PersistentTokenInterface $token): string
{
return $this->cacheKeyPrefix.rawurlencode($token->getSeries());
}
}

View File

@ -0,0 +1,71 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\RememberMe;
use Symfony\Component\Security\Core\Exception\TokenNotFoundException;
/**
* This class is used for testing purposes, and is not really suited for production.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class InMemoryTokenProvider implements TokenProviderInterface
{
private $tokens = [];
/**
* {@inheritdoc}
*/
public function loadTokenBySeries(string $series)
{
if (!isset($this->tokens[$series])) {
throw new TokenNotFoundException('No token found.');
}
return $this->tokens[$series];
}
/**
* {@inheritdoc}
*/
public function updateToken(string $series, string $tokenValue, \DateTime $lastUsed)
{
if (!isset($this->tokens[$series])) {
throw new TokenNotFoundException('No token found.');
}
$token = new PersistentToken(
$this->tokens[$series]->getClass(),
method_exists($this->tokens[$series], 'getUserIdentifier') ? $this->tokens[$series]->getUserIdentifier() : $this->tokens[$series]->getUsername(),
$series,
$tokenValue,
$lastUsed
);
$this->tokens[$series] = $token;
}
/**
* {@inheritdoc}
*/
public function deleteTokenBySeries(string $series)
{
unset($this->tokens[$series]);
}
/**
* {@inheritdoc}
*/
public function createNewToken(PersistentTokenInterface $token)
{
$this->tokens[$token->getSeries()] = $token;
}
}

View File

@ -0,0 +1,95 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\RememberMe;
/**
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*
* @internal
*/
final class PersistentToken implements PersistentTokenInterface
{
private $class;
private $userIdentifier;
private $series;
private $tokenValue;
private $lastUsed;
public function __construct(string $class, string $userIdentifier, string $series, string $tokenValue, \DateTime $lastUsed)
{
if (empty($class)) {
throw new \InvalidArgumentException('$class must not be empty.');
}
if ('' === $userIdentifier) {
throw new \InvalidArgumentException('$userIdentifier must not be empty.');
}
if (empty($series)) {
throw new \InvalidArgumentException('$series must not be empty.');
}
if (empty($tokenValue)) {
throw new \InvalidArgumentException('$tokenValue must not be empty.');
}
$this->class = $class;
$this->userIdentifier = $userIdentifier;
$this->series = $series;
$this->tokenValue = $tokenValue;
$this->lastUsed = $lastUsed;
}
/**
* {@inheritdoc}
*/
public function getClass(): string
{
return $this->class;
}
/**
* {@inheritdoc}
*/
public function getUsername(): string
{
trigger_deprecation('symfony/security-core', '5.3', 'Method "%s()" is deprecated, use getUserIdentifier() instead.', __METHOD__);
return $this->userIdentifier;
}
public function getUserIdentifier(): string
{
return $this->userIdentifier;
}
/**
* {@inheritdoc}
*/
public function getSeries(): string
{
return $this->series;
}
/**
* {@inheritdoc}
*/
public function getTokenValue(): string
{
return $this->tokenValue;
}
/**
* {@inheritdoc}
*/
public function getLastUsed(): \DateTime
{
return $this->lastUsed;
}
}

View File

@ -0,0 +1,58 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\RememberMe;
/**
* Interface to be implemented by persistent token classes (such as
* Doctrine entities representing a remember-me token).
*
* @method string getUserIdentifier() returns the identifier used to authenticate (e.g. their email address or username)
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface PersistentTokenInterface
{
/**
* Returns the class of the user.
*
* @return string
*/
public function getClass();
/**
* Returns the series.
*
* @return string
*/
public function getSeries();
/**
* Returns the token value.
*
* @return string
*/
public function getTokenValue();
/**
* Returns the time the token was last used.
*
* @return \DateTime
*/
public function getLastUsed();
/**
* @return string
*
* @deprecated since Symfony 5.3, use getUserIdentifier() instead
*/
public function getUsername();
}

View File

@ -0,0 +1,48 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\RememberMe;
use Symfony\Component\Security\Core\Exception\TokenNotFoundException;
/**
* Interface for TokenProviders.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface TokenProviderInterface
{
/**
* Loads the active token for the given series.
*
* @return PersistentTokenInterface
*
* @throws TokenNotFoundException if the token is not found
*/
public function loadTokenBySeries(string $series);
/**
* Deletes all tokens belonging to series.
*/
public function deleteTokenBySeries(string $series);
/**
* Updates the token according to this data.
*
* @throws TokenNotFoundException if the token is not found
*/
public function updateToken(string $series, string $tokenValue, \DateTime $lastUsed);
/**
* Creates a new token.
*/
public function createNewToken(PersistentTokenInterface $token);
}

View File

@ -0,0 +1,32 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\RememberMe;
/**
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
interface TokenVerifierInterface
{
/**
* Verifies that the given $token is valid.
*
* This lets you override the token check logic to for example accept slightly outdated tokens.
*
* Do not forget to implement token comparisons using hash_equals for a secure implementation.
*/
public function verifyToken(PersistentTokenInterface $token, string $tokenValue): bool;
/**
* Updates an existing token with a new token value and lastUsed time.
*/
public function updateExistingToken(PersistentTokenInterface $token, string $tokenValue, \DateTimeInterface $lastUsed): void;
}

View File

@ -0,0 +1,332 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\Token;
use Symfony\Component\Security\Core\User\EquatableInterface;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* Base class for Token instances.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
abstract class AbstractToken implements TokenInterface
{
private $user;
private $roleNames = [];
private $authenticated = false;
private $attributes = [];
/**
* @param string[] $roles An array of roles
*
* @throws \InvalidArgumentException
*/
public function __construct(array $roles = [])
{
foreach ($roles as $role) {
$this->roleNames[] = $role;
}
}
/**
* {@inheritdoc}
*/
public function getRoleNames(): array
{
return $this->roleNames;
}
/**
* {@inheritdoc}
*/
public function getUsername(/* $legacy = true */)
{
if (1 === \func_num_args() && false === func_get_arg(0)) {
return null;
}
trigger_deprecation('symfony/security-core', '5.3', 'Method "%s()" is deprecated, use getUserIdentifier() instead.', __METHOD__);
if ($this->user instanceof UserInterface) {
return method_exists($this->user, 'getUserIdentifier') ? $this->user->getUserIdentifier() : $this->user->getUsername();
}
return (string) $this->user;
}
/**
* {@inheritdoc}
*/
public function getUserIdentifier(): string
{
// method returns "null" in non-legacy mode if not overridden
$username = $this->getUsername(false);
if (null !== $username) {
trigger_deprecation('symfony/security-core', '5.3', 'Method "%s::getUsername()" is deprecated, override "getUserIdentifier()" instead.', get_debug_type($this));
}
if ($this->user instanceof UserInterface) {
// @deprecated since Symfony 5.3, change to $user->getUserIdentifier() in 6.0
return method_exists($this->user, 'getUserIdentifier') ? $this->user->getUserIdentifier() : $this->user->getUsername();
}
return (string) $this->user;
}
/**
* {@inheritdoc}
*/
public function getUser()
{
return $this->user;
}
/**
* {@inheritdoc}
*/
public function setUser($user)
{
if (!($user instanceof UserInterface || (\is_object($user) && method_exists($user, '__toString')) || \is_string($user))) {
throw new \InvalidArgumentException('$user must be an instanceof UserInterface, an object implementing a __toString method, or a primitive string.');
}
if (!$user instanceof UserInterface) {
trigger_deprecation('symfony/security-core', '5.4', 'Using an object that is not an instance of "%s" as $user in "%s" is deprecated.', UserInterface::class, static::class);
}
// @deprecated since Symfony 5.4, remove the whole block if/elseif/else block in 6.0
if (1 < \func_num_args() && !func_get_arg(1)) {
// ContextListener checks if the user has changed on its own and calls `setAuthenticated()` subsequently,
// avoid doing the same checks twice
$changed = false;
} elseif (null === $this->user) {
$changed = false;
} elseif ($this->user instanceof UserInterface) {
if (!$user instanceof UserInterface) {
$changed = true;
} else {
$changed = $this->hasUserChanged($user);
}
} elseif ($user instanceof UserInterface) {
$changed = true;
} else {
$changed = (string) $this->user !== (string) $user;
}
// @deprecated since Symfony 5.4
if ($changed) {
$this->setAuthenticated(false, false);
}
$this->user = $user;
}
/**
* {@inheritdoc}
*
* @deprecated since Symfony 5.4
*/
public function isAuthenticated()
{
if (1 > \func_num_args() || func_get_arg(0)) {
trigger_deprecation('symfony/security-core', '5.4', 'Method "%s()" is deprecated, return null from "getUser()" instead when a token is not authenticated.', __METHOD__);
}
return $this->authenticated;
}
/**
* {@inheritdoc}
*/
public function setAuthenticated(bool $authenticated)
{
if (2 > \func_num_args() || func_get_arg(1)) {
trigger_deprecation('symfony/security-core', '5.4', 'Method "%s()" is deprecated', __METHOD__);
}
$this->authenticated = $authenticated;
}
/**
* {@inheritdoc}
*/
public function eraseCredentials()
{
if ($this->getUser() instanceof UserInterface) {
$this->getUser()->eraseCredentials();
}
}
/**
* Returns all the necessary state of the object for serialization purposes.
*
* There is no need to serialize any entry, they should be returned as-is.
* If you extend this method, keep in mind you MUST guarantee parent data is present in the state.
* Here is an example of how to extend this method:
* <code>
* public function __serialize(): array
* {
* return [$this->childAttribute, parent::__serialize()];
* }
* </code>
*
* @see __unserialize()
*/
public function __serialize(): array
{
return [$this->user, $this->authenticated, null, $this->attributes, $this->roleNames];
}
/**
* Restores the object state from an array given by __serialize().
*
* There is no need to unserialize any entry in $data, they are already ready-to-use.
* If you extend this method, keep in mind you MUST pass the parent data to its respective class.
* Here is an example of how to extend this method:
* <code>
* public function __unserialize(array $data): void
* {
* [$this->childAttribute, $parentData] = $data;
* parent::__unserialize($parentData);
* }
* </code>
*
* @see __serialize()
*/
public function __unserialize(array $data): void
{
[$this->user, $this->authenticated, , $this->attributes, $this->roleNames] = $data;
}
/**
* {@inheritdoc}
*/
public function getAttributes()
{
return $this->attributes;
}
/**
* {@inheritdoc}
*/
public function setAttributes(array $attributes)
{
$this->attributes = $attributes;
}
/**
* {@inheritdoc}
*/
public function hasAttribute(string $name)
{
return \array_key_exists($name, $this->attributes);
}
/**
* {@inheritdoc}
*/
public function getAttribute(string $name)
{
if (!\array_key_exists($name, $this->attributes)) {
throw new \InvalidArgumentException(sprintf('This token has no "%s" attribute.', $name));
}
return $this->attributes[$name];
}
/**
* {@inheritdoc}
*/
public function setAttribute(string $name, $value)
{
$this->attributes[$name] = $value;
}
/**
* {@inheritdoc}
*/
public function __toString()
{
$class = static::class;
$class = substr($class, strrpos($class, '\\') + 1);
$roles = [];
foreach ($this->roleNames as $role) {
$roles[] = $role;
}
return sprintf('%s(user="%s", authenticated=%s, roles="%s")', $class, $this->getUserIdentifier(), json_encode($this->authenticated), implode(', ', $roles));
}
/**
* @internal
*/
final public function serialize(): string
{
return serialize($this->__serialize());
}
/**
* @internal
*/
final public function unserialize($serialized)
{
$this->__unserialize(\is_array($serialized) ? $serialized : unserialize($serialized));
}
/**
* @deprecated since Symfony 5.4
*/
private function hasUserChanged(UserInterface $user): bool
{
if (!($this->user instanceof UserInterface)) {
throw new \BadMethodCallException('Method "hasUserChanged" should be called when current user class is instance of "UserInterface".');
}
if ($this->user instanceof EquatableInterface) {
return !(bool) $this->user->isEqualTo($user);
}
// @deprecated since Symfony 5.3, check for PasswordAuthenticatedUserInterface on both user objects before comparing passwords
if ($this->user->getPassword() !== $user->getPassword()) {
return true;
}
// @deprecated since Symfony 5.3, check for LegacyPasswordAuthenticatedUserInterface on both user objects before comparing salts
if ($this->user->getSalt() !== $user->getSalt()) {
return true;
}
$userRoles = array_map('strval', (array) $user->getRoles());
if ($this instanceof SwitchUserToken) {
$userRoles[] = 'ROLE_PREVIOUS_ADMIN';
}
if (\count($userRoles) !== \count($this->getRoleNames()) || \count($userRoles) !== \count(array_intersect($userRoles, $this->getRoleNames()))) {
return true;
}
// @deprecated since Symfony 5.3, drop getUsername() in 6.0
$userIdentifier = function ($user) {
return method_exists($user, 'getUserIdentifier') ? $user->getUserIdentifier() : $user->getUsername();
};
if ($userIdentifier($this->user) !== $userIdentifier($user)) {
return true;
}
return false;
}
}

View File

@ -0,0 +1,79 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\Token;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* AnonymousToken represents an anonymous token.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since 5.4, anonymous is now represented by the absence of a token
*/
class AnonymousToken extends AbstractToken
{
private $secret;
/**
* @param string $secret A secret used to make sure the token is created by the app and not by a malicious client
* @param string|\Stringable|UserInterface $user
* @param string[] $roles
*/
public function __construct(string $secret, $user, array $roles = [])
{
trigger_deprecation('symfony/security-core', '5.4', 'The "%s" class is deprecated.', __CLASS__);
parent::__construct($roles);
$this->secret = $secret;
$this->setUser($user);
// @deprecated since Symfony 5.4
$this->setAuthenticated(true, false);
}
/**
* {@inheritdoc}
*/
public function getCredentials()
{
return '';
}
/**
* Returns the secret.
*
* @return string
*/
public function getSecret()
{
return $this->secret;
}
/**
* {@inheritdoc}
*/
public function __serialize(): array
{
return [$this->secret, parent::__serialize()];
}
/**
* {@inheritdoc}
*/
public function __unserialize(array $data): void
{
[$this->secret, $parentData] = $data;
$parentData = \is_array($parentData) ? $parentData : unserialize($parentData);
parent::__unserialize($parentData);
}
}

View File

@ -0,0 +1,134 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\Token;
/**
* @author Wouter de Jong <wouter@wouterj.nl>
*/
class NullToken implements TokenInterface
{
public function __toString(): string
{
return '';
}
public function getRoleNames(): array
{
return [];
}
public function getCredentials()
{
return '';
}
public function getUser()
{
return null;
}
public function setUser($user)
{
throw new \BadMethodCallException('Cannot set user on a NullToken.');
}
public function getUsername()
{
trigger_deprecation('symfony/security-core', '5.3', 'Method "%s()" is deprecated, use getUserIdentifier() instead.', __METHOD__);
return '';
}
public function getUserIdentifier(): string
{
return '';
}
/**
* @deprecated since Symfony 5.4
*/
public function isAuthenticated()
{
if (0 === \func_num_args() || func_get_arg(0)) {
trigger_deprecation('symfony/security-core', '5.4', 'Method "%s()" is deprecated, return null from "getUser()" instead when a token is not authenticated.', __METHOD__);
}
return true;
}
/**
* @deprecated since Symfony 5.4
*/
public function setAuthenticated(bool $isAuthenticated)
{
throw new \BadMethodCallException('Cannot change authentication state of NullToken.');
}
public function eraseCredentials()
{
}
public function getAttributes()
{
return [];
}
public function setAttributes(array $attributes)
{
throw new \BadMethodCallException('Cannot set attributes of NullToken.');
}
public function hasAttribute(string $name)
{
return false;
}
public function getAttribute(string $name)
{
return null;
}
public function setAttribute(string $name, $value)
{
throw new \BadMethodCallException('Cannot add attribute to NullToken.');
}
public function __serialize(): array
{
return [];
}
public function __unserialize(array $data): void
{
}
/**
* @return string
*
* @internal in 5.3
* @final in 5.3
*/
public function serialize()
{
return '';
}
/**
* @return void
*
* @internal in 5.3
* @final in 5.3
*/
public function unserialize($serialized)
{
}
}

View File

@ -0,0 +1,114 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\Token;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* PreAuthenticatedToken implements a pre-authenticated token.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class PreAuthenticatedToken extends AbstractToken
{
private $credentials;
private $firewallName;
/**
* @param UserInterface $user
* @param string $firewallName
* @param string[] $roles
*/
public function __construct($user, /*string*/ $firewallName, /*array*/ $roles = [])
{
if (\is_string($roles)) {
trigger_deprecation('symfony/security-core', '5.4', 'Argument $credentials of "%s()" is deprecated.', __METHOD__);
$credentials = $firewallName;
$firewallName = $roles;
$roles = \func_num_args() > 3 ? func_get_arg(3) : [];
}
parent::__construct($roles);
if ('' === $firewallName) {
throw new \InvalidArgumentException('$firewallName must not be empty.');
}
$this->setUser($user);
$this->credentials = $credentials ?? null;
$this->firewallName = $firewallName;
if ($roles) {
$this->setAuthenticated(true, false);
}
}
/**
* Returns the provider key.
*
* @return string The provider key
*
* @deprecated since Symfony 5.2, use getFirewallName() instead
*/
public function getProviderKey()
{
if (1 !== \func_num_args() || true !== func_get_arg(0)) {
trigger_deprecation('symfony/security-core', '5.2', 'Method "%s()" is deprecated, use "getFirewallName()" instead.', __METHOD__);
}
return $this->firewallName;
}
public function getFirewallName(): string
{
return $this->getProviderKey(true);
}
/**
* {@inheritdoc}
*/
public function getCredentials()
{
trigger_deprecation('symfony/security-core', '5.4', 'Method "%s()" is deprecated.', __METHOD__);
return $this->credentials;
}
/**
* {@inheritdoc}
*/
public function eraseCredentials()
{
parent::eraseCredentials();
$this->credentials = null;
}
/**
* {@inheritdoc}
*/
public function __serialize(): array
{
return [$this->credentials, $this->firewallName, parent::__serialize()];
}
/**
* {@inheritdoc}
*/
public function __unserialize(array $data): void
{
[$this->credentials, $this->firewallName, $parentData] = $data;
$parentData = \is_array($parentData) ? $parentData : unserialize($parentData);
parent::__unserialize($parentData);
}
}

View File

@ -0,0 +1,118 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\Token;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* Authentication Token for "Remember-Me".
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class RememberMeToken extends AbstractToken
{
private $secret;
private $firewallName;
/**
* @param string $secret A secret used to make sure the token is created by the app and not by a malicious client
*
* @throws \InvalidArgumentException
*/
public function __construct(UserInterface $user, string $firewallName, string $secret)
{
parent::__construct($user->getRoles());
if (empty($secret)) {
throw new \InvalidArgumentException('$secret must not be empty.');
}
if ('' === $firewallName) {
throw new \InvalidArgumentException('$firewallName must not be empty.');
}
$this->firewallName = $firewallName;
$this->secret = $secret;
$this->setUser($user);
parent::setAuthenticated(true, false);
}
/**
* {@inheritdoc}
*/
public function setAuthenticated(bool $authenticated)
{
if ($authenticated) {
throw new \LogicException('You cannot set this token to authenticated after creation.');
}
parent::setAuthenticated(false, false);
}
/**
* Returns the provider secret.
*
* @return string The provider secret
*
* @deprecated since Symfony 5.2, use getFirewallName() instead
*/
public function getProviderKey()
{
if (1 !== \func_num_args() || true !== func_get_arg(0)) {
trigger_deprecation('symfony/security-core', '5.2', 'Method "%s()" is deprecated, use "getFirewallName()" instead.', __METHOD__);
}
return $this->firewallName;
}
public function getFirewallName(): string
{
return $this->getProviderKey(true);
}
/**
* @return string
*/
public function getSecret()
{
return $this->secret;
}
/**
* {@inheritdoc}
*/
public function getCredentials()
{
trigger_deprecation('symfony/security-core', '5.4', 'Method "%s()" is deprecated.', __METHOD__);
return '';
}
/**
* {@inheritdoc}
*/
public function __serialize(): array
{
return [$this->secret, $this->firewallName, parent::__serialize()];
}
/**
* {@inheritdoc}
*/
public function __unserialize(array $data): void
{
[$this->secret, $this->firewallName, $parentData] = $data;
$parentData = \is_array($parentData) ? $parentData : unserialize($parentData);
parent::__unserialize($parentData);
}
}

View File

@ -0,0 +1,71 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\Token\Storage;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Contracts\Service\ResetInterface;
/**
* TokenStorage contains a TokenInterface.
*
* It gives access to the token representing the current user authentication.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class TokenStorage implements TokenStorageInterface, ResetInterface
{
private $token;
private $initializer;
/**
* {@inheritdoc}
*/
public function getToken()
{
if ($initializer = $this->initializer) {
$this->initializer = null;
$initializer();
}
return $this->token;
}
/**
* {@inheritdoc}
*/
public function setToken(TokenInterface $token = null)
{
if ($token) {
// ensure any initializer is called
$this->getToken();
// @deprecated since Symfony 5.3
if (!method_exists($token, 'getUserIdentifier')) {
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "getUserIdentifier(): string" in token class "%s" is deprecated. This method will replace "getUsername()" in Symfony 6.0.', get_debug_type($token));
}
}
$this->initializer = null;
$this->token = $token;
}
public function setInitializer(?callable $initializer): void
{
$this->initializer = $initializer;
}
public function reset()
{
$this->setToken(null);
}
}

View File

@ -0,0 +1,36 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\Token\Storage;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
* The TokenStorageInterface.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface TokenStorageInterface
{
/**
* Returns the current security token.
*
* @return TokenInterface|null
*/
public function getToken();
/**
* Sets the authentication token.
*
* @param TokenInterface|null $token A TokenInterface token, or null if no further authentication information should be stored
*/
public function setToken(TokenInterface $token = null);
}

View File

@ -0,0 +1,109 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\Token\Storage;
use Psr\Container\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Contracts\Service\ServiceSubscriberInterface;
/**
* A token storage that increments the session usage index when the token is accessed.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
final class UsageTrackingTokenStorage implements TokenStorageInterface, ServiceSubscriberInterface
{
private $storage;
private $container;
private $enableUsageTracking = false;
public function __construct(TokenStorageInterface $storage, ContainerInterface $container)
{
$this->storage = $storage;
$this->container = $container;
}
/**
* {@inheritdoc}
*/
public function getToken(): ?TokenInterface
{
if ($this->shouldTrackUsage()) {
// increments the internal session usage index
$this->getSession()->getMetadataBag();
}
return $this->storage->getToken();
}
/**
* {@inheritdoc}
*/
public function setToken(TokenInterface $token = null): void
{
$this->storage->setToken($token);
if ($token && $this->shouldTrackUsage()) {
// increments the internal session usage index
$this->getSession()->getMetadataBag();
}
}
public function enableUsageTracking(): void
{
$this->enableUsageTracking = true;
}
public function disableUsageTracking(): void
{
$this->enableUsageTracking = false;
}
public static function getSubscribedServices(): array
{
return [
'request_stack' => RequestStack::class,
];
}
private function getSession(): SessionInterface
{
// BC for symfony/security-bundle < 5.3
if ($this->container->has('session')) {
trigger_deprecation('symfony/security-core', '5.3', 'Injecting the "session" in "%s" is deprecated, inject the "request_stack" instead.', __CLASS__);
return $this->container->get('session');
}
return $this->container->get('request_stack')->getSession();
}
private function shouldTrackUsage(): bool
{
if (!$this->enableUsageTracking) {
return false;
}
// BC for symfony/security-bundle < 5.3
if ($this->container->has('session')) {
return true;
}
if (!$this->container->get('request_stack')->getMainRequest()) {
return false;
}
return true;
}
}

View File

@ -0,0 +1,87 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\Token;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* Token representing a user who temporarily impersonates another one.
*
* @author Christian Flothmann <christian.flothmann@sensiolabs.de>
*/
class SwitchUserToken extends UsernamePasswordToken
{
private $originalToken;
private $originatedFromUri;
/**
* @param UserInterface $user
* @param string|null $originatedFromUri The URI where was the user at the switch
*
* @throws \InvalidArgumentException
*/
public function __construct($user, /*string*/ $firewallName, /*array*/ $roles, /*TokenInterface*/ $originalToken, /*string*/ $originatedFromUri = null)
{
if (\is_string($roles)) {
// @deprecated since 5.4, deprecation is triggered by UsernamePasswordToken::__construct()
$credentials = $firewallName;
$firewallName = $roles;
$roles = $originalToken;
$originalToken = $originatedFromUri;
$originatedFromUri = \func_num_args() > 5 ? func_get_arg(5) : null;
parent::__construct($user, $credentials, $firewallName, $roles);
} else {
parent::__construct($user, $firewallName, $roles);
}
if (!$originalToken instanceof TokenInterface) {
throw new \TypeError(sprintf('Argument $originalToken of "%s" must be an instance of "%s", "%s" given.', __METHOD__, TokenInterface::class, get_debug_type($originalToken)));
}
$this->originalToken = $originalToken;
$this->originatedFromUri = $originatedFromUri;
}
public function getOriginalToken(): TokenInterface
{
return $this->originalToken;
}
public function getOriginatedFromUri(): ?string
{
return $this->originatedFromUri;
}
/**
* {@inheritdoc}
*/
public function __serialize(): array
{
return [$this->originalToken, $this->originatedFromUri, parent::__serialize()];
}
/**
* {@inheritdoc}
*/
public function __unserialize(array $data): void
{
if (3 > \count($data)) {
// Support for tokens serialized with version 5.1 or lower of symfony/security-core.
[$this->originalToken, $parentData] = $data;
} else {
[$this->originalToken, $this->originatedFromUri, $parentData] = $data;
}
$parentData = \is_array($parentData) ? $parentData : unserialize($parentData);
parent::__unserialize($parentData);
}
}

View File

@ -0,0 +1,133 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\Token;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* TokenInterface is the interface for the user authentication information.
*
* @method string getUserIdentifier() returns the user identifier used during authentication (e.g. a user's email address or username)
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface TokenInterface extends \Serializable
{
/**
* Returns a string representation of the Token.
*
* This is only to be used for debugging purposes.
*
* @return string
*/
public function __toString();
/**
* Returns the user roles.
*
* @return string[]
*/
public function getRoleNames(): array;
/**
* Returns the user credentials.
*
* @return mixed
*
* @deprecated since Symfony 5.4
*/
public function getCredentials();
/**
* Returns a user representation.
*
* @return UserInterface|null
*
* @see AbstractToken::setUser()
*/
public function getUser();
/**
* Sets the authenticated user in the token.
*
* @param UserInterface $user
*
* @throws \InvalidArgumentException
*/
public function setUser($user);
/**
* Returns whether the user is authenticated or not.
*
* @return bool true if the token has been authenticated, false otherwise
*
* @deprecated since Symfony 5.4, return null from "getUser()" instead when a token is not authenticated
*/
public function isAuthenticated();
/**
* Sets the authenticated flag.
*
* @deprecated since Symfony 5.4
*/
public function setAuthenticated(bool $isAuthenticated);
/**
* Removes sensitive information from the token.
*/
public function eraseCredentials();
/**
* @return array
*/
public function getAttributes();
/**
* @param array $attributes The token attributes
*/
public function setAttributes(array $attributes);
/**
* @return bool
*/
public function hasAttribute(string $name);
/**
* @return mixed
*
* @throws \InvalidArgumentException When attribute doesn't exist for this token
*/
public function getAttribute(string $name);
/**
* @param mixed $value The attribute value
*/
public function setAttribute(string $name, $value);
/**
* Returns all the necessary state of the object for serialization purposes.
*/
public function __serialize(): array;
/**
* Restores the object state from an array given by __serialize().
*/
public function __unserialize(array $data): void;
/**
* @return string
*
* @deprecated since Symfony 5.3, use getUserIdentifier() instead
*/
public function getUsername();
}

View File

@ -0,0 +1,125 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\Token;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* UsernamePasswordToken implements a username and password token.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class UsernamePasswordToken extends AbstractToken
{
private $credentials;
private $firewallName;
/**
* @param UserInterface $user
* @param string[] $roles
*
* @throws \InvalidArgumentException
*/
public function __construct($user, /*string*/ $firewallName, /*array*/ $roles = [])
{
if (\is_string($roles)) {
trigger_deprecation('symfony/security-core', '5.4', 'The $credentials argument of "%s" is deprecated.', static::class.'::__construct');
$credentials = $firewallName;
$firewallName = $roles;
$roles = \func_num_args() > 3 ? func_get_arg(3) : [];
}
parent::__construct($roles);
if ('' === $firewallName) {
throw new \InvalidArgumentException('$firewallName must not be empty.');
}
$this->setUser($user);
$this->credentials = $credentials ?? null;
$this->firewallName = $firewallName;
parent::setAuthenticated(\count($roles) > 0, false);
}
/**
* {@inheritdoc}
*/
public function setAuthenticated(bool $isAuthenticated)
{
if ($isAuthenticated) {
throw new \LogicException('Cannot set this token to trusted after instantiation.');
}
parent::setAuthenticated(false, false);
}
/**
* {@inheritdoc}
*/
public function getCredentials()
{
trigger_deprecation('symfony/security-core', '5.4', 'Method "%s" is deprecated.', __METHOD__);
return $this->credentials;
}
/**
* Returns the provider key.
*
* @return string The provider key
*
* @deprecated since Symfony 5.2, use getFirewallName() instead
*/
public function getProviderKey()
{
if (1 !== \func_num_args() || true !== func_get_arg(0)) {
trigger_deprecation('symfony/security-core', '5.2', 'Method "%s" is deprecated, use "getFirewallName()" instead.', __METHOD__);
}
return $this->firewallName;
}
public function getFirewallName(): string
{
return $this->getProviderKey(true);
}
/**
* {@inheritdoc}
*/
public function eraseCredentials()
{
parent::eraseCredentials();
$this->credentials = null;
}
/**
* {@inheritdoc}
*/
public function __serialize(): array
{
return [$this->credentials, $this->firewallName, parent::__serialize()];
}
/**
* {@inheritdoc}
*/
public function __unserialize(array $data): void
{
[$this->credentials, $this->firewallName, $parentData] = $data;
$parentData = \is_array($parentData) ? $parentData : unserialize($parentData);
parent::__unserialize($parentData);
}
}