Skip to content

Commit 2ddb064

Browse files
author
Robin Chalas
committed
[Security] Fix clearing remember-me cookie after deauthentication
1 parent 8b123e7 commit 2ddb064

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

Firewall/ContextListener.php

+11
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
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\RememberMeServicesInterface;
3031

3132
/**
3233
* ContextListener manages the SecurityContext persistence through a session.
@@ -44,6 +45,7 @@ class ContextListener implements ListenerInterface
4445
private $registered;
4546
private $trustResolver;
4647
private $logoutOnUserChange = false;
48+
private $rememberMeServices;
4749

4850
/**
4951
* @param iterable|UserProviderInterface[] $userProviders
@@ -103,6 +105,10 @@ public function handle(GetResponseEvent $event)
103105

104106
if ($token instanceof TokenInterface) {
105107
$token = $this->refreshUser($token);
108+
109+
if (!$token && $this->logoutOnUserChange && $this->rememberMeServices) {
110+
$this->rememberMeServices->loginFail($request);
111+
}
106112
} elseif (null !== $token) {
107113
if (null !== $this->logger) {
108114
$this->logger->warning('Expected a security token from the session, got something else.', ['key' => $this->sessionKey, 'received' => $token]);
@@ -268,4 +274,9 @@ public static function handleUnserializeCallback($class)
268274
{
269275
throw new \UnexpectedValueException('Class not found: '.$class, 0x37313bc);
270276
}
277+
278+
public function setRememberMeServices(RememberMeServicesInterface $rememberMeServices)
279+
{
280+
$this->rememberMeServices = $rememberMeServices;
281+
}
271282
}

Tests/Firewall/ContextListenerTest.php

+19-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
use Symfony\Component\Security\Core\User\UserInterface;
3232
use Symfony\Component\Security\Core\User\UserProviderInterface;
3333
use Symfony\Component\Security\Http\Firewall\ContextListener;
34+
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
3435

3536
class ContextListenerTest extends TestCase
3637
{
@@ -278,6 +279,19 @@ public function testIfTokenIsNotDeauthenticated()
278279
$this->assertSame($goodRefreshedUser, $tokenStorage->getToken()->getUser());
279280
}
280281

282+
public function testRememberMeGetsCanceledIfTokenIsDeauthenticated()
283+
{
284+
$tokenStorage = new TokenStorage();
285+
$refreshedUser = new User('foobar', 'baz');
286+
287+
$rememberMeServices = $this->createMock(RememberMeServicesInterface::class);
288+
$rememberMeServices->expects($this->once())->method('loginFail');
289+
290+
$this->handleEventWithPreviousSession($tokenStorage, [new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser)], null, true, $rememberMeServices);
291+
292+
$this->assertNull($tokenStorage->getToken());
293+
}
294+
281295
public function testTryAllUserProvidersUntilASupportingUserProviderIsFound()
282296
{
283297
$tokenStorage = new TokenStorage();
@@ -347,7 +361,7 @@ protected function runSessionOnKernelResponse($newToken, $original = null)
347361
return $session;
348362
}
349363

350-
private function handleEventWithPreviousSession(TokenStorageInterface $tokenStorage, $userProviders, UserInterface $user = null, $logoutOnUserChange = false)
364+
private function handleEventWithPreviousSession(TokenStorageInterface $tokenStorage, $userProviders, UserInterface $user = null, $logoutOnUserChange = false, RememberMeServicesInterface $rememberMeServices = null)
351365
{
352366
$user = $user ?: new User('foo', 'bar');
353367
$session = new Session(new MockArraySessionStorage());
@@ -359,6 +373,10 @@ private function handleEventWithPreviousSession(TokenStorageInterface $tokenStor
359373

360374
$listener = new ContextListener($tokenStorage, $userProviders, 'context_key');
361375
$listener->setLogoutOnUserChange($logoutOnUserChange);
376+
377+
if ($rememberMeServices) {
378+
$listener->setRememberMeServices($rememberMeServices);
379+
}
362380
$listener->handle(new GetResponseEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $request, HttpKernelInterface::MASTER_REQUEST));
363381
}
364382
}

0 commit comments

Comments
 (0)