From 1088e329ea2ee61fa1414f199bb5b35dbcb28174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?p=C3=A9c=C3=A9?= Date: Mon, 4 May 2020 00:01:10 +0200 Subject: [PATCH 1/3] Adds SwitchUserTokenInterface --- .../DataCollector/SecurityDataCollector.php | 6 ++--- .../Authentication/Token/AbstractToken.php | 4 ++-- .../Authentication/Token/SwitchUserToken.php | 9 +++++-- .../Token/SwitchUserTokenInterface.php | 24 +++++++++++++++++++ .../Voter/AuthenticatedVoter.php | 4 ++-- 5 files changed, 38 insertions(+), 9 deletions(-) create mode 100644 src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserTokenInterface.php diff --git a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php index 9bd7c005757bb..6fbf638609ffd 100644 --- a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php +++ b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php @@ -19,7 +19,7 @@ use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; -use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken; +use Symfony\Component\Security\Core\Authentication\Token\SwitchUserTokenInterface; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Symfony\Component\Security\Core\Authorization\TraceableAccessDecisionManager; use Symfony\Component\Security\Core\Authorization\Voter\TraceableVoter; @@ -96,8 +96,8 @@ public function collect(Request $request, Response $response, \Throwable $except $assignedRoles = $token->getRoleNames(); $impersonatorUser = null; - if ($token instanceof SwitchUserToken) { - $impersonatorUser = $token->getOriginalToken()->getUsername(); + if ($token instanceof SwitchUserTokenInterface && null !== $originalToken = $token->getOriginalToken()) { + $impersonatorUser = $originalToken->getUsername(); } if (null !== $this->roleHierarchy) { diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php index 9106334b99e8b..7b912debb1f57 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php @@ -272,8 +272,8 @@ private function hasUserChanged(UserInterface $user): bool $userRoles = array_map('strval', (array) $user->getRoles()); - if ($this instanceof SwitchUserToken) { - $userRoles[] = 'ROLE_PREVIOUS_ADMIN'; + if ($this instanceof SwitchUserTokenInterface) { + $userRoles[] = $this->getSwitchingAdditionalRole(); } if (\count($userRoles) !== \count($this->getRoleNames()) || \count($userRoles) !== \count(array_intersect($userRoles, $this->getRoleNames()))) { diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserToken.php index 4177cee658f69..66b522db3e5c5 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserToken.php @@ -16,7 +16,7 @@ * * @author Christian Flothmann */ -class SwitchUserToken extends UsernamePasswordToken +class SwitchUserToken extends UsernamePasswordToken implements SwitchUserTokenInterface { private $originalToken; @@ -35,11 +35,16 @@ public function __construct($user, $credentials, string $providerKey, array $rol $this->originalToken = $originalToken; } - public function getOriginalToken(): TokenInterface + public function getOriginalToken(): ?TokenInterface { return $this->originalToken; } + public function getSwitchingAdditionalRole(): string + { + return 'ROLE_PREVIOUS_ADMIN'; + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserTokenInterface.php b/src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserTokenInterface.php new file mode 100644 index 0000000000000..681efcc0586f0 --- /dev/null +++ b/src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserTokenInterface.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Core\Authentication\Token; + +/** + * SwitchUserTokenInterface is the interface for a switch user token. + * + * @author Pierre-Charles Bertineau + */ +interface SwitchUserTokenInterface extends TokenInterface +{ + public function getOriginalToken(): ?TokenInterface; + + public function getSwitchingAdditionalRole(): string; +} diff --git a/src/Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.php b/src/Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.php index d571a7e9379b3..25d711421299c 100644 --- a/src/Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.php +++ b/src/Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Security\Core\Authorization\Voter; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface; -use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken; +use Symfony\Component\Security\Core\Authentication\Token\SwitchUserTokenInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** @@ -84,7 +84,7 @@ public function vote(TokenInterface $token, $subject, array $attributes) return VoterInterface::ACCESS_GRANTED; } - if (self::IS_IMPERSONATOR === $attribute && $token instanceof SwitchUserToken) { + if (self::IS_IMPERSONATOR === $attribute && $token instanceof SwitchUserTokenInterface) { return VoterInterface::ACCESS_GRANTED; } } From 61ecb3a69b30d4d870e6545c0b4327ccd88179fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?p=C3=A9c=C3=A9?= Date: Mon, 4 May 2020 13:08:01 +0200 Subject: [PATCH 2/3] Remove useless added role (Sf 5.1 compliance) --- .../Security/Core/Authentication/Token/AbstractToken.php | 4 ++-- .../Security/Core/Authentication/Token/SwitchUserToken.php | 5 ----- .../Core/Authentication/Token/SwitchUserTokenInterface.php | 2 -- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php index 7b912debb1f57..9106334b99e8b 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php @@ -272,8 +272,8 @@ private function hasUserChanged(UserInterface $user): bool $userRoles = array_map('strval', (array) $user->getRoles()); - if ($this instanceof SwitchUserTokenInterface) { - $userRoles[] = $this->getSwitchingAdditionalRole(); + if ($this instanceof SwitchUserToken) { + $userRoles[] = 'ROLE_PREVIOUS_ADMIN'; } if (\count($userRoles) !== \count($this->getRoleNames()) || \count($userRoles) !== \count(array_intersect($userRoles, $this->getRoleNames()))) { diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserToken.php index 66b522db3e5c5..a1619e9e4cf57 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserToken.php @@ -40,11 +40,6 @@ public function getOriginalToken(): ?TokenInterface return $this->originalToken; } - public function getSwitchingAdditionalRole(): string - { - return 'ROLE_PREVIOUS_ADMIN'; - } - /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserTokenInterface.php b/src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserTokenInterface.php index 681efcc0586f0..2ec14512629b2 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserTokenInterface.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserTokenInterface.php @@ -19,6 +19,4 @@ interface SwitchUserTokenInterface extends TokenInterface { public function getOriginalToken(): ?TokenInterface; - - public function getSwitchingAdditionalRole(): string; } From 1f598c642b9deefc880e08aa4bf220f1ba022b82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?p=C3=A9c=C3=A9?= Date: Mon, 4 May 2020 15:28:33 +0200 Subject: [PATCH 3/3] Renamed interface to differenciate impersonation case of specific switch user case --- .../SecurityBundle/DataCollector/SecurityDataCollector.php | 4 ++-- ...kenInterface.php => ImpersonatedUserTokenInterface.php} | 7 +++++-- .../Security/Core/Authentication/Token/SwitchUserToken.php | 5 ++++- .../Core/Authorization/Voter/AuthenticatedVoter.php | 4 ++-- 4 files changed, 13 insertions(+), 7 deletions(-) rename src/Symfony/Component/Security/Core/Authentication/Token/{SwitchUserTokenInterface.php => ImpersonatedUserTokenInterface.php} (67%) diff --git a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php index 6fbf638609ffd..69967d3992441 100644 --- a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php +++ b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php @@ -18,8 +18,8 @@ use Symfony\Component\HttpKernel\DataCollector\DataCollector; use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; +use Symfony\Component\Security\Core\Authentication\Token\ImpersonatedUserTokenInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; -use Symfony\Component\Security\Core\Authentication\Token\SwitchUserTokenInterface; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Symfony\Component\Security\Core\Authorization\TraceableAccessDecisionManager; use Symfony\Component\Security\Core\Authorization\Voter\TraceableVoter; @@ -96,7 +96,7 @@ public function collect(Request $request, Response $response, \Throwable $except $assignedRoles = $token->getRoleNames(); $impersonatorUser = null; - if ($token instanceof SwitchUserTokenInterface && null !== $originalToken = $token->getOriginalToken()) { + if ($token instanceof ImpersonatedUserTokenInterface && null !== $originalToken = $token->getOriginalToken()) { $impersonatorUser = $originalToken->getUsername(); } diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserTokenInterface.php b/src/Symfony/Component/Security/Core/Authentication/Token/ImpersonatedUserTokenInterface.php similarity index 67% rename from src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserTokenInterface.php rename to src/Symfony/Component/Security/Core/Authentication/Token/ImpersonatedUserTokenInterface.php index 2ec14512629b2..c5591a7866241 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserTokenInterface.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/ImpersonatedUserTokenInterface.php @@ -12,11 +12,14 @@ namespace Symfony\Component\Security\Core\Authentication\Token; /** - * SwitchUserTokenInterface is the interface for a switch user token. + * ImpersonatedUserTokenInterface is the interface for an impersonated user token. * * @author Pierre-Charles Bertineau */ -interface SwitchUserTokenInterface extends TokenInterface +interface ImpersonatedUserTokenInterface extends TokenInterface { + /** + * Provides original token if available. + */ public function getOriginalToken(): ?TokenInterface; } diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserToken.php index a1619e9e4cf57..29ed9b5c685c5 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/SwitchUserToken.php @@ -16,7 +16,7 @@ * * @author Christian Flothmann */ -class SwitchUserToken extends UsernamePasswordToken implements SwitchUserTokenInterface +class SwitchUserToken extends UsernamePasswordToken implements ImpersonatedUserTokenInterface { private $originalToken; @@ -35,6 +35,9 @@ public function __construct($user, $credentials, string $providerKey, array $rol $this->originalToken = $originalToken; } + /** + * {@inheritdoc} + */ public function getOriginalToken(): ?TokenInterface { return $this->originalToken; diff --git a/src/Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.php b/src/Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.php index 25d711421299c..8daa1f510c0c3 100644 --- a/src/Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.php +++ b/src/Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Security\Core\Authorization\Voter; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface; -use Symfony\Component\Security\Core\Authentication\Token\SwitchUserTokenInterface; +use Symfony\Component\Security\Core\Authentication\Token\ImpersonatedUserTokenInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** @@ -84,7 +84,7 @@ public function vote(TokenInterface $token, $subject, array $attributes) return VoterInterface::ACCESS_GRANTED; } - if (self::IS_IMPERSONATOR === $attribute && $token instanceof SwitchUserTokenInterface) { + if (self::IS_IMPERSONATOR === $attribute && $token instanceof ImpersonatedUserTokenInterface) { return VoterInterface::ACCESS_GRANTED; } }