Actualización

This commit is contained in:
Xes
2025-04-10 12:24:57 +02:00
parent 8969cc929d
commit 45420b6f0d
39760 changed files with 4303286 additions and 0 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>
*/
interface AuthenticationManagerInterface
{
/**
* Attempts to authenticate a TokenInterface object.
*
* @param TokenInterface $token The TokenInterface instance to authenticate
*
* @return TokenInterface An authenticated TokenInterface instance, never null
*
* @throws AuthenticationException if the authentication fails
*/
public function authenticate(TokenInterface $token);
}

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;
use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent;
use Symfony\Component\Security\Core\Event\AuthenticationEvent;
use Symfony\Component\Security\Core\AuthenticationEvents;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
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@symfony.com>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class AuthenticationProviderManager implements AuthenticationManagerInterface
{
private $providers;
private $eraseCredentials;
private $eventDispatcher;
/**
* Constructor.
*
* @param AuthenticationProviderInterface[] $providers An array of AuthenticationProviderInterface instances
* @param bool $eraseCredentials Whether to erase credentials after authentication or not
*
* @throws \InvalidArgumentException
*/
public function __construct(array $providers, $eraseCredentials = true)
{
if (!$providers) {
throw new \InvalidArgumentException('You must at least add one authentication provider.');
}
foreach ($providers as $provider) {
if (!$provider instanceof AuthenticationProviderInterface) {
throw new \InvalidArgumentException(sprintf('Provider "%s" must implement the AuthenticationProviderInterface.', get_class($provider)));
}
}
$this->providers = $providers;
$this->eraseCredentials = (bool) $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->supports($token)) {
continue;
}
try {
$result = $provider->authenticate($token);
if (null !== $result) {
break;
}
} catch (AccountStatusException $e) {
$lastException = $e;
break;
} catch (AuthenticationException $e) {
$lastException = $e;
}
}
if (null !== $result) {
if (true === $this->eraseCredentials) {
$result->eraseCredentials();
}
if (null !== $this->eventDispatcher) {
$this->eventDispatcher->dispatch(AuthenticationEvents::AUTHENTICATION_SUCCESS, new AuthenticationEvent($result));
}
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(AuthenticationEvents::AUTHENTICATION_FAILURE, new AuthenticationFailureEvent($token, $lastException));
}
$lastException->setToken($token);
throw $lastException;
}
}

View File

@@ -0,0 +1,73 @@
<?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;
/**
* The default implementation of the authentication trust resolver.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class AuthenticationTrustResolver implements AuthenticationTrustResolverInterface
{
private $anonymousClass;
private $rememberMeClass;
/**
* Constructor.
*
* @param string $anonymousClass
* @param string $rememberMeClass
*/
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);
}
}

View File

@@ -0,0 +1,53 @@
<?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>
*/
interface AuthenticationTrustResolverInterface
{
/**
* Resolves whether the passed token implementation is authenticated
* anonymously.
*
* If null is passed, the method must return false.
*
* @param TokenInterface $token
*
* @return bool
*/
public function isAnonymous(TokenInterface $token = null);
/**
* Resolves whether the passed token implementation is authenticated
* using remember-me capabilities.
*
* @param TokenInterface $token
*
* @return bool
*/
public function isRememberMe(TokenInterface $token = null);
/**
* Resolves whether the passed token implementation is fully authenticated.
*
* @param TokenInterface $token
*
* @return bool
*/
public function isFullFledged(TokenInterface $token = null);
}

View File

@@ -0,0 +1,66 @@
<?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\TokenInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
/**
* AnonymousAuthenticationProvider validates AnonymousToken instances.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class AnonymousAuthenticationProvider implements AuthenticationProviderInterface
{
/**
* Used to determine if the token is created by the application
* instead of a malicious client.
*
* @var string
*/
private $secret;
/**
* Constructor.
*
* @param string $secret The secret shared with the AnonymousToken
*/
public function __construct($secret)
{
$this->secret = $secret;
}
/**
* {@inheritdoc}
*/
public function authenticate(TokenInterface $token)
{
if (!$this->supports($token)) {
return;
}
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,42 @@
<?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\TokenInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
/**
* AuthenticationProviderInterface is the interface for all authentication
* providers.
*
* Concrete implementations processes specific Token instances.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
interface AuthenticationProviderInterface extends AuthenticationManagerInterface
{
/**
* Use this constant for not provided username.
*
* @var string
*/
const USERNAME_NONE_PROVIDED = 'NONE_PROVIDED';
/**
* Checks whether this provider supports the given token.
*
* @param TokenInterface $token A TokenInterface instance
*
* @return bool true if the implementation supports the Token, false otherwise
*/
public function supports(TokenInterface $token);
}

View File

@@ -0,0 +1,99 @@
<?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\Encoder\EncoderFactoryInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
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@symfony.com>
*/
class DaoAuthenticationProvider extends UserAuthenticationProvider
{
private $encoderFactory;
private $userProvider;
/**
* Constructor.
*
* @param UserProviderInterface $userProvider An UserProviderInterface instance
* @param UserCheckerInterface $userChecker An UserCheckerInterface instance
* @param string $providerKey The provider key
* @param EncoderFactoryInterface $encoderFactory An EncoderFactoryInterface instance
* @param bool $hideUserNotFoundExceptions Whether to hide user not found exception or not
*/
public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, $providerKey, EncoderFactoryInterface $encoderFactory, $hideUserNotFoundExceptions = true)
{
parent::__construct($userChecker, $providerKey, $hideUserNotFoundExceptions);
$this->encoderFactory = $encoderFactory;
$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 (!$this->encoderFactory->getEncoder($user)->isPasswordValid($user->getPassword(), $presentedPassword, $user->getSalt())) {
throw new BadCredentialsException('The presented password is invalid.');
}
}
}
/**
* {@inheritdoc}
*/
protected function retrieveUser($username, UsernamePasswordToken $token)
{
$user = $token->getUser();
if ($user instanceof UserInterface) {
return $user;
}
try {
$user = $this->userProvider->loadUserByUsername($username);
if (!$user instanceof UserInterface) {
throw new AuthenticationServiceException('The user provider must return a UserInterface object.');
}
return $user;
} catch (UsernameNotFoundException $e) {
$e->setUsername($username);
throw $e;
} catch (\Exception $e) {
$e = new AuthenticationServiceException($e->getMessage(), 0, $e);
$e->setToken($token);
throw $e;
}
}
}

View File

@@ -0,0 +1,89 @@
<?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\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Ldap\LdapInterface;
use Symfony\Component\Ldap\Exception\ConnectionException;
/**
* 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>
*/
class LdapBindAuthenticationProvider extends UserAuthenticationProvider
{
private $userProvider;
private $ldap;
private $dnString;
/**
* Constructor.
*
* @param UserProviderInterface $userProvider A UserProvider
* @param UserCheckerInterface $userChecker A UserChecker
* @param string $providerKey The provider key
* @param LdapInterface $ldap A Ldap client
* @param string $dnString A string used to create the bind DN
* @param bool $hideUserNotFoundExceptions Whether to hide user not found exception or not
*/
public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, $providerKey, LdapInterface $ldap, $dnString = '{username}', $hideUserNotFoundExceptions = true)
{
parent::__construct($userChecker, $providerKey, $hideUserNotFoundExceptions);
$this->userProvider = $userProvider;
$this->ldap = $ldap;
$this->dnString = $dnString;
}
/**
* {@inheritdoc}
*/
protected function retrieveUser($username, UsernamePasswordToken $token)
{
if (AuthenticationProviderInterface::USERNAME_NONE_PROVIDED === $username) {
throw new UsernameNotFoundException('Username can not be null');
}
return $this->userProvider->loadUserByUsername($username);
}
/**
* {@inheritdoc}
*/
protected function checkAuthentication(UserInterface $user, UsernamePasswordToken $token)
{
$username = $token->getUsername();
$password = $token->getCredentials();
if ('' === $password) {
throw new BadCredentialsException('The presented password must not be empty.');
}
try {
$username = $this->ldap->escape($username, '', LdapInterface::ESCAPE_DN);
$dn = str_replace('{username}', $username, $this->dnString);
$this->ldap->bind($dn, $password);
} catch (ConnectionException $e) {
throw new BadCredentialsException('The presented password is invalid.');
}
}
}

View File

@@ -0,0 +1,80 @@
<?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\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
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@symfony.com>
*/
class PreAuthenticatedAuthenticationProvider implements AuthenticationProviderInterface
{
private $userProvider;
private $userChecker;
private $providerKey;
/**
* Constructor.
*
* @param UserProviderInterface $userProvider An UserProviderInterface instance
* @param UserCheckerInterface $userChecker An UserCheckerInterface instance
* @param string $providerKey The provider key
*/
public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, $providerKey)
{
$this->userProvider = $userProvider;
$this->userChecker = $userChecker;
$this->providerKey = $providerKey;
}
/**
* {@inheritdoc}
*/
public function authenticate(TokenInterface $token)
{
if (!$this->supports($token)) {
return;
}
if (!$user = $token->getUser()) {
throw new BadCredentialsException('No pre-authenticated principal found in request.');
}
$user = $this->userProvider->loadUserByUsername($user);
$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->getProviderKey();
}
}

View File

@@ -0,0 +1,68 @@
<?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\User\UserCheckerInterface;
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
{
private $userChecker;
private $secret;
private $providerKey;
/**
* Constructor.
*
* @param UserCheckerInterface $userChecker An UserCheckerInterface interface
* @param string $secret A secret
* @param string $providerKey A provider secret
*/
public function __construct(UserCheckerInterface $userChecker, $secret, $providerKey)
{
$this->userChecker = $userChecker;
$this->secret = $secret;
$this->providerKey = $providerKey;
}
/**
* {@inheritdoc}
*/
public function authenticate(TokenInterface $token)
{
if (!$this->supports($token)) {
return;
}
if ($this->secret !== $token->getSecret()) {
throw new BadCredentialsException('The presented secret does not match.');
}
$user = $token->getUser();
$this->userChecker->checkPreAuth($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->getProviderKey() === $this->providerKey;
}
}

View File

@@ -0,0 +1,50 @@
<?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\User\UserProviderInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
/**
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
class SimpleAuthenticationProvider implements AuthenticationProviderInterface
{
private $simpleAuthenticator;
private $userProvider;
private $providerKey;
public function __construct(SimpleAuthenticatorInterface $simpleAuthenticator, UserProviderInterface $userProvider, $providerKey)
{
$this->simpleAuthenticator = $simpleAuthenticator;
$this->userProvider = $userProvider;
$this->providerKey = $providerKey;
}
public function authenticate(TokenInterface $token)
{
$authToken = $this->simpleAuthenticator->authenticateToken($token, $this->userProvider, $this->providerKey);
if ($authToken instanceof TokenInterface) {
return $authToken;
}
throw new AuthenticationException('Simple authenticator failed to return an authenticated token.');
}
public function supports(TokenInterface $token)
{
return $this->simpleAuthenticator->supportsToken($token, $this->providerKey);
}
}

View File

@@ -0,0 +1,155 @@
<?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\User\UserInterface;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
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;
use Symfony\Component\Security\Core\Role\SwitchUserRole;
/**
* UserProviderInterface retrieves users for UsernamePasswordToken tokens.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
abstract class UserAuthenticationProvider implements AuthenticationProviderInterface
{
private $hideUserNotFoundExceptions;
private $userChecker;
private $providerKey;
/**
* Constructor.
*
* @param UserCheckerInterface $userChecker An UserCheckerInterface interface
* @param string $providerKey A provider key
* @param bool $hideUserNotFoundExceptions Whether to hide user not found exception or not
*
* @throws \InvalidArgumentException
*/
public function __construct(UserCheckerInterface $userChecker, $providerKey, $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)) {
return;
}
$username = $token->getUsername();
if ('' === $username || null === $username) {
$username = AuthenticationProviderInterface::USERNAME_NONE_PROVIDED;
}
try {
$user = $this->retrieveUser($username, $token);
} catch (UsernameNotFoundException $e) {
if ($this->hideUserNotFoundExceptions) {
throw new BadCredentialsException('Bad credentials.', 0, $e);
}
$e->setUsername($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 (BadCredentialsException $e) {
if ($this->hideUserNotFoundExceptions) {
throw new BadCredentialsException('Bad credentials.', 0, $e);
}
throw $e;
}
$authenticatedToken = new UsernamePasswordToken($user, $token->getCredentials(), $this->providerKey, $this->getRoles($user, $token));
$authenticatedToken->setAttributes($token->getAttributes());
return $authenticatedToken;
}
/**
* {@inheritdoc}
*/
public function supports(TokenInterface $token)
{
return $token instanceof UsernamePasswordToken && $this->providerKey === $token->getProviderKey();
}
/**
* Retrieves roles from user and appends SwitchUserRole if original token contained one.
*
* @param UserInterface $user The user
* @param TokenInterface $token The token
*
* @return array The user roles
*/
private function getRoles(UserInterface $user, TokenInterface $token)
{
$roles = $user->getRoles();
foreach ($token->getRoles() as $role) {
if ($role instanceof SwitchUserRole) {
$roles[] = $role;
break;
}
}
return $roles;
}
/**
* Retrieves the user from an implementation-specific location.
*
* @param string $username The username to retrieve
* @param UsernamePasswordToken $token The Token
*
* @return UserInterface 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 UserInterface $user The retrieved UserInterface instance
* @param UsernamePasswordToken $token The UsernamePasswordToken token to be authenticated
*
* @throws AuthenticationException if the credentials could not be validated
*/
abstract protected function checkAuthentication(UserInterface $user, UsernamePasswordToken $token);
}

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 = array();
/**
* {@inheritdoc}
*/
public function loadTokenBySeries($series)
{
if (!isset($this->tokens[$series])) {
throw new TokenNotFoundException('No token found.');
}
return $this->tokens[$series];
}
/**
* {@inheritdoc}
*/
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;
}
/**
* {@inheritdoc}
*/
public function deleteTokenBySeries($series)
{
unset($this->tokens[$series]);
}
/**
* {@inheritdoc}
*/
public function createNewToken(PersistentTokenInterface $token)
{
$this->tokens[$token->getSeries()] = $token;
}
}

View File

@@ -0,0 +1,99 @@
<?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 $username;
private $series;
private $tokenValue;
private $lastUsed;
/**
* Constructor.
*
* @param string $class
* @param string $username
* @param string $series
* @param string $tokenValue
* @param \DateTime $lastUsed
*
* @throws \InvalidArgumentException
*/
public function __construct($class, $username, $series, $tokenValue, \DateTime $lastUsed)
{
if (empty($class)) {
throw new \InvalidArgumentException('$class must not be empty.');
}
if ('' === $username || null === $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;
}
/**
* {@inheritdoc}
*/
public function getClass()
{
return $this->class;
}
/**
* {@inheritdoc}
*/
public function getUsername()
{
return $this->username;
}
/**
* {@inheritdoc}
*/
public function getSeries()
{
return $this->series;
}
/**
* {@inheritdoc}
*/
public function getTokenValue()
{
return $this->tokenValue;
}
/**
* {@inheritdoc}
*/
public function getLastUsed()
{
return $this->lastUsed;
}
}

View File

@@ -0,0 +1,56 @@
<?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).
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface PersistentTokenInterface
{
/**
* Returns the class of the user.
*
* @return string
*/
public function getClass();
/**
* Returns the username.
*
* @return string
*/
public function getUsername();
/**
* 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();
}

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;
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.
*
* @param string $series
*
* @return PersistentTokenInterface
*
* @throws TokenNotFoundException if the token is not found
*/
public function loadTokenBySeries($series);
/**
* Deletes all tokens belonging to series.
*
* @param string $series
*/
public function deleteTokenBySeries($series);
/**
* Updates the token according to this data.
*
* @param string $series
* @param string $tokenValue
* @param \DateTime $lastUsed
*
* @throws TokenNotFoundException if the token is not found
*/
public function updateToken($series, $tokenValue, \DateTime $lastUsed);
/**
* Creates a new token.
*
* @param PersistentTokenInterface $token
*/
public function createNewToken(PersistentTokenInterface $token);
}

View File

@@ -0,0 +1,25 @@
<?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\User\UserProviderInterface;
/**
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
interface SimpleAuthenticatorInterface
{
public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey);
public function supportsToken(TokenInterface $token, $providerKey);
}

View File

@@ -0,0 +1,288 @@
<?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\Role\RoleInterface;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Symfony\Component\Security\Core\User\EquatableInterface;
/**
* 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 $roles = array();
private $authenticated = false;
private $attributes = array();
/**
* Constructor.
*
* @param (RoleInterface|string)[] $roles An array of roles
*
* @throws \InvalidArgumentException
*/
public function __construct(array $roles = array())
{
foreach ($roles as $role) {
if (is_string($role)) {
$role = new Role($role);
} elseif (!$role instanceof RoleInterface) {
throw new \InvalidArgumentException(sprintf('$roles must be an array of strings, or RoleInterface instances, but got %s.', gettype($role)));
}
$this->roles[] = $role;
}
}
/**
* {@inheritdoc}
*/
public function getRoles()
{
return $this->roles;
}
/**
* {@inheritdoc}
*/
public function getUsername()
{
if ($this->user instanceof UserInterface) {
return $this->user->getUsername();
}
return (string) $this->user;
}
/**
* {@inheritdoc}
*/
public function getUser()
{
return $this->user;
}
/**
* Sets the user in the token.
*
* The user can be a UserInterface instance, or an object implementing
* a __toString method or the username as a regular string.
*
* @param string|object $user The user
*
* @throws \InvalidArgumentException
*/
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 (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;
}
if ($changed) {
$this->setAuthenticated(false);
}
$this->user = $user;
}
/**
* {@inheritdoc}
*/
public function isAuthenticated()
{
return $this->authenticated;
}
/**
* {@inheritdoc}
*/
public function setAuthenticated($authenticated)
{
$this->authenticated = (bool) $authenticated;
}
/**
* {@inheritdoc}
*/
public function eraseCredentials()
{
if ($this->getUser() instanceof UserInterface) {
$this->getUser()->eraseCredentials();
}
}
/**
* {@inheritdoc}
*/
public function serialize()
{
return serialize(
array(
is_object($this->user) ? clone $this->user : $this->user,
$this->authenticated,
array_map(function ($role) { return clone $role; }, $this->roles),
$this->attributes,
)
);
}
/**
* {@inheritdoc}
*/
public function unserialize($serialized)
{
list($this->user, $this->authenticated, $this->roles, $this->attributes) = unserialize($serialized);
}
/**
* Returns the token attributes.
*
* @return array The token attributes
*/
public function getAttributes()
{
return $this->attributes;
}
/**
* Sets the token attributes.
*
* @param array $attributes The token attributes
*/
public function setAttributes(array $attributes)
{
$this->attributes = $attributes;
}
/**
* Returns true if the attribute exists.
*
* @param string $name The attribute name
*
* @return bool true if the attribute exists, false otherwise
*/
public function hasAttribute($name)
{
return array_key_exists($name, $this->attributes);
}
/**
* Returns an attribute value.
*
* @param string $name The attribute name
*
* @return mixed The attribute value
*
* @throws \InvalidArgumentException When attribute doesn't exist for this token
*/
public function getAttribute($name)
{
if (!array_key_exists($name, $this->attributes)) {
throw new \InvalidArgumentException(sprintf('This token has no "%s" attribute.', $name));
}
return $this->attributes[$name];
}
/**
* Sets an attribute.
*
* @param string $name The attribute name
* @param mixed $value The attribute value
*/
public function setAttribute($name, $value)
{
$this->attributes[$name] = $value;
}
/**
* {@inheritdoc}
*/
public function __toString()
{
$class = get_class($this);
$class = substr($class, strrpos($class, '\\') + 1);
$roles = array();
foreach ($this->roles as $role) {
$roles[] = $role->getRole();
}
return sprintf('%s(user="%s", authenticated=%s, roles="%s")', $class, $this->getUsername(), json_encode($this->authenticated), implode(', ', $roles));
}
private function hasUserChanged(UserInterface $user)
{
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);
}
if ($this->user->getPassword() !== $user->getPassword()) {
return true;
}
if ($this->user->getSalt() !== $user->getSalt()) {
return true;
}
if ($this->user->getUsername() !== $user->getUsername()) {
return true;
}
if ($this->user instanceof AdvancedUserInterface && $user instanceof AdvancedUserInterface) {
if ($this->user->isAccountNonExpired() !== $user->isAccountNonExpired()) {
return true;
}
if ($this->user->isAccountNonLocked() !== $user->isAccountNonLocked()) {
return true;
}
if ($this->user->isCredentialsNonExpired() !== $user->isCredentialsNonExpired()) {
return true;
}
if ($this->user->isEnabled() !== $user->isEnabled()) {
return true;
}
} elseif ($this->user instanceof AdvancedUserInterface xor $user instanceof AdvancedUserInterface) {
return true;
}
return false;
}
}

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\Token;
use Symfony\Component\Security\Core\Role\RoleInterface;
/**
* AnonymousToken represents an anonymous token.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class AnonymousToken extends AbstractToken
{
private $secret;
/**
* Constructor.
*
* @param string $secret A secret used to make sure the token is created by the app and not by a malicious client
* @param string|object $user The user can be a UserInterface instance, or an object implementing a __toString method or the username as a regular string
* @param RoleInterface[] $roles An array of roles
*/
public function __construct($secret, $user, array $roles = array())
{
parent::__construct($roles);
$this->secret = $secret;
$this->setUser($user);
$this->setAuthenticated(true);
}
/**
* {@inheritdoc}
*/
public function getCredentials()
{
return '';
}
/**
* Returns the secret.
*
* @return string
*/
public function getSecret()
{
return $this->secret;
}
/**
* {@inheritdoc}
*/
public function serialize()
{
return serialize(array($this->secret, parent::serialize()));
}
/**
* {@inheritdoc}
*/
public function unserialize($serialized)
{
list($this->secret, $parentStr) = unserialize($serialized);
parent::unserialize($parentStr);
}
}

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\Token;
use Symfony\Component\Security\Core\Role\RoleInterface;
/**
* PreAuthenticatedToken implements a pre-authenticated token.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class PreAuthenticatedToken extends AbstractToken
{
private $credentials;
private $providerKey;
/**
* Constructor.
*
* @param string|object $user The user can be a UserInterface instance, or an object implementing a __toString method or the username as a regular string
* @param mixed $credentials The user credentials
* @param string $providerKey The provider key
* @param (RoleInterface|string)[] $roles An array of roles
*/
public function __construct($user, $credentials, $providerKey, array $roles = array())
{
parent::__construct($roles);
if (empty($providerKey)) {
throw new \InvalidArgumentException('$providerKey must not be empty.');
}
$this->setUser($user);
$this->credentials = $credentials;
$this->providerKey = $providerKey;
if ($roles) {
$this->setAuthenticated(true);
}
}
/**
* Returns the provider key.
*
* @return string The provider key
*/
public function getProviderKey()
{
return $this->providerKey;
}
/**
* {@inheritdoc}
*/
public function getCredentials()
{
return $this->credentials;
}
/**
* {@inheritdoc}
*/
public function eraseCredentials()
{
parent::eraseCredentials();
$this->credentials = null;
}
/**
* {@inheritdoc}
*/
public function serialize()
{
return serialize(array($this->credentials, $this->providerKey, parent::serialize()));
}
/**
* {@inheritdoc}
*/
public function unserialize($str)
{
list($this->credentials, $this->providerKey, $parentStr) = unserialize($str);
parent::unserialize($parentStr);
}
}

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;
/**
* Authentication Token for "Remember-Me".
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class RememberMeToken extends AbstractToken
{
private $secret;
private $providerKey;
/**
* Constructor.
*
* @param UserInterface $user
* @param string $providerKey
* @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, $providerKey, $secret)
{
parent::__construct($user->getRoles());
if (empty($secret)) {
throw new \InvalidArgumentException('$secret must not be empty.');
}
if (empty($providerKey)) {
throw new \InvalidArgumentException('$providerKey must not be empty.');
}
$this->providerKey = $providerKey;
$this->secret = $secret;
$this->setUser($user);
parent::setAuthenticated(true);
}
/**
* {@inheritdoc}
*/
public function setAuthenticated($authenticated)
{
if ($authenticated) {
throw new \LogicException('You cannot set this token to authenticated after creation.');
}
parent::setAuthenticated(false);
}
/**
* Returns the provider secret.
*
* @return string The provider secret
*/
public function getProviderKey()
{
return $this->providerKey;
}
/**
* Returns the secret.
*
* @return string
*/
public function getSecret()
{
return $this->secret;
}
/**
* {@inheritdoc}
*/
public function getCredentials()
{
return '';
}
/**
* {@inheritdoc}
*/
public function serialize()
{
return serialize(array(
$this->secret,
$this->providerKey,
parent::serialize(),
));
}
/**
* {@inheritdoc}
*/
public function unserialize($serialized)
{
list($this->secret, $this->providerKey, $parentStr) = unserialize($serialized);
parent::unserialize($parentStr);
}
}

View File

@@ -0,0 +1,43 @@
<?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;
/**
* 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
{
private $token;
/**
* {@inheritdoc}
*/
public function getToken()
{
return $this->token;
}
/**
* {@inheritdoc}
*/
public function setToken(TokenInterface $token = null)
{
$this->token = $token;
}
}

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 A TokenInterface instance or null if no authentication information is available
*/
public function getToken();
/**
* Sets the authentication token.
*
* @param TokenInterface $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,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\Token;
use Symfony\Component\Security\Core\Role\RoleInterface;
/**
* TokenInterface is the interface for the user authentication information.
*
* @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 RoleInterface[] An array of RoleInterface instances
*/
public function getRoles();
/**
* Returns the user credentials.
*
* @return mixed The user credentials
*/
public function getCredentials();
/**
* Returns a user representation.
*
* @return mixed Can be a UserInterface instance, an object implementing a __toString method,
* or the username as a regular string
*
* @see AbstractToken::setUser()
*/
public function getUser();
/**
* Sets a user.
*
* @param mixed $user
*/
public function setUser($user);
/**
* Returns the username.
*
* @return string
*/
public function getUsername();
/**
* Returns whether the user is authenticated or not.
*
* @return bool true if the token has been authenticated, false otherwise
*/
public function isAuthenticated();
/**
* Sets the authenticated flag.
*
* @param bool $isAuthenticated The authenticated flag
*/
public function setAuthenticated($isAuthenticated);
/**
* Removes sensitive information from the token.
*/
public function eraseCredentials();
/**
* Returns the token attributes.
*
* @return array The token attributes
*/
public function getAttributes();
/**
* Sets the token attributes.
*
* @param array $attributes The token attributes
*/
public function setAttributes(array $attributes);
/**
* Returns true if the attribute exists.
*
* @param string $name The attribute name
*
* @return bool true if the attribute exists, false otherwise
*/
public function hasAttribute($name);
/**
* Returns an attribute value.
*
* @param string $name The attribute name
*
* @return mixed The attribute value
*
* @throws \InvalidArgumentException When attribute doesn't exist for this token
*/
public function getAttribute($name);
/**
* Sets an attribute.
*
* @param string $name The attribute name
* @param mixed $value The attribute value
*/
public function setAttribute($name, $value);
}

View File

@@ -0,0 +1,107 @@
<?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\Role\RoleInterface;
/**
* UsernamePasswordToken implements a username and password token.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class UsernamePasswordToken extends AbstractToken
{
private $credentials;
private $providerKey;
/**
* Constructor.
*
* @param string|object $user The username (like a nickname, email address, etc.), or a UserInterface instance or an object implementing a __toString method
* @param mixed $credentials This usually is the password of the user
* @param string $providerKey The provider key
* @param (RoleInterface|string)[] $roles An array of roles
*
* @throws \InvalidArgumentException
*/
public function __construct($user, $credentials, $providerKey, array $roles = array())
{
parent::__construct($roles);
if (empty($providerKey)) {
throw new \InvalidArgumentException('$providerKey must not be empty.');
}
$this->setUser($user);
$this->credentials = $credentials;
$this->providerKey = $providerKey;
parent::setAuthenticated(count($roles) > 0);
}
/**
* {@inheritdoc}
*/
public function setAuthenticated($isAuthenticated)
{
if ($isAuthenticated) {
throw new \LogicException('Cannot set this token to trusted after instantiation.');
}
parent::setAuthenticated(false);
}
/**
* {@inheritdoc}
*/
public function getCredentials()
{
return $this->credentials;
}
/**
* Returns the provider key.
*
* @return string The provider key
*/
public function getProviderKey()
{
return $this->providerKey;
}
/**
* {@inheritdoc}
*/
public function eraseCredentials()
{
parent::eraseCredentials();
$this->credentials = null;
}
/**
* {@inheritdoc}
*/
public function serialize()
{
return serialize(array($this->credentials, $this->providerKey, parent::serialize()));
}
/**
* {@inheritdoc}
*/
public function unserialize($serialized)
{
list($this->credentials, $this->providerKey, $parentStr) = unserialize($serialized);
parent::unserialize($parentStr);
}
}