Skip to content

Commit

Permalink
bug #18425 [Security] Fixed SwitchUserListener when exiting an impers…
Browse files Browse the repository at this point in the history
…onation with AnonymousToken (lyrixx)

This PR was merged into the 2.3 branch.

Discussion
----------

[Security] Fixed SwitchUserListener when exiting an impersonation with AnonymousToken

| Q             | A
| ------------- | ---
| Branch?       | 2.3
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

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 ?

Commits
-------

59fea72 [Security] Fixed SwitchUserListener when exiting an impersonication with AnonymousToken
  • Loading branch information
fabpot committed Apr 5, 2016
2 parents 134a7c9 + 59fea72 commit 5b6da77
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 1 deletion.
Expand Up @@ -13,6 +13,7 @@

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;
Expand Down Expand Up @@ -162,7 +163,7 @@ private function attemptExitUser(Request $request)
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);
Expand Down
Expand Up @@ -149,6 +149,54 @@ public function testExitUserDispatchesEventWithRefreshedUser()
$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
*/
Expand Down

0 comments on commit 5b6da77

Please sign in to comment.