Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.7k
[Security][SecurityBundle] Add is_granted feature for impersonator on AuthorizationChecker#28794
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
stof commentedOct 10, 2018
Adding such a method which is not part of the interface is a bad idea, as it would force to code against the implementation rather than the interface (which is not a supported usage of Symfony, as we allow ourselves to decorate services with a different implementation, and we do it regularly to implement the profiler features for instance). I think this should be implemented as a separate class (most of the logic is handled by the access decision manager anyway) |
FabienPapet commentedOct 10, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Agree, where do you think I should put this code ? Do you have any idea about a classname ? |
FabienPapet commentedOct 10, 2018
edited. ping@stof |
| use Symfony\Component\Security\Core\Role\SwitchUserRole; | ||
| /** | ||
| * SwitchUserAuthorizationChecker. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
this line is useless, as it does not provide additional information
| /** | ||
| * @param AccessDecisionManagerInterface $accessDecisionManager | ||
| * @param TokenStorageInterface $tokenStorage |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
imo this PHPDoc is not needed, as the arguments are typehinted, not sure about the member vars PHPDoc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
removed
| $token = $this->getOriginalToken($this->tokenStorage->getToken()); | ||
| if (false !== $token) { | ||
| return $this->accessDecisionManager->decide($token, $attributes, $subject); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
maybe checking for=== false first andreturn false? Not sure if its worth to switch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
IMO actual is better than switching which would give something like this
$token = $this->getOriginalToken($this->tokenStorage->getToken()); if (false === $token) { return false; } return $this->accessDecisionManager->decide($token, $attributes, $subject);| namespace Symfony\Component\Security\Core\Authorization; | ||
| /** | ||
| * The AuthorizationCheckerInterface. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
removed
ro0NL left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
im not sure separate handling of the two tokens makes sense (thus two twig functions etc.)
alternatively what about a default fallback mechanism? If the current token doesnt grant access, test the source token, if any. Optionally the security bundle could add configuration to white- and/or blacklist specific attributes. Does that make sense?
| /** | ||
| * @author Fabien Papet <fabien.papet@gmail.com> | ||
| */ | ||
| interface SwitchUserAuthorizationCheckerInterface |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
this duplicatesAuthorizationCheckerInterface basically, which looks odd
FabienPapet commentedOct 12, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
I'm not sure about using fallbacks. I think using a single is_granted can be confusing and can lead to errors (from a DX point of view). Maybe other Symfony contributors have an idea ? |
xabbuh commentedMar 8, 2019
I am not sure I understand the use case here. Can you elaborate a bit? |
FabienPapet commentedMar 8, 2019
The use case is pretty simple. The user admin can switch into a user. and sometimes on several screens, there are some actions that only the user admin can do. And I have to check the impersonator roles to acheive that |
xabbuh commentedMar 8, 2019
So if I understand this correctly, we are looking for a shortcut for |
FabienPapet commentedMar 8, 2019
No, because we can have different levels for user impersonation. And I want to check the roles of impersonator |
xabbuh commentedMar 8, 2019
What do you mean with different levels in this context? I am sorry to bother you with these questions but I would like to better understand the use case to see whether or not this fits in the Symfony core. |
FabienPapet commentedMar 8, 2019
That totally fine 👍 |
OskarStark commentedMar 8, 2019
I think this is not the goal of the impersonating. You should be the impersonated user with the exact roles, no matter from which role you did the impersonation... |
FabienPapet commentedMar 11, 2019
It is :) |
| * | ||
| * @return TokenInterface|false The original TokenInterface instance, false if the current TokenInterface is not switched | ||
| */ | ||
| private function getOriginalToken(TokenInterface $token) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
As of 4.3 you can simply check that the token is an instance ofSwitchUserToken and remove this method :). See#22048
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Code is from october2018 it didn't exist where I did this. I'll edit this evening
HeahDude commentedMar 11, 2019 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
What about a voter that checks for a We could then have a Twig function |
FabienPapet commentedMar 11, 2019
Maybe an IMPERSONATOR_ROLE_X to be consistent with RoleVoter ? |
HeahDude commentedMar 11, 2019 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
To be flexible this should be working with any attributes to trigger custom voters not just using roles or roles hierarchy. // ...class SwitchUserVoterextends Voter{private$prefix ='IMPERSONATOR_';private$accessDecisionManager;// ...publicfunctionsupports(...) {return0 ===strpos($attribute,$this->prefix); }publicfunctionvoteOnAttribute(...) {if (!$tokeninstanceof SwitchUserToken) {returnfalse; }return$this->accessDecisionManager->decide($token->getOriginalToken(), [substr($attribute,strlen($this->prefix))],$subject); }} That would allow both: {% is_granted('EDIT_POST',post)or impersonator_is_granted('MANAGE_POST',post) %}{# or with a custom prefix X_#}{% is_granted(['EDIT_POST','X_MANAGE_POST'],post) %}Plus the second example is valid for any call of |
HeahDude commentedMar 11, 2019
The prefix would be easier to decorate also in |
| class SwitchRoleVoter implements VoterInterface | ||
| { | ||
| /** | ||
| * @var AccessDecisionManager |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Can be removed since this is inferred from the controller.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
from the constructor* right ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Yes this auto correction is amazing some time :D
| continue; | ||
| } | ||
| return $this->accessDecisionManager->decide($token->getOriginalToken(), [substr($attribute, \strlen($this->prefix))], $subject); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
if (VoterInterface::ACCESS_GRANTED ===$result =$this->accessDecisionManager->decide($token->getOriginalToken(), [substr($attribute,\strlen($this->prefix))],$subject)) {return$result;}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Ah no this should just decorate the call forget that comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Hmm I think this is more complex, the current logic prevents passing two prefixed attributes, you should extend Voter to simplify the decoration or handle this case too IMHO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Without extending, you could go with:
$attributes =array_map(function ($attribute) {returnsubstr($attribute,\strlen($this->prefix));},array_filter($attributes,function ($attribute) {return0 ===strpos($attribute,$this->prefix) }));}));if (!$attributes) {return$result;}return$this->accessDecisionManager->decide($token->getOriginalToken(),$attributes,$subject);
WDYT?
fabpot commentedAug 11, 2020
Closing as I don't think this feature (as explained by@OskarStark) should be in core. |
Uh oh!
There was an error while loading.Please reload this page.
This feature adds a new is*Granted function for the user impersonating another user. I may need some help for tests and also for the function naming. A twig extension may be added if you want to (or in another PR).
Todo