[Security] Dispatch an event when "logout user on change" steps in
This commit is contained in:
parent
68439059d0
commit
40e42183b8
@ -23,6 +23,7 @@ CHANGELOG
|
||||
* Dispatch `SwitchUserEvent` on `security.switch_user`
|
||||
* Deprecated `Argon2iPasswordEncoder`, use `SodiumPasswordEncoder` instead
|
||||
* Deprecated `BCryptPasswordEncoder`, use `NativePasswordEncoder` instead
|
||||
* Added `DeauthenticatedEvent` dispatched in case the user has changed when trying to refresh it
|
||||
|
||||
4.2.0
|
||||
-----
|
||||
|
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Event;
|
||||
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* Deauthentication happens in case the user has changed when trying to refresh it.
|
||||
*
|
||||
* @author Hamza Amrouche <hamza.simperfit@gmail.com>
|
||||
*/
|
||||
class DeauthenticatedEvent extends Event
|
||||
{
|
||||
private $originalToken;
|
||||
private $refreshedToken;
|
||||
|
||||
public function __construct(TokenInterface $originalToken, TokenInterface $refreshedToken)
|
||||
{
|
||||
$this->originalToken = $originalToken;
|
||||
$this->refreshedToken = $refreshedToken;
|
||||
}
|
||||
|
||||
public function getRefreshedToken(): TokenInterface
|
||||
{
|
||||
return $this->refreshedToken;
|
||||
}
|
||||
|
||||
public function getOriginalToken(): TokenInterface
|
||||
{
|
||||
return $this->originalToken;
|
||||
}
|
||||
}
|
@ -28,6 +28,7 @@ use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
|
||||
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\Event\DeauthenticatedEvent;
|
||||
|
||||
/**
|
||||
* ContextListener manages the SecurityContext persistence through a session.
|
||||
@ -225,6 +226,10 @@ class ContextListener implements ListenerInterface
|
||||
$this->logger->debug('Token was deauthenticated after trying to refresh it.');
|
||||
}
|
||||
|
||||
if (null !== $this->dispatcher) {
|
||||
$this->dispatcher->dispatch(new DeauthenticatedEvent($token, $newToken), DeauthenticatedEvent::class);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
|
||||
use Symfony\Component\Security\Core\User\User;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
use Symfony\Component\Security\Http\Event\DeauthenticatedEvent;
|
||||
use Symfony\Component\Security\Http\Firewall\ContextListener;
|
||||
|
||||
class ContextListenerTest extends TestCase
|
||||
@ -313,6 +314,33 @@ class ContextListenerTest extends TestCase
|
||||
$this->assertSame($refreshedUser, $tokenStorage->getToken()->getUser());
|
||||
}
|
||||
|
||||
public function testDeauthenticatedEvent()
|
||||
{
|
||||
$tokenStorage = new TokenStorage();
|
||||
$refreshedUser = new User('foobar', 'baz');
|
||||
|
||||
$user = new User('foo', 'bar');
|
||||
$session = new Session(new MockArraySessionStorage());
|
||||
$session->set('_security_context_key', serialize(new UsernamePasswordToken($user, '', 'context_key', ['ROLE_USER'])));
|
||||
|
||||
$request = new Request();
|
||||
$request->setSession($session);
|
||||
$request->cookies->set('MOCKSESSID', true);
|
||||
|
||||
$eventDispatcher = new EventDispatcher();
|
||||
$eventDispatcher->addListener(DeauthenticatedEvent::class, function (DeauthenticatedEvent $event) use ($user) {
|
||||
$this->assertTrue($event->getOriginalToken()->isAuthenticated());
|
||||
$this->assertEquals($event->getOriginalToken()->getUser(), $user);
|
||||
$this->assertFalse($event->getRefreshedToken()->isAuthenticated());
|
||||
$this->assertNotEquals($event->getRefreshedToken()->getUser(), $user);
|
||||
});
|
||||
|
||||
$listener = new ContextListener($tokenStorage, [new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser)], 'context_key', null, $eventDispatcher);
|
||||
$listener(new RequestEvent($this->getMockBuilder(HttpKernelInterface::class)->getMock(), $request, HttpKernelInterface::MASTER_REQUEST));
|
||||
|
||||
$this->assertNull($tokenStorage->getToken());
|
||||
}
|
||||
|
||||
protected function runSessionOnKernelResponse($newToken, $original = null)
|
||||
{
|
||||
$session = new Session(new MockArraySessionStorage());
|
||||
|
Reference in New Issue
Block a user