Skip to content

Commit 30460c0

Browse files
Amrouche HamzaSimperfit
Amrouche Hamza
authored andcommitted
[Security] REMEMBERME cookie does not get deleted using the "logout_on_user_change" option
1 parent e376c99 commit 30460c0

File tree

3 files changed

+52
-1
lines changed

3 files changed

+52
-1
lines changed

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

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
<argument type="service" id="logger" on-invalid="null" />
4646
<argument type="service" id="event_dispatcher" on-invalid="null" />
4747
<argument type="service" id="security.authentication.trust_resolver" />
48+
<argument type="service" id="security.authentication.rememberme" on-invalid="null" />
4849
</service>
4950

5051
<service id="security.logout_listener" class="Symfony\Component\Security\Http\Firewall\LogoutListener" abstract="true">

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

+9-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
use Symfony\Component\Security\Core\Role\SwitchUserRole;
2828
use Symfony\Component\Security\Core\User\UserInterface;
2929
use Symfony\Component\Security\Core\User\UserProviderInterface;
30+
use Symfony\Component\Security\Http\RememberMe\AbstractRememberMeServices;
31+
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
3032

3133
/**
3234
* ContextListener manages the SecurityContext persistence through a session.
@@ -44,12 +46,13 @@ class ContextListener implements ListenerInterface
4446
private $registered;
4547
private $trustResolver;
4648
private $logoutOnUserChange = false;
49+
private $rememberMeServices;
4750

4851
/**
4952
* @param iterable|UserProviderInterface[] $userProviders
5053
* @param string $contextKey
5154
*/
52-
public function __construct(TokenStorageInterface $tokenStorage, $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, AuthenticationTrustResolverInterface $trustResolver = null)
55+
public function __construct(TokenStorageInterface $tokenStorage, $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, AuthenticationTrustResolverInterface $trustResolver = null, RememberMeServicesInterface $rememberMeServices = null)
5356
{
5457
if (empty($contextKey)) {
5558
throw new \InvalidArgumentException('$contextKey must not be empty.');
@@ -61,6 +64,7 @@ public function __construct(TokenStorageInterface $tokenStorage, $userProviders,
6164
$this->logger = $logger;
6265
$this->dispatcher = $dispatcher;
6366
$this->trustResolver = $trustResolver ?: new AuthenticationTrustResolver(AnonymousToken::class, RememberMeToken::class);
67+
$this->rememberMeServices = $rememberMeServices;
6468
}
6569

6670
/**
@@ -103,6 +107,10 @@ public function handle(GetResponseEvent $event)
103107

104108
if ($token instanceof TokenInterface) {
105109
$token = $this->refreshUser($token);
110+
111+
if (null === $token && null !== $this->rememberMeServices) {
112+
$this->rememberMeServices->loginFail($request);
113+
}
106114
} elseif (null !== $token) {
107115
if (null !== $this->logger) {
108116
$this->logger->warning('Expected a security token from the session, got something else.', ['key' => $this->sessionKey, 'received' => $token]);

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

+42
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\Security\Http\Tests\Firewall;
1313

14+
use PHPUnit\Framework\Assert;
1415
use PHPUnit\Framework\TestCase;
1516
use Symfony\Component\EventDispatcher\EventDispatcher;
1617
use Symfony\Component\HttpFoundation\Request;
@@ -24,13 +25,16 @@
2425
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
2526
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
2627
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
28+
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
2729
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
2830
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
2931
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
3032
use Symfony\Component\Security\Core\User\User;
3133
use Symfony\Component\Security\Core\User\UserInterface;
3234
use Symfony\Component\Security\Core\User\UserProviderInterface;
3335
use Symfony\Component\Security\Http\Firewall\ContextListener;
36+
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
37+
use Symfony\Component\Security\Http\Tests\RememberMe\AbstractRememberMeServicesTest;
3438

3539
class ContextListenerTest extends TestCase
3640
{
@@ -316,6 +320,26 @@ public function testRuntimeExceptionIsThrownIfNoSupportingUserProviderWasRegiste
316320
$this->handleEventWithPreviousSession(new TokenStorage(), [new NotSupportingUserProvider(), new NotSupportingUserProvider()]);
317321
}
318322

323+
public function testLogoutOnChangeEventAsBeenSent()
324+
{
325+
$tokenStorage = new TokenStorage();
326+
$refreshedUser = new User('foobar', 'baz');
327+
328+
$user = new User('foo', 'bar');
329+
330+
$session = new Session(new MockArraySessionStorage());
331+
$session->set('_security_context_key', serialize(new UsernamePasswordToken($user, '', 'context_key', ['ROLE_USER'])));
332+
333+
$request = new Request();
334+
$request->setSession($session);
335+
$request->cookies->set('MOCKSESSID', true);
336+
$listener = new ContextListener($tokenStorage, [new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser)], 'context_key', null, null, null, new testRememberMeServices($this));
337+
$listener->setLogoutOnUserChange($refreshedUser);
338+
$listener->handle(new GetResponseEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $request, HttpKernelInterface::MASTER_REQUEST));
339+
340+
$this->assertNull($tokenStorage->getToken());
341+
}
342+
319343
public function testAcceptsProvidersAsTraversable()
320344
{
321345
$tokenStorage = new TokenStorage();
@@ -387,6 +411,24 @@ public function supportsClass($class)
387411
}
388412
}
389413

414+
class testRememberMeServices implements RememberMeServicesInterface
415+
{
416+
417+
public function autoLogin(Request $request)
418+
{
419+
}
420+
421+
public function loginFail(Request $request, \Exception $exception = null)
422+
{
423+
Assert::assertTrue($request->cookies->get('MOCKSESSID'));
424+
return null;
425+
}
426+
427+
public function loginSuccess(Request $request, Response $response, TokenInterface $token)
428+
{
429+
}
430+
}
431+
390432
class SupportingUserProvider implements UserProviderInterface
391433
{
392434
private $refreshedUser;

0 commit comments

Comments
 (0)