diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/JsonLoginFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/JsonLoginFactory.php index 2bda0ea9dc27..c1d3bcad34cf 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/JsonLoginFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/JsonLoginFactory.php @@ -83,10 +83,10 @@ protected function createListener($container, $id, $config, $userProvider) { $listenerId = $this->getListenerId(); $listener = new ChildDefinition($listenerId); - $listener->replaceArgument(2, $id); - $listener->replaceArgument(3, new Reference($this->createAuthenticationSuccessHandler($container, $id, $config))); - $listener->replaceArgument(4, new Reference($this->createAuthenticationFailureHandler($container, $id, $config))); - $listener->replaceArgument(5, array_intersect_key($config, $this->options)); + $listener->replaceArgument(3, $id); + $listener->replaceArgument(4, new Reference($this->createAuthenticationSuccessHandler($container, $id, $config))); + $listener->replaceArgument(5, new Reference($this->createAuthenticationFailureHandler($container, $id, $config))); + $listener->replaceArgument(6, array_intersect_key($config, $this->options)); $listenerId .= '.'.$id; $container->setDefinition($listenerId, $listener); diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml index f6b9cbf811ee..1eb7687a5db5 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml @@ -147,6 +147,7 @@ + diff --git a/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordJsonAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordJsonAuthenticationListener.php index 8b40119632b3..05389195fa92 100644 --- a/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordJsonAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordJsonAuthenticationListener.php @@ -29,6 +29,7 @@ use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface; use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; +use Symfony\Component\Security\Http\HttpUtils; use Symfony\Component\Security\Http\SecurityEvents; /** @@ -41,6 +42,7 @@ class UsernamePasswordJsonAuthenticationListener implements ListenerInterface { private $tokenStorage; private $authenticationManager; + private $httpUtils; private $providerKey; private $successHandler; private $failureHandler; @@ -49,10 +51,11 @@ class UsernamePasswordJsonAuthenticationListener implements ListenerInterface private $eventDispatcher; private $propertyAccessor; - public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $eventDispatcher = null, PropertyAccessorInterface $propertyAccessor = null) + public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $eventDispatcher = null, PropertyAccessorInterface $propertyAccessor = null) { $this->tokenStorage = $tokenStorage; $this->authenticationManager = $authenticationManager; + $this->httpUtils = $httpUtils; $this->providerKey = $providerKey; $this->successHandler = $successHandler; $this->failureHandler = $failureHandler; @@ -70,6 +73,10 @@ public function handle(GetResponseEvent $event) $request = $event->getRequest(); $data = json_decode($request->getContent()); + if (isset($this->options['check_path']) && !$this->httpUtils->checkRequestPath($request, $this->options['check_path'])) { + return; + } + try { if (!$data instanceof \stdClass) { throw new BadCredentialsException('Invalid JSON.'); diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordJsonAuthenticationListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordJsonAuthenticationListenerTest.php index e5435cb1b215..c687ea5a3176 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordJsonAuthenticationListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordJsonAuthenticationListenerTest.php @@ -24,6 +24,7 @@ use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface; use Symfony\Component\Security\Http\Firewall\UsernamePasswordJsonAuthenticationListener; +use Symfony\Component\Security\Http\HttpUtils; /** * @author Kévin Dunglas @@ -35,9 +36,15 @@ class UsernamePasswordJsonAuthenticationListenerTest extends TestCase */ private $listener; - private function createListener(array $options = array(), $success = true) + private function createListener(array $options = array(), $success = true, $matchCheckPath = true) { $tokenStorage = $this->getMockBuilder(TokenStorageInterface::class)->getMock(); + $httpUtils = $this->getMockBuilder(HttpUtils::class)->getMock(); + $httpUtils + ->expects($this->any()) + ->method('checkRequestPath') + ->will($this->returnValue($matchCheckPath)) + ; $authenticationManager = $this->getMockBuilder(AuthenticationManagerInterface::class)->getMock(); $authenticatedToken = $this->getMockBuilder(TokenInterface::class)->getMock(); @@ -53,7 +60,7 @@ private function createListener(array $options = array(), $success = true) $authenticationFailureHandler = $this->getMockBuilder(AuthenticationFailureHandlerInterface::class)->getMock(); $authenticationFailureHandler->method('onAuthenticationFailure')->willReturn(new Response('ko')); - $this->listener = new UsernamePasswordJsonAuthenticationListener($tokenStorage, $authenticationManager, 'providerKey', $authenticationSuccessHandler, $authenticationFailureHandler, $options); + $this->listener = new UsernamePasswordJsonAuthenticationListener($tokenStorage, $authenticationManager, $httpUtils, 'providerKey', $authenticationSuccessHandler, $authenticationFailureHandler, $options); } public function testHandleSuccess() @@ -136,4 +143,25 @@ public function testAttemptAuthenticationUsernameTooLong() $this->listener->handle($event); $this->assertSame('ko', $event->getResponse()->getContent()); } + + public function testDoesNotAttemptAuthenticationIfRequestPathDoesNotMatchCheckPath() + { + $this->createListener(array('check_path' => '/'), true, false); + $request = new Request(); + $event = new GetResponseEvent($this->getMockBuilder(KernelInterface::class)->getMock(), $request, KernelInterface::MASTER_REQUEST); + $event->setResponse(new Response('original')); + + $this->listener->handle($event); + $this->assertSame('original', $event->getResponse()->getContent()); + } + + public function testAttemptAuthenticationIfRequestPathMatchesCheckPath() + { + $this->createListener(array('check_path' => '/')); + $request = new Request(array(), array(), array(), array(), array(), array(), '{"username": "dunglas", "password": "foo"}'); + $event = new GetResponseEvent($this->getMockBuilder(KernelInterface::class)->getMock(), $request, KernelInterface::MASTER_REQUEST); + + $this->listener->handle($event); + $this->assertEquals('ok', $event->getResponse()->getContent()); + } }