diff options
Diffstat (limited to 'Core/Authentication')
21 files changed, 1549 insertions, 0 deletions
diff --git a/Core/Authentication/AuthenticationManagerInterface.php b/Core/Authentication/AuthenticationManagerInterface.php new file mode 100644 index 0000000..280377a --- /dev/null +++ b/Core/Authentication/AuthenticationManagerInterface.php @@ -0,0 +1,35 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien.potencier@symfony-project.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.potencier@symfony-project.com> + */ +interface AuthenticationManagerInterface +{ + /** + * Attempts to authenticates a TokenInterface object. + * + * @param TokenInterface $token The TokenInterface instance to authenticate + * + * @return TokenInterface An authenticated TokenInterface instance + * + * @throws AuthenticationException if the authentication fails + */ + function authenticate(TokenInterface $token); +} diff --git a/Core/Authentication/AuthenticationProviderManager.php b/Core/Authentication/AuthenticationProviderManager.php new file mode 100644 index 0000000..187a81b --- /dev/null +++ b/Core/Authentication/AuthenticationProviderManager.php @@ -0,0 +1,120 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien.potencier@symfony-project.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\Exception\AccountStatusException; +use Symfony\Component\Security\Core\Exception\AuthenticationException; +use Symfony\Component\Security\Core\Exception\ProviderNotFoundException; +use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; + +/** + * AuthenticationProviderManager uses a list of AuthenticationProviderInterface + * instances to authenticate a Token. + * + * @author Fabien Potencier <fabien.potencier@symfony-project.com> + */ +class AuthenticationProviderManager implements AuthenticationManagerInterface +{ + protected $providers; + protected $eraseCredentials; + + /** + * Constructor. + * + * @param AuthenticationProviderInterface[] $providers An array of AuthenticationProviderInterface instances + * @param Boolean $eraseCredentials Whether to erase credentials after authentication or not + */ + public function __construct(array $providers = array(), $eraseCredentials = true) + { + $this->setProviders($providers); + $this->eraseCredentials = (Boolean) $eraseCredentials; + } + + /** + * {@inheritdoc} + */ + public function authenticate(TokenInterface $token) + { + if (!count($this->providers)) { + throw new \LogicException('You must add at least one provider.'); + } + + $lastException = null; + $result = null; + + foreach ($this->providers as $provider) { + if (!$provider->supports($token)) { + continue; + } + + try { + $result = $provider->authenticate($token); + } catch (AccountStatusException $e) { + $e->setExtraInformation($token); + + throw $e; + } catch (AuthenticationException $e) { + $lastException = $e; + } + } + + if (null !== $result) { + if (true === $this->eraseCredentials) { + $result->eraseCredentials(); + } + + return $result; + } + + if (null === $lastException) { + $lastException = new ProviderNotFoundException(sprintf('No Authentication Provider found for token of class "%s".', get_class($token))); + } + + $lastException->setExtraInformation($token); + + throw $lastException; + } + + /** + * Returns the list of current providers. + * + * @return AuthenticationProviderInterface[] An array of AuthenticationProviderInterface instances + */ + public function all() + { + return $this->providers; + } + + /** + * Sets the providers instances. + * + * @param AuthenticationProviderInterface[] $providers An array of AuthenticationProviderInterface instances + */ + public function setProviders(array $providers) + { + $this->providers = array(); + foreach ($providers as $provider) { + $this->add($provider); + } + } + + /** + * Adds a provider. + * + * @param AuthenticationProviderInterface $provider A AuthenticationProviderInterface instance + */ + public function add(AuthenticationProviderInterface $provider) + { + $this->providers[] = $provider; + } +} diff --git a/Core/Authentication/AuthenticationTrustResolver.php b/Core/Authentication/AuthenticationTrustResolver.php new file mode 100644 index 0000000..95b8cb4 --- /dev/null +++ b/Core/Authentication/AuthenticationTrustResolver.php @@ -0,0 +1,75 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien.potencier@symfony-project.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; + +/** + * The default implementation of the authentication trust resolver. + * + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +class AuthenticationTrustResolver implements AuthenticationTrustResolverInterface +{ + protected $anonymousClass; + protected $rememberMeClass; + + /** + * Constructor + * + * @param string $anonymousClass + * @param string $rememberMeClass + * + * @return void + */ + public function __construct($anonymousClass, $rememberMeClass) + { + $this->anonymousClass = $anonymousClass; + $this->rememberMeClass = $rememberMeClass; + } + + /** + * {@inheritDoc} + */ + public function isAnonymous(TokenInterface $token = null) + { + if (null === $token) { + return false; + } + + return $token instanceof $this->anonymousClass; + } + + /** + * {@inheritDoc} + */ + public function isRememberMe(TokenInterface $token = null) + { + if (null === $token) { + return false; + } + + return $token instanceof $this->rememberMeClass; + } + + /** + * {@inheritDoc} + */ + public function isFullFledged(TokenInterface $token = null) + { + if (null === $token) { + return false; + } + + return !$this->isAnonymous($token) && !$this->isRememberMe($token); + } +} diff --git a/Core/Authentication/AuthenticationTrustResolverInterface.php b/Core/Authentication/AuthenticationTrustResolverInterface.php new file mode 100644 index 0000000..1f29465 --- /dev/null +++ b/Core/Authentication/AuthenticationTrustResolverInterface.php @@ -0,0 +1,53 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien.potencier@symfony-project.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> + */ +interface AuthenticationTrustResolverInterface +{ + /** + * Resolves whether the passed token implementation is authenticated + * anonymously. + * + * If null is passed, the method must return false. + * + * @param TokenInterface $token + * + * @return Boolean + */ + function isAnonymous(TokenInterface $token = null); + + /** + * Resolves whether the passed token implementation is authenticated + * using remember-me capabilities. + * + * @param TokenInterface $token + * + * @return Boolean + */ + function isRememberMe(TokenInterface $token = null); + + /** + * Resolves whether the passed token implementation is fully authenticated. + * + * @param TokenInterface $token + * + * @return Boolean + */ + function isFullFledged(TokenInterface $token = null); +} diff --git a/Core/Authentication/EntryPoint/AuthenticationEntryPointInterface.php b/Core/Authentication/EntryPoint/AuthenticationEntryPointInterface.php new file mode 100644 index 0000000..7fd64bf --- /dev/null +++ b/Core/Authentication/EntryPoint/AuthenticationEntryPointInterface.php @@ -0,0 +1,32 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien.potencier@symfony-project.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\EntryPoint; + +use Symfony\Component\Security\Core\Exception\AuthenticationException; +use Symfony\Component\HttpFoundation\Request; + +/** + * AuthenticationEntryPointInterface is the interface used to start the + * authentication scheme. + * + * @author Fabien Potencier <fabien.potencier@symfony-project.com> + */ +interface AuthenticationEntryPointInterface +{ + /** + * Starts the authentication scheme. + * + * @param object $request The request that resulted in an AuthenticationException + * @param AuthenticationException $authException The exception that started the authentication process + */ + function start(Request $request, AuthenticationException $authException = null); +} diff --git a/Core/Authentication/Provider/AnonymousAuthenticationProvider.php b/Core/Authentication/Provider/AnonymousAuthenticationProvider.php new file mode 100644 index 0000000..821e17e --- /dev/null +++ b/Core/Authentication/Provider/AnonymousAuthenticationProvider.php @@ -0,0 +1,60 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien.potencier@symfony-project.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\TokenInterface; +use Symfony\Component\Security\Core\Exception\BadCredentialsException; +use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; + +/** + * AnonymousAuthenticationProvider validates AnonymousToken instances. + * + * @author Fabien Potencier <fabien.potencier@symfony-project.com> + */ +class AnonymousAuthenticationProvider implements AuthenticationProviderInterface +{ + protected $key; + + /** + * Constructor. + * + * @param string $key The key shared with the authentication token + */ + public function __construct($key) + { + $this->key = $key; + } + + /** + * {@inheritdoc} + */ + public function authenticate(TokenInterface $token) + { + if (!$this->supports($token)) { + return null; + } + + if ($this->key != $token->getKey()) { + throw new BadCredentialsException('The Token does not contain the expected key.'); + } + + return $token; + } + + /** + * {@inheritdoc} + */ + public function supports(TokenInterface $token) + { + return $token instanceof AnonymousToken; + } +} diff --git a/Core/Authentication/Provider/AuthenticationProviderInterface.php b/Core/Authentication/Provider/AuthenticationProviderInterface.php new file mode 100644 index 0000000..89d5ed5 --- /dev/null +++ b/Core/Authentication/Provider/AuthenticationProviderInterface.php @@ -0,0 +1,35 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien.potencier@symfony-project.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\TokenInterface; +use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; + +/** + * AuthenticationProviderInterface is the interface for for all authentication + * providers. + * + * Concrete implementations processes specific Token instances. + * + * @author Fabien Potencier <fabien.potencier@symfony-project.com> + */ +interface AuthenticationProviderInterface extends AuthenticationManagerInterface +{ + /** + * Checks whether this provider supports the given token. + * + * @param TokenInterface $token A TokenInterface instance + * + * @return Boolean true if the implementation supports the Token, false otherwise + */ + function supports(TokenInterface $token); +} diff --git a/Core/Authentication/Provider/DaoAuthenticationProvider.php b/Core/Authentication/Provider/DaoAuthenticationProvider.php new file mode 100644 index 0000000..398f586 --- /dev/null +++ b/Core/Authentication/Provider/DaoAuthenticationProvider.php @@ -0,0 +1,95 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien.potencier@symfony-project.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\TokenInterface; +use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; +use Symfony\Component\Security\Core\User\UserProviderInterface; +use Symfony\Component\Security\Core\User\AccountCheckerInterface; +use Symfony\Component\Security\Core\User\AccountInterface; +use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; +use Symfony\Component\Security\Core\Exception\AuthenticationServiceException; +use Symfony\Component\Security\Core\Exception\BadCredentialsException; +use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; + +/** + * DaoAuthenticationProvider uses a UserProviderInterface to retrieve the user + * for a UsernamePasswordToken. + * + * @author Fabien Potencier <fabien.potencier@symfony-project.com> + */ +class DaoAuthenticationProvider extends UserAuthenticationProvider +{ + protected $encoderFactory; + protected $userProvider; + + /** + * Constructor. + * + * @param UserProviderInterface $userProvider A UserProviderInterface instance + * @param AccountCheckerInterface $accountChecker An AccountCheckerInterface instance + * @param EncoderFactoryInterface $encoderFactory A EncoderFactoryInterface instance + */ + public function __construct(UserProviderInterface $userProvider, AccountCheckerInterface $accountChecker, $providerKey, EncoderFactoryInterface $encoderFactory, $hideUserNotFoundExceptions = true) + { + parent::__construct($accountChecker, $providerKey, $hideUserNotFoundExceptions); + + $this->encoderFactory = $encoderFactory; + $this->userProvider = $userProvider; + } + + /** + * {@inheritdoc} + */ + protected function checkAuthentication(AccountInterface $account, UsernamePasswordToken $token) + { + $user = $token->getUser(); + if ($user instanceof AccountInterface) { + if ($account->getPassword() !== $user->getPassword()) { + throw new BadCredentialsException('The credentials were changed from another session.'); + } + } else { + if (!$presentedPassword = (string) $token->getCredentials()) { + throw new BadCredentialsException('Bad credentials'); + } + + if (!$this->encoderFactory->getEncoder($account)->isPasswordValid($account->getPassword(), $presentedPassword, $account->getSalt())) { + throw new BadCredentialsException('Bad credentials'); + } + } + } + + /** + * {@inheritdoc} + */ + protected function retrieveUser($username, UsernamePasswordToken $token) + { + $user = $token->getUser(); + if ($user instanceof AccountInterface) { + return $user; + } + + try { + $user = $this->userProvider->loadUserByUsername($username); + + if (!$user instanceof AccountInterface) { + throw new AuthenticationServiceException('The user provider must return an AccountInterface object.'); + } + + return $user; + } catch (UsernameNotFoundException $notFound) { + throw $notFound; + } catch (\Exception $repositoryProblem) { + throw new AuthenticationServiceException($repositoryProblem->getMessage(), $token, 0, $repositoryProblem); + } + } +} diff --git a/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.php b/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.php new file mode 100644 index 0000000..7fda9d4 --- /dev/null +++ b/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.php @@ -0,0 +1,81 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien.potencier@symfony-project.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\User\AccountInterface; +use Symfony\Component\Security\Core\User\UserProviderInterface; +use Symfony\Component\Security\Core\User\AccountCheckerInterface; +use Symfony\Component\Security\Core\Exception\BadCredentialsException; +use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; + +/** + * 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 + * UsernameNotFoundException, for example. + * + * @author Fabien Potencier <fabien.potencier@symfony-project.com> + */ +class PreAuthenticatedAuthenticationProvider implements AuthenticationProviderInterface +{ + protected $userProvider; + protected $accountChecker; + protected $providerKey; + + /** + * Constructor. + * + * @param UserProviderInterface $userProvider A UserProviderInterface instance + * @param AccountCheckerInterface $accountChecker An AccountCheckerInterface instance + */ + public function __construct(UserProviderInterface $userProvider, AccountCheckerInterface $accountChecker, $providerKey) + { + $this->userProvider = $userProvider; + $this->accountChecker = $accountChecker; + $this->providerKey = $providerKey; + } + + /** + * {@inheritdoc} + */ + public function authenticate(TokenInterface $token) + { + if (!$this->supports($token)) { + return null; + } + + if (!$user = $token->getUser()) { + throw new BadCredentialsException('No pre-authenticated principal found in request.'); + } +/* + if (null === $token->getCredentials()) { + throw new BadCredentialsException('No pre-authenticated credentials found in request.'); + } +*/ + $user = $this->userProvider->loadUserByUsername($user); + + $this->accountChecker->checkPostAuth($user); + + return new PreAuthenticatedToken($user, $token->getCredentials(), $user->getRoles()); + } + + /** + * {@inheritdoc} + */ + public function supports(TokenInterface $token) + { + return $token instanceof PreAuthenticatedToken && $this->providerKey === $token->getProviderKey(); + } +} diff --git a/Core/Authentication/Provider/RememberMeAuthenticationProvider.php b/Core/Authentication/Provider/RememberMeAuthenticationProvider.php new file mode 100644 index 0000000..95ee588 --- /dev/null +++ b/Core/Authentication/Provider/RememberMeAuthenticationProvider.php @@ -0,0 +1,45 @@ +<?php +namespace Symfony\Component\Security\Core\Authentication\Provider; + +use Symfony\Component\Security\Core\User\AccountCheckerInterface; +use Symfony\Component\Security\Core\User\AccountInterface; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken; +use Symfony\Component\Security\Core\Exception\BadCredentialsException; + +class RememberMeAuthenticationProvider implements AuthenticationProviderInterface +{ + protected $accountChecker; + protected $key; + protected $providerKey; + + public function __construct(AccountCheckerInterface $accountChecker, $key, $providerKey) + { + $this->accountChecker = $accountChecker; + $this->key = $key; + $this->providerKey = $providerKey; + } + + public function authenticate(TokenInterface $token) + { + if (!$this->supports($token)) { + return; + } + + if ($this->key !== $token->getKey()) { + throw new BadCredentialsException('The presented key does not match.'); + } + + $user = $token->getUser(); + $this->accountChecker->checkPreAuth($user); + $this->accountChecker->checkPostAuth($user); + $token->setAuthenticated(true); + + return $token; + } + + public function supports(TokenInterface $token) + { + return $token instanceof RememberMeToken && $token->getProviderKey() === $this->providerKey; + } +}
\ No newline at end of file diff --git a/Core/Authentication/Provider/UserAuthenticationProvider.php b/Core/Authentication/Provider/UserAuthenticationProvider.php new file mode 100644 index 0000000..6947de3 --- /dev/null +++ b/Core/Authentication/Provider/UserAuthenticationProvider.php @@ -0,0 +1,113 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien.potencier@symfony-project.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\User\AccountInterface; +use Symfony\Component\Security\Core\User\AccountCheckerInterface; +use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; +use Symfony\Component\Security\Core\Exception\AuthenticationException; +use Symfony\Component\Security\Core\Exception\BadCredentialsException; +use Symfony\Component\Security\Core\Exception\AuthenticationServiceException; +use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; + +/** + * UserProviderInterface retrieves users for UsernamePasswordToken tokens. + * + * @author Fabien Potencier <fabien.potencier@symfony-project.com> + */ +abstract class UserAuthenticationProvider implements AuthenticationProviderInterface +{ + protected $hideUserNotFoundExceptions; + protected $accountChecker; + protected $providerKey; + + /** + * Constructor. + * + * @param AccountCheckerInterface $accountChecker An AccountCheckerInterface interface + * @param Boolean $hideUserNotFoundExceptions Whether to hide user not found exception or not + */ + public function __construct(AccountCheckerInterface $accountChecker, $providerKey, $hideUserNotFoundExceptions = true) + { + if (empty($providerKey)) { + throw new \InvalidArgumentException('$providerKey must not be empty.'); + } + + $this->accountChecker = $accountChecker; + $this->providerKey = $providerKey; + $this->hideUserNotFoundExceptions = $hideUserNotFoundExceptions; + } + + /** + * {@inheritdoc} + */ + public function authenticate(TokenInterface $token) + { + if (!$this->supports($token)) { + return null; + } + + $username = null === $token->getUser() ? 'NONE_PROVIDED' : (string) $token; + + try { + $user = $this->retrieveUser($username, $token); + + if (!$user instanceof AccountInterface) { + throw new AuthenticationServiceException('retrieveUser() must return an AccountInterface.'); + } + + $this->accountChecker->checkPreAuth($user); + $this->checkAuthentication($user, $token); + $this->accountChecker->checkPostAuth($user); + + return new UsernamePasswordToken($user, $token->getCredentials(), $this->providerKey, $user->getRoles()); + } catch (UsernameNotFoundException $notFound) { + if ($this->hideUserNotFoundExceptions) { + throw new BadCredentialsException('Bad credentials', 0, $notFound); + } + + throw $notFound; + } + } + + /** + * {@inheritdoc} + */ + public function supports(TokenInterface $token) + { + return $token instanceof UsernamePasswordToken && $this->providerKey === $token->getProviderKey(); + } + + /** + * Retrieves the user from an implementation-specific location. + * + * @param string $username The username to retrieve + * @param UsernamePasswordToken $token The Token + * + * @return array The user + * + * @throws AuthenticationException if the credentials could not be validated + */ + abstract protected function retrieveUser($username, UsernamePasswordToken $token); + + /** + * Does additional checks on the user and token (like validating the + * credentials). + * + * @param AccountInterface $account The retrieved AccountInterface instance + * @param UsernamePasswordToken $token The UsernamePasswordToken token to be authenticated + * + * @throws AuthenticationException if the credentials could not be validated + */ + abstract protected function checkAuthentication(AccountInterface $account, UsernamePasswordToken $token); +} diff --git a/Core/Authentication/RememberMe/InMemoryTokenProvider.php b/Core/Authentication/RememberMe/InMemoryTokenProvider.php new file mode 100644 index 0000000..80c10d1 --- /dev/null +++ b/Core/Authentication/RememberMe/InMemoryTokenProvider.php @@ -0,0 +1,50 @@ +<?php + +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 +{ + protected $tokens = array(); + + public function loadTokenBySeries($series) + { + if (!isset($this->tokens[$series])) { + throw new TokenNotFoundException('No token found.'); + } + + return $this->tokens[$series]; + } + + public function updateToken($series, $tokenValue, \DateTime $lastUsed) + { + if (!isset($this->tokens[$series])) { + throw new TokenNotFoundException('No token found.'); + } + + $token = new PersistentToken( + $this->tokens[$series]->getClass(), + $this->tokens[$series]->getUsername(), + $series, + $tokenValue, + $lastUsed + ); + $this->tokens[$series] = $token; + } + + public function deleteTokenBySeries($series) + { + unset($this->tokens[$series]); + } + + public function createNewToken(PersistentTokenInterface $token) + { + $this->tokens[$token->getSeries()] = $token; + } +}
\ No newline at end of file diff --git a/Core/Authentication/RememberMe/PersistentToken.php b/Core/Authentication/RememberMe/PersistentToken.php new file mode 100644 index 0000000..9b9bb93 --- /dev/null +++ b/Core/Authentication/RememberMe/PersistentToken.php @@ -0,0 +1,107 @@ +<?php + +namespace Symfony\Component\Security\Core\Authentication\RememberMe; + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien.potencier@symfony-project.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * This class is only used by PersistentTokenRememberMeServices internally. + * + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +final class PersistentToken implements PersistentTokenInterface +{ + private $class; + private $username; + private $series; + private $tokenValue; + private $lastUsed; + + /** + * Constructor + * + * @param string $class + * @param string $username + * @param string $series + * @param string $tokenValue + * @param DateTime $lastUsed + */ + public function __construct($class, $username, $series, $tokenValue, \DateTime $lastUsed) + { + if (empty($class)) { + throw new \InvalidArgumentException('$class must not be empty.'); + } + if (empty($username)) { + throw new \InvalidArgumentException('$username 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->username = $username; + $this->series = $series; + $this->tokenValue = $tokenValue; + $this->lastUsed = $lastUsed; + } + + /** + * Returns the class of the user + * + * @return string + */ + public function getClass() + { + return $this->class; + } + + /** + * Returns the username + * + * @return string + */ + public function getUsername() + { + return $this->username; + } + + /** + * Returns the series + * + * @return string + */ + public function getSeries() + { + return $this->series; + } + + /** + * Returns the token value + * + * @return string + */ + public function getTokenValue() + { + return $this->tokenValue; + } + + /** + * Returns the time the token was last used + * + * @return DateTime + */ + public function getLastUsed() + { + return $this->lastUsed; + } +}
\ No newline at end of file diff --git a/Core/Authentication/RememberMe/PersistentTokenInterface.php b/Core/Authentication/RememberMe/PersistentTokenInterface.php new file mode 100644 index 0000000..3696d1f --- /dev/null +++ b/Core/Authentication/RememberMe/PersistentTokenInterface.php @@ -0,0 +1,45 @@ +<?php + +namespace Symfony\Component\Security\Core\Authentication\RememberMe; + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien.potencier@symfony-project.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Interface to be implemented by persistent token classes (such as + * Doctrine entities representing a remember-me token) + * + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +interface PersistentTokenInterface +{ + /** + * Returns the username + * @return string + */ + function getUsername(); + + /** + * Returns the series + * @return string + */ + function getSeries(); + + /** + * Returns the token value + * @return string + */ + function getTokenValue(); + + /** + * Returns the last time the cookie was used + * @return \DateTime + */ + function getLastUsed(); +}
\ No newline at end of file diff --git a/Core/Authentication/RememberMe/TokenProviderInterface.php b/Core/Authentication/RememberMe/TokenProviderInterface.php new file mode 100644 index 0000000..e77e68a --- /dev/null +++ b/Core/Authentication/RememberMe/TokenProviderInterface.php @@ -0,0 +1,51 @@ +<?php + +namespace Symfony\Component\Security\Core\Authentication\RememberMe; + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien.potencier@symfony-project.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Interface for TokenProviders + * + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +interface TokenProviderInterface +{ + /** + * Loads the active token for the given series + * + * @throws TokenNotFoundException if the token is not found + * + * @param string $series + * @return PersistentTokenInterface + */ + function loadTokenBySeries($series); + + /** + * Deletes all tokens belonging to series + * @param string $series + */ + function deleteTokenBySeries($series); + + /** + * Updates the token according to this data + * + * @param string $series + * @param string $tokenValue + * @param DateTime $lastUsed + */ + function updateToken($series, $tokenValue, \DateTime $lastUsed); + + /** + * Creates a new token + * @param PersistentTokenInterface $token + */ + function createNewToken(PersistentTokenInterface $token); +}
\ No newline at end of file diff --git a/Core/Authentication/Token/AnonymousToken.php b/Core/Authentication/Token/AnonymousToken.php new file mode 100644 index 0000000..7735925 --- /dev/null +++ b/Core/Authentication/Token/AnonymousToken.php @@ -0,0 +1,58 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien.potencier@symfony-project.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; + +/** + * AnonymousToken represents an anonymous token. + * + * @author Fabien Potencier <fabien.potencier@symfony-project.com> + */ +class AnonymousToken extends Token +{ + protected $user; + protected $key; + + /** + * Constructor. + * + * @param string $key The key shared with the authentication provider + * @param string $user The user + * @param Role[] $roles An array of roles + */ + public function __construct($key, $user, array $roles = array()) + { + parent::__construct($roles); + + $this->key = $key; + $this->user = $user; + + parent::setAuthenticated(true); + } + + /** + * {@inheritdoc} + */ + public function getCredentials() + { + return ''; + } + + /** + * Returns the key. + * + * @return string The Key + */ + public function getKey() + { + return $this->key; + } +} diff --git a/Core/Authentication/Token/PreAuthenticatedToken.php b/Core/Authentication/Token/PreAuthenticatedToken.php new file mode 100644 index 0000000..c84ea10 --- /dev/null +++ b/Core/Authentication/Token/PreAuthenticatedToken.php @@ -0,0 +1,52 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien.potencier@symfony-project.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; + +/** + * PreAuthenticatedToken implements a pre-authenticated token. + * + * @author Fabien Potencier <fabien.potencier@symfony-project.com> + */ +class PreAuthenticatedToken extends Token +{ + protected $providerKey; + + /** + * Constructor. + */ + public function __construct($user, $credentials, $providerKey, array $roles = null) + { + parent::__construct(null === $roles ? array() : $roles); + if (null !== $roles) { + $this->setAuthenticated(true); + } + + $this->user = $user; + $this->credentials = $credentials; + $this->providerKey = $providerKey; + } + + public function getProviderKey() + { + return $this->providerKey; + } + + /** + * {@inheritdoc} + */ + public function eraseCredentials() + { + parent::eraseCredentials(); + + $this->credentials = null; + } +} diff --git a/Core/Authentication/Token/RememberMeToken.php b/Core/Authentication/Token/RememberMeToken.php new file mode 100644 index 0000000..81bf1e0 --- /dev/null +++ b/Core/Authentication/Token/RememberMeToken.php @@ -0,0 +1,75 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien.potencier@symfony-project.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\Authentication\RememberMe\PersistentTokenInterface; +use Symfony\Component\Security\Core\User\AccountInterface; + +/** + * Base class for "Remember Me" tokens + * + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +class RememberMeToken extends Token +{ + protected $key; + protected $providerKey; + + /** + * The persistent token which resulted in this authentication token. + * + * @var PersistentTokenInterface + */ + protected $persistentToken; + + /** + * Constructor. + * + * @param string $username + * @param string $key + */ + public function __construct(AccountInterface $user, $providerKey, $key) { + parent::__construct($user->getRoles()); + + if (empty($key)) { + throw new \InvalidArgumentException('$key must not be empty.'); + } + if (empty($providerKey)) { + throw new \InvalidArgumentException('$providerKey must not be empty.'); + } + + $this->setUser($user); + $this->providerKey = $providerKey; + $this->key = $key; + $this->setAuthenticated(true); + } + + public function getProviderKey() + { + return $this->providerKey; + } + + public function getKey() + { + return $this->key; + } + + public function getPersistentToken() + { + return $this->persistentToken; + } + + public function setPersistentToken(PersistentTokenInterface $persistentToken) + { + $this->persistentToken = $persistentToken; + } +}
\ No newline at end of file diff --git a/Core/Authentication/Token/Token.php b/Core/Authentication/Token/Token.php new file mode 100644 index 0000000..d41bab5 --- /dev/null +++ b/Core/Authentication/Token/Token.php @@ -0,0 +1,199 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien.potencier@symfony-project.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\Role\RoleInterface; +use Symfony\Component\Security\Core\Role\Role; +use Symfony\Component\Security\Core\User\AccountInterface; + +/** + * Base class for Token instances. + * + * @author Fabien Potencier <fabien.potencier@symfony-project.com> + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +abstract class Token implements TokenInterface +{ + protected $roles; + protected $authenticated; + protected $user; + protected $credentials; + protected $immutable; + + /** + * Constructor. + * + * @param Role[] $roles An array of roles + */ + public function __construct(array $roles = array()) + { + $this->setRoles($roles); + $this->authenticated = false; + $this->immutable = false; + } + + /** + * Adds a Role to the token. + * + * @param RoleInterface $role A RoleInterface instance + */ + public function addRole(RoleInterface $role) + { + if ($this->immutable) { + throw new \LogicException('This token is considered immutable.'); + } + + $this->roles[] = $role; + } + + /** + * {@inheritdoc} + */ + public function getRoles() + { + return $this->roles; + } + + /** + * {@inheritDoc} + */ + public function setRoles(array $roles) + { + $this->roles = array(); + + foreach ($roles as $role) { + if (is_string($role)) { + $role = new Role($role); + } + + $this->addRole($role); + } + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + if (!is_object($this->user)) { + return (string) $this->user; + } elseif ($this->user instanceof AccountInterface) { + return $this->user->getUsername(); + } else { + return 'n/a'; + } + } + + /** + * {@inheritdoc} + */ + public function isAuthenticated() + { + return $this->authenticated; + } + + /** + * {@inheritdoc} + */ + public function setAuthenticated($authenticated) + { + if ($this->immutable) { + throw new \LogicException('This token is considered immutable.'); + } + + $this->authenticated = (Boolean) $authenticated; + } + + /** + * {@inheritdoc} + */ + public function getCredentials() + { + return $this->credentials; + } + + /** + * {@inheritdoc} + */ + public function getUser() + { + return $this->user; + } + + /** + * {@inheritDoc} + */ + public function setUser($user) + { + if ($this->immutable) { + throw new \LogicException('This token is considered immutable.'); + } + + if (!is_string($user) && !is_object($user)) { + throw new \InvalidArgumentException('$user must be an object, or a primitive string.'); + } else if (is_object($user) && !method_exists($user, '__toString')) { + throw new \InvalidArgumentException('If $user is an object, it must implement __toString().'); + } + + $this->user = $user; + } + + /** + * {@inheritdoc} + */ + public function eraseCredentials() + { + if ($this->immutable) { + throw new \LogicException('This token is considered immutable.'); + } + + if ($this->getCredentials() instanceof AccountInterface) { + $this->getCredentials()->eraseCredentials(); + } + + if ($this->getUser() instanceof AccountInterface) { + $this->getUser()->eraseCredentials(); + } + } + + /** + * {@inheritdoc} + */ + public function isImmutable() + { + return $this->immutable; + } + + /** + * {@inheritdoc} + */ + public function setImmutable() + { + $this->immutable = true; + } + + /** + * {@inheritdoc} + */ + public function serialize() + { + return serialize(array($this->user, $this->credentials, $this->authenticated, $this->roles, $this->immutable)); + } + + /** + * {@inheritdoc} + */ + public function unserialize($serialized) + { + list($this->user, $this->credentials, $this->authenticated, $this->roles, $this->immutable) = unserialize($serialized); + } +} diff --git a/Core/Authentication/Token/TokenInterface.php b/Core/Authentication/Token/TokenInterface.php new file mode 100644 index 0000000..b6ac31c --- /dev/null +++ b/Core/Authentication/Token/TokenInterface.php @@ -0,0 +1,102 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien.potencier@symfony-project.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\AccountInterface; + +/** + * TokenInterface is the interface for the user authentication information. + * + * @author Fabien Potencier <fabien.potencier@symfony-project.com> + */ +interface TokenInterface extends \Serializable +{ + /** + * Returns a string representation of the token. + * + * @return string A string representation + */ + function __toString(); + + /** + * Returns the user roles. + * + * @return Role[] An array of Role instances. + */ + function getRoles(); + + /** + * Sets the user's roles + * + * @param array $roles + * @return void + */ + function setRoles(array $roles); + + /** + * Returns the user credentials. + * + * @return mixed The user credentials + */ + function getCredentials(); + + /** + * Returns a user representation. + * + * @return mixed either returns an object which implements __toString(), or + * a primitive string is returned. + */ + function getUser(); + + /** + * Sets the user. + * + * @param mixed $user can either be an object which implements __toString(), or + * only a primitive string + */ + function setUser($user); + + /** + * Checks if the user is authenticated or not. + * + * @return Boolean true if the token has been authenticated, false otherwise + */ + function isAuthenticated(); + + /** + * Sets the authenticated flag. + * + * @param Boolean $isAuthenticated The authenticated flag + */ + function setAuthenticated($isAuthenticated); + + /** + * Whether this token is considered immutable + * + * @return Boolean + */ + function isImmutable(); + + /** + * Marks this token as immutable. This change cannot be reversed. + * + * You'll need to create a new token if you want a mutable token again. + * + * @return void + */ + function setImmutable(); + + /** + * Removes sensitive information from the token. + */ + function eraseCredentials(); +} diff --git a/Core/Authentication/Token/UsernamePasswordToken.php b/Core/Authentication/Token/UsernamePasswordToken.php new file mode 100644 index 0000000..a61acd4 --- /dev/null +++ b/Core/Authentication/Token/UsernamePasswordToken.php @@ -0,0 +1,66 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien.potencier@symfony-project.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; + +/** + * UsernamePasswordToken implements a username and password token. + * + * @author Fabien Potencier <fabien.potencier@symfony-project.com> + */ +class UsernamePasswordToken extends Token +{ + protected $providerKey; + + /** + * Constructor. + * + * @param string $user The username (like a nickname, email address, etc.) + * @param string $credentials This usually is the password of the user + */ + public function __construct($user, $credentials, $providerKey, array $roles = array()) + { + parent::__construct($roles); + + $this->setUser($user); + $this->credentials = $credentials; + $this->providerKey = $providerKey; + + parent::setAuthenticated((Boolean) count($roles)); + } + + public function getProviderKey() + { + return $this->providerKey; + } + + /** + * {@inheritdoc} + */ + public function setAuthenticated($isAuthenticated) + { + if ($isAuthenticated) { + throw new \LogicException('Cannot set this token to trusted after instantiation.'); + } + + parent::setAuthenticated(false); + } + + /** + * {@inheritdoc} + */ + public function eraseCredentials() + { + parent::eraseCredentials(); + + $this->credentials = null; + } +} |