From c5bd0bdacb0fe1c1adbb004a79e6e9678dcc478e Mon Sep 17 00:00:00 2001 From: Boris Vujicic Date: Fri, 2 Mar 2018 09:14:52 +0100 Subject: [PATCH 1/4] [Security] added userChecker to SimpleAuthenticationProvider Added UserChecker to SimpleAuthenticationProvider and updated SimpleFormFactory --- .../Security/Factory/SimpleFormFactory.php | 1 + .../Provider/SimpleAuthenticationProvider.php | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SimpleFormFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SimpleFormFactory.php index 6241cf4f3912f..69b8b943abac0 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SimpleFormFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SimpleFormFactory.php @@ -55,6 +55,7 @@ protected function createAuthProvider(ContainerBuilder $container, $id, $config, ->replaceArgument(0, new Reference($config['authenticator'])) ->replaceArgument(1, new Reference($userProviderId)) ->replaceArgument(2, $id) + ->replaceArgument(3, new Reference('security.user_checker.'.$id)) ; return $provider; diff --git a/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php b/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php index ffbc72c055a0f..46fce6fdc5373 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Security\Core\Authentication\Provider; +use Symfony\Component\Security\Core\User\UserChecker; +use Symfony\Component\Security\Core\User\UserCheckerInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface; @@ -24,17 +26,22 @@ class SimpleAuthenticationProvider implements AuthenticationProviderInterface private $simpleAuthenticator; private $userProvider; private $providerKey; + private $userChecker; - public function __construct(SimpleAuthenticatorInterface $simpleAuthenticator, UserProviderInterface $userProvider, $providerKey) + public function __construct(SimpleAuthenticatorInterface $simpleAuthenticator, UserProviderInterface $userProvider, $providerKey, UserCheckerInterface $userChecker = null) { $this->simpleAuthenticator = $simpleAuthenticator; $this->userProvider = $userProvider; $this->providerKey = $providerKey; + $this->userChecker = $userChecker ?: new UserChecker(); } public function authenticate(TokenInterface $token) { + $user = $this->userProvider->loadUserByUsername($token->getUsername()); + $this->userChecker->checkPreAuth($user); $authToken = $this->simpleAuthenticator->authenticateToken($token, $this->userProvider, $this->providerKey); + $this->userChecker->checkPostAuth($user); if ($authToken instanceof TokenInterface) { return $authToken; From 63d9dce10bdda859f485eb6e21fccb7a30216ced Mon Sep 17 00:00:00 2001 From: Boris Vujicic Date: Sat, 3 Mar 2018 21:35:01 +0100 Subject: [PATCH 2/4] [Security] added userChecker to SimpleAuthenticationProvider retrieve user from authToken, rather then fetching it from userProvider --- .../Authentication/Provider/SimpleAuthenticationProvider.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php b/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php index 46fce6fdc5373..29795e608da9e 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php @@ -38,10 +38,9 @@ public function __construct(SimpleAuthenticatorInterface $simpleAuthenticator, U public function authenticate(TokenInterface $token) { - $user = $this->userProvider->loadUserByUsername($token->getUsername()); - $this->userChecker->checkPreAuth($user); $authToken = $this->simpleAuthenticator->authenticateToken($token, $this->userProvider, $this->providerKey); - $this->userChecker->checkPostAuth($user); + $this->userChecker->checkPreAuth($authToken->getUser()); + $this->userChecker->checkPostAuth($authToken->getUser()); if ($authToken instanceof TokenInterface) { return $authToken; From 3cc426e51102b284ab25d2be8ba28c40293aa025 Mon Sep 17 00:00:00 2001 From: Boris Vujicic Date: Sun, 4 Mar 2018 09:37:35 +0100 Subject: [PATCH 3/4] [Security] added userChecker to SimpleAuthenticationProvider apply userChecker after authToken is authenticated --- .../Provider/SimpleAuthenticationProvider.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php b/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php index 29795e608da9e..a902f1c647d44 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php @@ -39,14 +39,15 @@ public function __construct(SimpleAuthenticatorInterface $simpleAuthenticator, U public function authenticate(TokenInterface $token) { $authToken = $this->simpleAuthenticator->authenticateToken($token, $this->userProvider, $this->providerKey); - $this->userChecker->checkPreAuth($authToken->getUser()); - $this->userChecker->checkPostAuth($authToken->getUser()); - if ($authToken instanceof TokenInterface) { - return $authToken; + if (!($authToken instanceof TokenInterface)) { + throw new AuthenticationException('Simple authenticator failed to return an authenticated token.'); } - throw new AuthenticationException('Simple authenticator failed to return an authenticated token.'); + $this->userChecker->checkPreAuth($authToken->getUser()); + $this->userChecker->checkPostAuth($authToken->getUser()); + + return $authToken; } public function supports(TokenInterface $token) From 476861e0e704cd616185c38a94b723fd5618a966 Mon Sep 17 00:00:00 2001 From: Boris Vujicic Date: Mon, 5 Mar 2018 09:10:34 +0100 Subject: [PATCH 4/4] [Security] added userChecker to SimpleAuthenticationProvider test for userChecker postAuth and preAuth --- .../Provider/SimpleAuthenticationProvider.php | 7 +- .../SimpleAuthenticationProviderTest.php | 89 +++++++++++++++++++ 2 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 src/Symfony/Component/Security/Core/Tests/Authentication/Provider/SimpleAuthenticationProviderTest.php diff --git a/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php b/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php index a902f1c647d44..a82fb7eea4279 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php @@ -40,12 +40,13 @@ public function authenticate(TokenInterface $token) { $authToken = $this->simpleAuthenticator->authenticateToken($token, $this->userProvider, $this->providerKey); - if (!($authToken instanceof TokenInterface)) { + if (!$authToken instanceof TokenInterface) { throw new AuthenticationException('Simple authenticator failed to return an authenticated token.'); } - $this->userChecker->checkPreAuth($authToken->getUser()); - $this->userChecker->checkPostAuth($authToken->getUser()); + $user = $authToken->getUser(); + $this->userChecker->checkPreAuth($user); + $this->userChecker->checkPostAuth($user); return $authToken; } diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/SimpleAuthenticationProviderTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/SimpleAuthenticationProviderTest.php new file mode 100644 index 0000000000000..1e7069c1fa0bb --- /dev/null +++ b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/SimpleAuthenticationProviderTest.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Core\Tests\Authentication\Provider; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Security\Core\Exception\DisabledException; +use Symfony\Component\Security\Core\Authentication\Provider\SimpleAuthenticationProvider; +use Symfony\Component\Security\Core\Exception\LockedException; + +class SimpleAuthenticationProviderTest extends TestCase +{ + /** + * @expectedException \Symfony\Component\Security\Core\Exception\DisabledException + */ + public function testAuthenticateWhenPreChecksFails() + { + $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($user)); + + $userChecker = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserCheckerInterface')->getMock(); + $userChecker->expects($this->once()) + ->method('checkPreAuth') + ->will($this->throwException(new DisabledException())); + + $authenticator = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface')->getMock(); + $authenticator->expects($this->once()) + ->method('authenticateToken') + ->will($this->returnValue($token)); + + $provider = $this->getProvider($authenticator, null, $userChecker); + + $provider->authenticate($token); + } + + /** + * @expectedException \Symfony\Component\Security\Core\Exception\LockedException + */ + public function testAuthenticateWhenPostChecksFails() + { + $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($user)); + + $userChecker = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserCheckerInterface')->getMock(); + $userChecker->expects($this->once()) + ->method('checkPostAuth') + ->will($this->throwException(new LockedException())); + + $authenticator = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface')->getMock(); + $authenticator->expects($this->once()) + ->method('authenticateToken') + ->will($this->returnValue($token)); + + $provider = $this->getProvider($authenticator, null, $userChecker); + + $provider->authenticate($token); + } + + protected function getProvider($simpleAuthenticator = null, $userProvider = null, $userChecker = null, $key = 'test') + { + if (null === $userChecker) { + $userChecker = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserCheckerInterface')->getMock(); + } + if (null === $simpleAuthenticator) { + $simpleAuthenticator = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface')->getMock(); + } + if (null === $userProvider) { + $userProvider = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserProviderInterface')->getMock(); + } + + return new SimpleAuthenticationProvider($simpleAuthenticator, $userProvider, $key, $userChecker); + } +}