[Security] Fixed SwitchUserListener when exiting an impersonication with AnonymousToken
If you configure a firewall with switch user with `role: IS_AUTHENTICATED_ANONYMOUSLY` it's impossible to exit the impersonation because the next line `$this->provider->refreshUser($original->getUser())` will fail. It fails because `RefreshUser` expects an instance of `UserInterface` and here it's a string. Therefore, it does not make sense to refresh an Anonymous Token, right ?
This commit is contained in:
parent
131436525f
commit
59fea72a43
@ -13,6 +13,7 @@ namespace Symfony\Component\Security\Http\Firewall;
|
||||
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
use Symfony\Component\Security\Core\SecurityContextInterface;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
use Symfony\Component\Security\Core\User\UserCheckerInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
|
||||
@ -162,7 +163,7 @@ class SwitchUserListener implements ListenerInterface
|
||||
throw new AuthenticationCredentialsNotFoundException('Could not find original Token object.');
|
||||
}
|
||||
|
||||
if (null !== $this->dispatcher) {
|
||||
if (null !== $this->dispatcher && $original->getUser() instanceof UserInterface) {
|
||||
$user = $this->provider->refreshUser($original->getUser());
|
||||
$switchEvent = new SwitchUserEvent($request, $user);
|
||||
$this->dispatcher->dispatch(SecurityEvents::SWITCH_USER, $switchEvent);
|
||||
|
@ -149,6 +149,54 @@ class SwitchUserListenerTest extends \PHPUnit_Framework_TestCase
|
||||
$listener->handle($this->event);
|
||||
}
|
||||
|
||||
public function testExitUserDoesNotDispatchEventWithStringUser()
|
||||
{
|
||||
$originalUser = 'anon.';
|
||||
$refreshedUser = $this->getMock('Symfony\Component\Security\Core\User\UserInterface');
|
||||
$this
|
||||
->userProvider
|
||||
->expects($this->never())
|
||||
->method('refreshUser');
|
||||
$originalToken = $this->getToken();
|
||||
$originalToken
|
||||
->expects($this->any())
|
||||
->method('getUser')
|
||||
->willReturn($originalUser);
|
||||
$role = $this
|
||||
->getMockBuilder('Symfony\Component\Security\Core\Role\SwitchUserRole')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$role
|
||||
->expects($this->any())
|
||||
->method('getSource')
|
||||
->willReturn($originalToken);
|
||||
$this
|
||||
->securityContext
|
||||
->expects($this->any())
|
||||
->method('getToken')
|
||||
->willReturn($this->getToken(array($role)));
|
||||
$this
|
||||
->request
|
||||
->expects($this->any())
|
||||
->method('get')
|
||||
->with('_switch_user')
|
||||
->willReturn('_exit');
|
||||
$this
|
||||
->request
|
||||
->expects($this->any())
|
||||
->method('getUri')
|
||||
->willReturn('/');
|
||||
|
||||
$dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
|
||||
$dispatcher
|
||||
->expects($this->never())
|
||||
->method('dispatch')
|
||||
;
|
||||
|
||||
$listener = new SwitchUserListener($this->securityContext, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager, null, '_switch_user', 'ROLE_ALLOWED_TO_SWITCH', $dispatcher);
|
||||
$listener->handle($this->event);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Security\Core\Exception\AccessDeniedException
|
||||
*/
|
||||
|
Reference in New Issue
Block a user