From 97edc98438873a03fe80ef5725b396104dbe44e0 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 4 Feb 2020 08:35:15 +0100 Subject: [PATCH 1/4] Add missing use statements --- Firewall.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Firewall.php b/Firewall.php index ee769496..133c4486 100644 --- a/Firewall.php +++ b/Firewall.php @@ -17,6 +17,7 @@ use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\Security\Http\Firewall\AbstractListener; use Symfony\Component\Security\Http\Firewall\AccessListener; use Symfony\Component\Security\Http\Firewall\LogoutListener; From ecdc0d1ddea712696d218563fd88d67d882bfd36 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 4 Feb 2020 09:03:00 +0100 Subject: [PATCH 2/4] Fix CS --- Logout/LogoutUrlGenerator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Logout/LogoutUrlGenerator.php b/Logout/LogoutUrlGenerator.php index 71a071f3..b00d34f9 100644 --- a/Logout/LogoutUrlGenerator.php +++ b/Logout/LogoutUrlGenerator.php @@ -52,7 +52,7 @@ public function registerListener($key, $logoutPath, $csrfTokenId, $csrfParameter if (\func_num_args() >= 6) { $context = func_get_arg(5); } else { - if (__CLASS__ !== \get_class($this)) { + if (__CLASS__ !== static::class) { $r = new \ReflectionMethod($this, __FUNCTION__); if (__CLASS__ !== $r->getDeclaringClass()->getName()) { @trigger_error(sprintf('The "%s()" method will have a 6th `string $context = null` argument in version 4.0. Not defining it is deprecated since Symfony 3.3.', __METHOD__), E_USER_DEPRECATED); From e3f826de0f10024cdc56282c9e0eabbda332e05b Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 4 Feb 2020 10:29:10 +0100 Subject: [PATCH 3/4] Fix CS --- Tests/Firewall/ContextListenerTest.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Tests/Firewall/ContextListenerTest.php b/Tests/Firewall/ContextListenerTest.php index 092f3e7e..0d053190 100644 --- a/Tests/Firewall/ContextListenerTest.php +++ b/Tests/Firewall/ContextListenerTest.php @@ -352,8 +352,9 @@ protected function runSessionOnKernelResponse($newToken, $original = null) $session->set('_security_session', $original); } - $tokenStorage = new UsageTrackingTokenStorage(new TokenStorage(), new class([ - 'session' => function () use ($session) { return $session; } + $tokenStorage = new UsageTrackingTokenStorage(new TokenStorage(), new class(['session' => function () use ($session) { + return $session; + }, ]) implements ContainerInterface { use ServiceLocatorTrait; }); @@ -404,8 +405,9 @@ private function handleEventWithPreviousSession($userProviders, UserInterface $u if (method_exists(Request::class, 'getPreferredFormat')) { $usageIndex = $session->getUsageIndex(); - $tokenStorage = new UsageTrackingTokenStorage($tokenStorage, new class([ - 'session' => function () use ($session) { return $session; } + $tokenStorage = new UsageTrackingTokenStorage($tokenStorage, new class(['session' => function () use ($session) { + return $session; + }, ]) implements ContainerInterface { use ServiceLocatorTrait; }); From 20abb20f18690e11f36ee6942d415a8ad09bbacb Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sun, 23 Feb 2020 15:53:58 +0100 Subject: [PATCH 4/4] [Security] Allow switching to another user when already switched --- Firewall/SwitchUserListener.php | 5 ++-- Tests/Firewall/SwitchUserListenerTest.php | 30 +++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/Firewall/SwitchUserListener.php b/Firewall/SwitchUserListener.php index 70492cc7..a5d077fb 100644 --- a/Firewall/SwitchUserListener.php +++ b/Firewall/SwitchUserListener.php @@ -134,7 +134,8 @@ private function attemptSwitchUser(Request $request, $username) return $token; } - throw new \LogicException(sprintf('You are already switched to "%s" user.', $token->getUsername())); + // User already switched, exit before seamlessly switching to another user + $token = $this->attemptExitUser($request); } if (false === $this->accessDecisionManager->decide($token, [$this->role])) { @@ -152,7 +153,7 @@ private function attemptSwitchUser(Request $request, $username) $this->userChecker->checkPostAuth($user); $roles = $user->getRoles(); - $roles[] = new SwitchUserRole('ROLE_PREVIOUS_ADMIN', $this->tokenStorage->getToken()); + $roles[] = new SwitchUserRole('ROLE_PREVIOUS_ADMIN', $token); $token = new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey, $roles); diff --git a/Tests/Firewall/SwitchUserListenerTest.php b/Tests/Firewall/SwitchUserListenerTest.php index f4060f46..ab77180e 100644 --- a/Tests/Firewall/SwitchUserListenerTest.php +++ b/Tests/Firewall/SwitchUserListenerTest.php @@ -191,6 +191,36 @@ public function testSwitchUser() $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $this->tokenStorage->getToken()); } + public function testSwitchUserAlreadySwitched() + { + $originalToken = new UsernamePasswordToken('original', null, 'key', ['ROLE_FOO']); + $alreadySwitchedToken = new UsernamePasswordToken('switched_1', null, 'key', [new SwitchUserRole('ROLE_PREVIOUS_ADMIN', $originalToken)]); + + $tokenStorage = new TokenStorage(); + $tokenStorage->setToken($alreadySwitchedToken); + + $targetUser = new User('kuba', 'password', ['ROLE_FOO', 'ROLE_BAR']); + $this->request->query->set('_switch_user', 'kuba'); + + $this->accessDecisionManager->expects($this->once()) + ->method('decide')->with($originalToken, ['ROLE_ALLOWED_TO_SWITCH']) + ->willReturn(true); + $this->userProvider->expects($this->once()) + ->method('loadUserByUsername') + ->with('kuba') + ->willReturn($targetUser); + $this->userChecker->expects($this->once()) + ->method('checkPostAuth')->with($targetUser); + + $listener = new SwitchUserListener($tokenStorage, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager, null, '_switch_user', 'ROLE_ALLOWED_TO_SWITCH', null, false); + $listener->handle($this->event); + + $this->assertSame([], $this->request->query->all()); + $this->assertSame('', $this->request->server->get('QUERY_STRING')); + $this->assertSame('kuba', $tokenStorage->getToken()->getUsername()); + $this->assertSame($originalToken, $tokenStorage->getToken()->getRoles()[2]->getSource()); + } + public function testSwitchUserWorksWithFalsyUsernames() { $token = new UsernamePasswordToken('username', '', 'key', ['ROLE_FOO']);