8000 [Security] Allow switching to another user when already switched · symfony/symfony@89effcf · GitHub
[go: up one dir, main page]

Skip to content

Commit 89effcf

Browse files
committed
[Security] Allow switching to another user when already switched
1 parent 159ef1b commit 89effcf

File tree

3 files changed

+37
-5
lines changed

3 files changed

+37
-5
lines changed

src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@ public function testSwitchUser($originalUser, $targetUser, $expectedUser, $expec
3333
$this->assertEquals($expectedUser, $client->getProfile()->getCollector('security')->getUser());
3434
}
3535

36-
public function testSwitchedUserCannotSwitchToOther()
36+
public function testSwitchedUserCanSwitchToOther()
3737
{
3838
$client = $this->createAuthenticatedClient('user_can_switch');
3939

4040
$client->request('GET', '/profile?_switch_user=user_cannot_switch_1');
4141
$client->request('GET', '/profile?_switch_user=user_cannot_switch_2');
4242

43-
$this->assertEquals(500, $client->getResponse()->getStatusCode());
44-
$this->assertEquals('user_cannot_switch_1', $client->getProfile()->getCollector('security')->getUser());
43+
$this->assertEquals(200, $client->getResponse()->getStatusCode());
44+
$this->assertEquals('user_cannot_switch_2', $client->getProfile()->getCollector('security')->getUser());
4545
}
4646

4747
public function testSwitchedUserExit()

src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ private function attemptSwitchUser(Request $request, $username)
134134
return $token;
135135
}
136136

137-
throw new \LogicException(sprintf('You are already switched to "%s" user.', $token->getUsername()));
137+
// User already switched, exit before seamlessly switching to another user
138+
$token = $this->attemptExitUser($request);
138139
}
139140

140141
if (false === $this->accessDecisionManager->decide($token, [$this->role])) {
@@ -152,7 +153,7 @@ private function attemptSwitchUser(Request $request, $username)
152153
$this->userChecker->checkPostAuth($user);
153154

154155
$roles = $user->getRoles();
155-
$roles[] = new SwitchUserRole('ROLE_PREVIOUS_ADMIN', $this->tokenStorage->getToken());
156+
$roles[] = new SwitchUserRole('ROLE_PREVIOUS_ADMIN', $token);
156157

157158
$token = new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey, $roles);
158159

src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Symfony\Component\HttpKernel\HttpKernelInterface;
1818
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
1919
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
20+
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
2021
use Symfony\Component\Security\Core\Role\SwitchUserRole;
2122
use Symfony\Component\Security\Core\User\User;
2223
use Symfony\Component\Security\Http\Event\SwitchUserEvent;
@@ -191,6 +192,36 @@ public function testSwitchUser()
191192
$this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $this->tokenStorage->getToken());
192193
}
193194

195+
public function testSwitchUserAlreadySwitched()
196+
{
197+
$originalToken = new UsernamePasswordToken('original', null, 'key', ['ROLE_FOO']);
198+
$alreadySwitchedToken = new UsernamePasswordToken('switched_1', null, 'key', [new SwitchUserRole('ROLE_PREVIOUS_ADMIN', $originalToken)]);
199+
200+
$tokenStorage = new TokenStorage();
201+
$tokenStorage->setToken($alreadySwitchedToken);
202+
203+
$targetUser = new User('kuba', 'password', ['ROLE_FOO', 'ROLE_BAR']);
204+
$this->request->query->set('_switch_user', 'kuba');
205+
206+
$this->accessDecisionManager->expects($this->once())
207+
->method('decide')->with($originalToken, ['ROLE_ALLOWED_TO_SWITCH'])
208+
->willReturn(true);
209+
$this->userProvider->expects($this->once())
210+
->method('loadUserByUsername')
211+
->with('kuba')
212+
->willReturn($targetUser);
213+
$this->userChecker->expects($this->once())
214+
->method('checkPostAuth')->with($targetUser);
215+
216+
$listener = new SwitchUserListener($tokenStorage, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager, null, '_switch_user', 'ROLE_ALLOWED_TO_SWITCH', null, false);
217+
$listener->handle($this->event);
218+
219+
$this->assertSame([], $this->request->query->all());
220+
$this->assertSame('', $this->request->server->get('QUERY_STRING'));
221+
$this->assertSame('kuba', $tokenStorage->getToken()->getUsername());
222+
$this->assertSame($originalToken, $tokenStorage->getToken()->getRoles()[2]->getSource());
223+
}
224+
194225
public function testSwitchUserWorksWithFalsyUsernames()
195226
{
196227
$token = new UsernamePasswordToken('username', '', 'key', ['ROLE_FOO']);

0 commit comments

Comments
 (0)
0