Splitting the getting of the user and checking credentials into two steps
This looks like a subjective change (one more method, but the method implementations are simpler), but it wasn't. The problem was that the UserChecker checkPreAuth should happen *after* we get the user, but *before* the credentials are checked, and that wasn't possible before this change. Now it is.
This commit is contained in:
parent
6edb9e1b06
commit
ffdbc66534
@ -27,7 +27,7 @@ interface GuardAuthenticatorInterface extends AuthenticationEntryPointInterface
|
||||
* as any type (e.g. an associate array). If you return null, authentication
|
||||
* will be skipped.
|
||||
*
|
||||
* Whatever value you return here will be passed to authenticate()
|
||||
* Whatever value you return here will be passed to getUser() and checkCredentials()
|
||||
*
|
||||
* For example, for a form login, you might:
|
||||
*
|
||||
@ -47,19 +47,33 @@ interface GuardAuthenticatorInterface extends AuthenticationEntryPointInterface
|
||||
public function getCredentials(Request $request);
|
||||
|
||||
/**
|
||||
* Return a UserInterface object based on the credentials OR throw
|
||||
* an AuthenticationException.
|
||||
* Return a UserInterface object based on the credentials
|
||||
*
|
||||
* The *credentials* are the return value from getCredentials()
|
||||
*
|
||||
* You may throw an AuthenticationException if you wish. If you return
|
||||
* null, then a UsernameNotFoundException is thrown for you.
|
||||
*
|
||||
* @param mixed $credentials
|
||||
* @param UserProviderInterface $userProvider
|
||||
*
|
||||
* @throws AuthenticationException
|
||||
*
|
||||
* @return UserInterface
|
||||
* @return UserInterface|null
|
||||
*/
|
||||
public function authenticate($credentials, UserProviderInterface $userProvider);
|
||||
public function getUser($credentials, UserProviderInterface $userProvider);
|
||||
|
||||
/**
|
||||
* Throw an AuthenticationException if the credentials are invalid
|
||||
*
|
||||
* The *credentials* are the return value from getCredentials()
|
||||
*
|
||||
* @param mixed $credentials
|
||||
* @param UserInterface $user
|
||||
* @throws AuthenticationException
|
||||
* @return void
|
||||
*/
|
||||
public function checkCredentials($credentials, UserInterface $user);
|
||||
|
||||
/**
|
||||
* Create an authenticated token for the given user.
|
||||
|
@ -4,6 +4,7 @@ namespace Symfony\Component\Security\Guard\Provider;
|
||||
|
||||
use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
|
||||
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
|
||||
use Symfony\Component\Security\Guard\GuardAuthenticatorInterface;
|
||||
use Symfony\Component\Security\Guard\Token\GuardTokenInterface;
|
||||
use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken;
|
||||
@ -95,18 +96,28 @@ class GuardAuthenticationProvider implements AuthenticationProviderInterface
|
||||
private function authenticateViaGuard(GuardAuthenticatorInterface $guardAuthenticator, PreAuthenticationGuardToken $token)
|
||||
{
|
||||
// get the user from the GuardAuthenticator
|
||||
$user = $guardAuthenticator->authenticate($token->getCredentials(), $this->userProvider);
|
||||
$user = $guardAuthenticator->getUser($token->getCredentials(), $this->userProvider);
|
||||
|
||||
if (null === $user) {
|
||||
throw new UsernameNotFoundException(sprintf(
|
||||
'Null returned from %s::getUser()',
|
||||
get_class($guardAuthenticator)
|
||||
));
|
||||
}
|
||||
|
||||
if (!$user instanceof UserInterface) {
|
||||
throw new \UnexpectedValueException(sprintf(
|
||||
'The %s::authenticate method must return a UserInterface. You returned %s.',
|
||||
'The %s::getUser method must return a UserInterface. You returned %s.',
|
||||
get_class($guardAuthenticator),
|
||||
is_object($user) ? get_class($user) : gettype($user)
|
||||
));
|
||||
}
|
||||
|
||||
// check the AdvancedUserInterface methods!
|
||||
// check the preAuth UserChecker
|
||||
$this->userChecker->checkPreAuth($user);
|
||||
// check the credentials
|
||||
$guardAuthenticator->checkCredentials($token->getCredentials(), $user);
|
||||
// check the postAuth UserChecker
|
||||
$this->userChecker->checkPostAuth($user);
|
||||
|
||||
// turn the UserInterface into a TokenInterface
|
||||
|
@ -43,21 +43,25 @@ class GuardAuthenticationProviderTest extends \PHPUnit_Framework_TestCase
|
||||
'username' => '_weaverryan_test_user',
|
||||
'password' => 'guard_auth_ftw',
|
||||
);
|
||||
$this->preAuthenticationToken->expects($this->once())
|
||||
$this->preAuthenticationToken->expects($this->atLeastOnce())
|
||||
->method('getCredentials')
|
||||
->will($this->returnValue($enteredCredentials));
|
||||
|
||||
// authenticators A and C are never called
|
||||
$authenticatorA->expects($this->never())
|
||||
->method('authenticate');
|
||||
->method('getUser');
|
||||
$authenticatorC->expects($this->never())
|
||||
->method('authenticate');
|
||||
->method('getUser');
|
||||
|
||||
$mockedUser = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
|
||||
$authenticatorB->expects($this->once())
|
||||
->method('authenticate')
|
||||
->method('getUser')
|
||||
->with($enteredCredentials, $this->userProvider)
|
||||
->will($this->returnValue($mockedUser));
|
||||
// checkCredentials is called
|
||||
$authenticatorB->expects($this->once())
|
||||
->method('checkCredentials')
|
||||
->with($enteredCredentials, $mockedUser);
|
||||
$authedToken = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
|
||||
$authenticatorB->expects($this->once())
|
||||
->method('createAuthenticatedToken')
|
||||
|
Reference in New Issue
Block a user