From 7f812e18ec57633715660eb71b5426eb742ca96f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Alfaiate?= Date: Sat, 24 Aug 2024 10:57:07 +0700 Subject: [PATCH 1/3] [Security] Do not try to clear CSRF on stateless request --- .../Compiler/RegisterCsrfFeaturesPass.php | 1 + .../CsrfTokenClearingLogoutListener.php | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterCsrfFeaturesPass.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterCsrfFeaturesPass.php index 20b79b07c49d2..c9ee463c2683c 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterCsrfFeaturesPass.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterCsrfFeaturesPass.php @@ -58,6 +58,7 @@ protected function registerLogoutHandler(ContainerBuilder $container): void $container->register('security.logout.listener.csrf_token_clearing', CsrfTokenClearingLogoutListener::class) ->addArgument(new Reference('security.csrf.token_storage')) + ->addArgument(new Reference('security.firewall.map')) ->addTag('kernel.event_subscriber'); } } diff --git a/src/Symfony/Component/Security/Http/EventListener/CsrfTokenClearingLogoutListener.php b/src/Symfony/Component/Security/Http/EventListener/CsrfTokenClearingLogoutListener.php index ec00bc1d9be6e..7dc7ecb80e513 100644 --- a/src/Symfony/Component/Security/Http/EventListener/CsrfTokenClearingLogoutListener.php +++ b/src/Symfony/Component/Security/Http/EventListener/CsrfTokenClearingLogoutListener.php @@ -11,10 +11,12 @@ namespace Symfony\Component\Security\Http\EventListener; +use Symfony\Bundle\SecurityBundle\Security\FirewallMap; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Security\Csrf\TokenStorage\ClearableTokenStorageInterface; use Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage; use Symfony\Component\Security\Http\Event\LogoutEvent; +use Symfony\Component\Security\Http\FirewallMapInterface; /** * @author Christian Flothmann @@ -24,15 +26,25 @@ class CsrfTokenClearingLogoutListener implements EventSubscriberInterface { private ClearableTokenStorageInterface $csrfTokenStorage; + private FirewallMapInterface $map; - public function __construct(ClearableTokenStorageInterface $csrfTokenStorage) + public function __construct(ClearableTokenStorageInterface $csrfTokenStorage, FirewallMapInterface $map) { $this->csrfTokenStorage = $csrfTokenStorage; + $this->map = $map; } public function onLogout(LogoutEvent $event): void { - if ($this->csrfTokenStorage instanceof SessionTokenStorage && !$event->getRequest()->hasPreviousSession()) { + $request = $event->getRequest(); + + if ( + $this->csrfTokenStorage instanceof SessionTokenStorage + && ( + ($this->map instanceof FirewallMap && $this->map->getFirewallConfig($request)->isStateless()) + || !$request->hasPreviousSession() + ) + ) { return; } From 1be07ff4d36b698d3a12e756d2f00feea651f9ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Alfaiate?= Date: Sat, 24 Aug 2024 11:10:02 +0700 Subject: [PATCH 2/3] Add test to clear CSRF on stateless request --- .../CsrfTokenClearingLogoutListenerTest.php | 45 ++++++++++++++++++- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Security/Http/Tests/EventListener/CsrfTokenClearingLogoutListenerTest.php b/src/Symfony/Component/Security/Http/Tests/EventListener/CsrfTokenClearingLogoutListenerTest.php index 405c7ae085510..06599416ff341 100644 --- a/src/Symfony/Component/Security/Http/Tests/EventListener/CsrfTokenClearingLogoutListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/EventListener/CsrfTokenClearingLogoutListenerTest.php @@ -12,20 +12,31 @@ namespace Symfony\Component\Security\Http\Tests\EventListener; use PHPUnit\Framework\TestCase; +use Symfony\Bundle\SecurityBundle\Security\FirewallConfig; +use Symfony\Bundle\SecurityBundle\Security\FirewallMap; use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage; use Symfony\Component\Security\Http\Event\LogoutEvent; use Symfony\Component\Security\Http\EventListener\CsrfTokenClearingLogoutListener; class CsrfTokenClearingLogoutListenerTest extends TestCase { - public function testSkipsClearingSessionTokenStorageOnStatelessRequest() + public function testSkipsClearingSessionTokenStorageOnRequestWithoutSession() { + $map = $this->createMock(FirewallMap::class); + $map + ->expects($this->once()) + ->method('getFirewallConfig') + ->willReturn(new FirewallConfig('firewall', 'user_checker')) + ; + try { (new CsrfTokenClearingLogoutListener( - new SessionTokenStorage(new RequestStack()) + new SessionTokenStorage(new RequestStack()), + $map ))->onLogout(new LogoutEvent(new Request(), null)); } catch (SessionNotFoundException) { $this->fail('clear() must not be called if the request is not associated with a session instance'); @@ -33,4 +44,34 @@ public function testSkipsClearingSessionTokenStorageOnStatelessRequest() $this->addToAssertionCount(1); } + + public function testSkipsClearingSessionTokenStorageOnStatelessRequest() + { + $session = new Session(); + + // Create a stateless request with a previous session + $request = new Request(); + $request->setSession($session); + $request->cookies->set($session->getName(), 'previous_session'); + $request->attributes->set('_stateless', true); + + $map = $this->createMock(FirewallMap::class); + $map + ->expects($this->once()) + ->method('getFirewallConfig') + ->with($this->equalTo($request)) + ->willReturn(new FirewallConfig('stateless_firewall', 'user_checker', stateless: true)) + ; + + try { + (new CsrfTokenClearingLogoutListener( + new SessionTokenStorage(new RequestStack()), + $map + ))->onLogout(new LogoutEvent($request, null)); + } catch (SessionNotFoundException) { + $this->fail('clear() must not be called if the request is stateless'); + } + + $this->addToAssertionCount(1); + } } From af059e017c512c02463574b1aae17c7b5afc653f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Alfaiate?= Date: Sat, 24 Aug 2024 11:25:50 +0700 Subject: [PATCH 3/3] Fix incorrect test config --- .../Functional/app/LogoutWithoutSessionInvalidation/config.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutWithoutSessionInvalidation/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutWithoutSessionInvalidation/config.yml index c92abc9b88c33..29d738339119e 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutWithoutSessionInvalidation/config.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/LogoutWithoutSessionInvalidation/config.yml @@ -21,4 +21,3 @@ security: secret: secret logout: invalidate_session: false - stateless: true pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy