From 7152f0e4e292719cdeb8306076448036e025569b Mon Sep 17 00:00:00 2001 From: Wouter de Jong Date: Thu, 31 Oct 2024 18:01:31 +0100 Subject: [PATCH] [Security] Store original token in token storage when implicitly exiting impersonation --- Firewall/SwitchUserListener.php | 4 +++- Tests/Firewall/SwitchUserListenerTest.php | 6 +++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Firewall/SwitchUserListener.php b/Firewall/SwitchUserListener.php index 52a4ac3c..2fa04c04 100644 --- a/Firewall/SwitchUserListener.php +++ b/Firewall/SwitchUserListener.php @@ -109,7 +109,7 @@ public function authenticate(RequestEvent $event) } if (self::EXIT_VALUE === $username) { - $this->tokenStorage->setToken($this->attemptExitUser($request)); + $this->attemptExitUser($request); } else { try { $this->tokenStorage->setToken($this->attemptSwitchUser($request, $username)); @@ -221,6 +221,8 @@ private function attemptExitUser(Request $request): TokenInterface $original = $switchEvent->getToken(); } + $this->tokenStorage->setToken($original); + return $original; } diff --git a/Tests/Firewall/SwitchUserListenerTest.php b/Tests/Firewall/SwitchUserListenerTest.php index 0338af00..529c51e7 100644 --- a/Tests/Firewall/SwitchUserListenerTest.php +++ b/Tests/Firewall/SwitchUserListenerTest.php @@ -18,6 +18,7 @@ use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Symfony\Component\Security\Core\Exception\AccessDeniedException; @@ -228,7 +229,10 @@ public function testSwitchUserAlreadySwitched() $targetsUser = $this->callback(function ($user) { return 'kuba' === $user->getUserIdentifier(); }); $this->accessDecisionManager->expects($this->once()) - ->method('decide')->with($originalToken, ['ROLE_ALLOWED_TO_SWITCH'], $targetsUser) + ->method('decide')->with(self::callback(function (TokenInterface $token) use ($originalToken, $tokenStorage) { + // the token storage should also contain the original token for voters depending on it + return $token === $originalToken && $tokenStorage->getToken() === $originalToken; + }), ['ROLE_ALLOWED_TO_SWITCH'], $targetsUser) ->willReturn(true); $this->userChecker->expects($this->once())