8000 [Security] Allow to set a check_path on json_login listener · symfony/symfony@9f7eb61 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9f7eb61

Browse files
chalasrfabpot
authored andcommitted
[Security] Allow to set a check_path on json_login listener
1 parent 4f0daa7 commit 9f7eb61

File tree

6 files changed

+50
-8
lines changed

6 files changed

+50
-8
lines changed

src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/JsonLoginFactory.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
* JsonLoginFactory creates services for JSON login authentication.
2020
*
2121
* @author Kévin Dunglas <dunglas@gmail.com>
22+
*
23+
* @experimental in version 3.3
2224
*/
2325
class JsonLoginFactory extends AbstractFactory
2426
{
@@ -83,10 +85,10 @@ protected function createListener($container, $id, $config, $userProvider)
8385
{
8486
$listenerId = $this->getListenerId();
8587
$listener = new ChildDefinition($listenerId);
86-
$listener->replaceArgument(2, $id);
87-
$listener->replaceArgument(3, new Reference($this->createAuthenticationSuccessHandler($container, $id, $config)));
88-
$listener->replaceArgument(4, new Reference($this->createAuthenticationFailureHandler($container, $id, $config)));
89-
$listener->replaceArgument(5, array_intersect_key($config, $this->options));
88+
$listener->replaceArgument(3, $id);
89+
$listener->replaceArgument(4, new Reference($this->createAuthenticationSuccessHandler($container, $id, $config)));
90+
$listener->replaceArgument(5, new Reference($this->createAuthenticationFailureHandler($container, $id, $config)));
91+
$listener->replaceArgument(6, array_intersect_key($config, $this->options));
9092

9193
$listenerId .= '.'.$id;
9294
$container->setDefinition($listenerId, $listener);

src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@
147147
<tag name="monolog.logger" channel="security" />
148148
<argument type="service" id="security.token_storage" />
149149
<argument type="service" id="security.authentication.manager" />
150+
<argument type="service" id="security.http_utils" />
150151
<argument /> <!-- Provider-shared Key -->
151152
<argument type="service" id="security.authentication.success_handler" />
152153
<argument type="service" id="security.authentication.failure_handler" />

src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ security:
1616
pattern: ^/
1717
anonymous: true
1818
json_login:
19-
check_path: /mychk
19+
check_path: /chk
2020
username_path: user.login
2121
password_path: user.password
2222

src/Symfony/Component/Security/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ CHANGELOG
66

77
* deprecated `AccessDecisionManager::setVoters()` in favor of passing the
88
voters to the constructor.
9+
* [EXPERIMENTAL] added a `json_login` listener for stateless authentication
910

1011
3.2.0
1112
-----

src/Symfony/Component/Security/Http/Firewall/UsernamePasswordJsonAuthenticationListener.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,22 @@
2929
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
3030
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
3131
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
32+
use Symfony\Component\Security\Http\HttpUtils;
3233
use Symfony\Component\Security\Http\SecurityEvents;
3334

3435
/**
3536
* UsernamePasswordJsonAuthenticationListener is a stateless implementation of
3637
* an authentication via a JSON document composed of a username and a password.
3738
*
3839
* @author Kévin Dunglas <dunglas@gmail.com>
40+
*
41+
* @experimental in version 3.3
3942
*/
4043
class UsernamePasswordJsonAuthenticationListener implements ListenerInterface
4144
{
4245
private $tokenStorage;
4346
private $authenticationManager;
47+
private $httpUtils;
4448
private $providerKey;
4549
private $successHandler;
4650
private $failureHandler;
@@ -49,10 +53,11 @@ class UsernamePasswordJsonAuthenticationListener implements ListenerInterface
4953
private $eventDispatcher;
5054
private $propertyAccessor;
5155

52-
public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $eventDispatcher = null, PropertyAccessorInterface $propertyAccessor = null)
56+
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)
5357
{
5458
$this->tokenStorage = $tokenStorage;
5559
$this->authenticationManager = $authenticationManager;
60+
$this->httpUtils = $httpUtils;
5661
$this->providerKey = $providerKey;
5762
$this->successHandler = $successHandler;
5863
$this->failureHandler = $failureHandler;
@@ -68,6 +73,11 @@ public function __construct(TokenStorageInterface $tokenStorage, AuthenticationM
6873
public function handle(GetResponseEvent $event)
6974
{
7075
$request = $event->getRequest();
76+
77+
if (isset($this->options['check_path']) && !$this->httpUtils->checkRequestPath($request, $this->options['check_path'])) {
78+
return;
79+
}
80+
7181
$data = json_decode($request->getContent());
7282

7383
try {

src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordJsonAuthenticationListenerTest.php

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
2525
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
2626
use Symfony\Component\Security\Http\Firewall\UsernamePasswordJsonAuthenticationListener;
27+
use Symfony\Component\Security\Http\HttpUtils;
2728

2829
/**
2930
* @author Kévin Dunglas <dunglas@gmail.com>
@@ -35,9 +36,15 @@ class UsernamePasswordJsonAuthenticationListenerTest extends TestCase
3536
*/
3637
private $listener;
3738

38-
private function createListener(array $options = array(), $success = true)
39+
private function createListener(array $options = array(), $success = true, $matchCheckPath = true)
3940
{
4041
$tokenStorage = $this->getMockBuilder(TokenStorageInterface::class)->getMock();
42+
$httpUtils = $this->getMockBuilder(HttpUtils::class)->getMock();
43+
$httpUtils
44+
->expects($this->any())
45+
->method('checkRequestPath')
46+
->will($this->returnValue($matchCheckPath))
47+
;
4148
$authenticationManager = $this->getMockBuilder(AuthenticationManagerInterface::class)->getMock();
4249

4350
$authenticatedToken = $this->getMockBuilder(TokenInterface::class)->getMock();
@@ -53,7 +60,7 @@ private function createListener(array $options = array(), $success = true)
5360
$authenticationFailureHandler = $this->getMockBuilder(AuthenticationFailureHandlerInterface::class)->getMock();
5461
$authenticationFailureHandler->method('onAuthenticationFailure')->willReturn(new Response('ko'));
5562

56-
$this->listener = new UsernamePasswordJsonAuthenticationListener($tokenStorage, $authenticationManager, 'providerKey', $authenticationSuccessHandler, $authenticationFailureHandler, $options);
63+
$this->listener = new UsernamePasswordJsonAuthenticationListener($tokenStorage, $authenticationManager, $httpUtils, 'providerKey', $authenticationSuccessHandler, $authenticationFailureHandler, $options);
5764
}
5865

5966
public function testHandleSuccess()
@@ -136,4 +143,25 @@ public function testAttemptAuthenticationUsernameTooLong()
136143
$this->listener->handle($event);
137144
$this->assertSame('ko', $event->getResponse()->getContent());
138145
}
146+
147+
public function testDoesNotAttemptAuthenticationIfRequestPathDoesNotMatchCheckPath()
148+
{
149+
$this->createListener(array('check_path' => '/'), true, false);
150+
$request = new Request();
151+
$event = new GetResponseEvent($this->getMockBuilder(KernelInterface::class)->getMock(), $request, KernelInterface::MASTER_REQUEST);
152+
$event->setResponse(new Response('original'));
153+
154+
$this->listener->handle($event);
155+
$this->assertSame('original', $event->getResponse()->getContent());
156+
}
157+
158+
public function testAttemptAuthenticationIfRequestPathMatchesCheckPath()
159+
{
160+
$this->createListener(array('check_path' => '/'));
161+
$request = new Request(array(), array(), array(), array(), array(), array(), '{"username": "dunglas", "password": "foo"}');
162+
$event = new GetResponseEvent($this->getMockBuilder(KernelInterface::class)->getMock(), $request, KernelInterface::MASTER_REQUEST);
163+
164+
$this->listener->handle($event);
165+
$this->assertSame('ok', $event->getResponse()->getContent());
166+
}
139167
}

0 commit comments

Comments
 (0)
0