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 c92abc9b88c3..29d738339119 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 diff --git a/src/Symfony/Component/Security/Http/EventListener/CsrfTokenClearingLogoutListener.php b/src/Symfony/Component/Security/Http/EventListener/CsrfTokenClearingLogoutListener.php index ec00bc1d9be6..20881f0f0c91 100644 --- a/src/Symfony/Component/Security/Http/EventListener/CsrfTokenClearingLogoutListener.php +++ b/src/Symfony/Component/Security/Http/EventListener/CsrfTokenClearingLogoutListener.php @@ -32,7 +32,12 @@ public function __construct(ClearableTokenStorageInterface $csrfTokenStorage) public function onLogout(LogoutEvent $event): void { - if ($this->csrfTokenStorage instanceof SessionTokenStorage && !$event->getRequest()->hasPreviousSession()) { + $request = $event->getRequest(); + + if ( + $this->csrfTokenStorage instanceof SessionTokenStorage + && ($request->attributes->getBoolean('_stateless') || !$request->hasPreviousSession()) + ) { return; } diff --git a/src/Symfony/Component/Security/Http/Tests/EventListener/CsrfTokenClearingLogoutListenerTest.php b/src/Symfony/Component/Security/Http/Tests/EventListener/CsrfTokenClearingLogoutListenerTest.php index 405c7ae08551..fc4aa9ffe4b8 100644 --- a/src/Symfony/Component/Security/Http/Tests/EventListener/CsrfTokenClearingLogoutListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/EventListener/CsrfTokenClearingLogoutListenerTest.php @@ -15,13 +15,14 @@ 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() { try { (new CsrfTokenClearingLogoutListener( @@ -33,4 +34,25 @@ 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); + + try { + (new CsrfTokenClearingLogoutListener( + new SessionTokenStorage(new RequestStack()) + ))->onLogout(new LogoutEvent($request, null)); + } catch (SessionNotFoundException) { + $this->fail('clear() must not be called if the request is stateless'); + } + + $this->addToAssertionCount(1); + } }