Skip to content

Commit

Permalink
[Security] Fix clearing remember-me cookie after deauthentication
Browse files Browse the repository at this point in the history
  • Loading branch information
Robin Chalas committed Nov 30, 2019
1 parent 8b123e7 commit 2ddb064
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 1 deletion.
11 changes: 11 additions & 0 deletions Firewall/ContextListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
use Symfony\Component\Security\Core\Role\SwitchUserRole;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;

/**
* ContextListener manages the SecurityContext persistence through a session.
Expand All @@ -44,6 +45,7 @@ class ContextListener implements ListenerInterface
private $registered;
private $trustResolver;
private $logoutOnUserChange = false;
private $rememberMeServices;

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

if ($token instanceof TokenInterface) {
$token = $this->refreshUser($token);

if (!$token && $this->logoutOnUserChange && $this->rememberMeServices) {
$this->rememberMeServices->loginFail($request);
}
} elseif (null !== $token) {
if (null !== $this->logger) {
$this->logger->warning('Expected a security token from the session, got something else.', ['key' => $this->sessionKey, 'received' => $token]);
Expand Down Expand Up @@ -268,4 +274,9 @@ public static function handleUnserializeCallback($class)
{
throw new \UnexpectedValueException('Class not found: '.$class, 0x37313bc);
}

public function setRememberMeServices(RememberMeServicesInterface $rememberMeServices)
{
$this->rememberMeServices = $rememberMeServices;
}
}
20 changes: 19 additions & 1 deletion Tests/Firewall/ContextListenerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Http\Firewall\ContextListener;
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;

class ContextListenerTest extends TestCase
{
Expand Down Expand Up @@ -278,6 +279,19 @@ public function testIfTokenIsNotDeauthenticated()
$this->assertSame($goodRefreshedUser, $tokenStorage->getToken()->getUser());
}

public function testRememberMeGetsCanceledIfTokenIsDeauthenticated()
{
$tokenStorage = new TokenStorage();
$refreshedUser = new User('foobar', 'baz');

$rememberMeServices = $this->createMock(RememberMeServicesInterface::class);
$rememberMeServices->expects($this->once())->method('loginFail');

$this->handleEventWithPreviousSession($tokenStorage, [new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser)], null, true, $rememberMeServices);

$this->assertNull($tokenStorage->getToken());
}

public function testTryAllUserProvidersUntilASupportingUserProviderIsFound()
{
$tokenStorage = new TokenStorage();
Expand Down Expand Up @@ -347,7 +361,7 @@ protected function runSessionOnKernelResponse($newToken, $original = null)
return $session;
}

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

$listener = new ContextListener($tokenStorage, $userProviders, 'context_key');
$listener->setLogoutOnUserChange($logoutOnUserChange);

if ($rememberMeServices) {
$listener->setRememberMeServices($rememberMeServices);
}
$listener->handle(new GetResponseEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $request, HttpKernelInterface::MASTER_REQUEST));
}
}
Expand Down

0 comments on commit 2ddb064

Please sign in to comment.