From c318306b446c64c7fa5b9097129b3cdb1355e0c5 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Wed, 4 Apr 2018 09:58:50 +0200 Subject: [PATCH] [Security] Load the user before pre/post auth checks when needed --- .../Provider/SimpleAuthenticationProvider.php | 21 ++++++++ .../SimpleAuthenticationProviderTest.php | 49 +++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php b/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php index a82fb7eea427..ded0e94f50f6 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php @@ -11,8 +11,11 @@ namespace Symfony\Component\Security\Core\Authentication\Provider; +use Symfony\Component\Security\Core\Exception\AuthenticationServiceException; +use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\User\UserChecker; use Symfony\Component\Security\Core\User\UserCheckerInterface; +use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface; @@ -45,6 +48,24 @@ public function authenticate(TokenInterface $token) } $user = $authToken->getUser(); + + if (!$user instanceof UserInterface) { + try { + $user = $this->userProvider->loadUserByUsername($user); + + if (!$user instanceof UserInterface) { + throw new AuthenticationServiceException('The user provider must return a UserInterface object.'); + } + } catch (UsernameNotFoundException $e) { + $e->setUsername($user); + throw $e; + } catch (\Exception $e) { + $e = new AuthenticationServiceException($e->getMessage(), 0, $e); + $e->setToken($token); + throw $e; + } + } + $this->userChecker->checkPreAuth($user); $this->userChecker->checkPostAuth($user); diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/SimpleAuthenticationProviderTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/SimpleAuthenticationProviderTest.php index 1e7069c1fa0b..acee33b856b4 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/SimpleAuthenticationProviderTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/SimpleAuthenticationProviderTest.php @@ -15,6 +15,7 @@ use Symfony\Component\Security\Core\Exception\DisabledException; use Symfony\Component\Security\Core\Authentication\Provider\SimpleAuthenticationProvider; use Symfony\Component\Security\Core\Exception\LockedException; +use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; class SimpleAuthenticationProviderTest extends TestCase { @@ -72,6 +73,54 @@ public function testAuthenticateWhenPostChecksFails() $provider->authenticate($token); } + public function testAuthenticateFromString() + { + $user = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock(); + + $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); + $token->expects($this->any()) + ->method('getUser') + ->will($this->returnValue('foo')); + + $authenticator = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface')->getMock(); + $authenticator->expects($this->once()) + ->method('authenticateToken') + ->will($this->returnValue($token)); + + $userProvider = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserProviderInterface')->getMock(); + $userProvider->expects($this->once()) + ->method('loadUserByUsername') + ->willReturn($this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock()); + $provider = $this->getProvider($authenticator, $userProvider); + + $this->assertSame($token, $provider->authenticate($token)); + } + + /** + * @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException + */ + public function testUsernameNotFound() + { + $user = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock(); + + $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); + $token->expects($this->any()) + ->method('getUser') + ->will($this->returnValue('foo')); + + $authenticator = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface')->getMock(); + $authenticator->expects($this->once()) + ->method('authenticateToken') + ->will($this->returnValue($token)); + + $userProvider = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserProviderInterface')->getMock(); + $userProvider->expects($this->once()) + ->method('loadUserByUsername') + ->willThrowException(new UsernameNotFoundException()); + + $this->getProvider($authenticator, $userProvider)->authenticate($token); + } + protected function getProvider($simpleAuthenticator = null, $userProvider = null, $userChecker = null, $key = 'test') { if (null === $userChecker) {