Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[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

Closed
FabienPapet wants to merge1 commit intosymfony:masterfromFabienPapet:add-isgranted-impersonator
Closed

Conversation

@FabienPapet
Copy link

@FabienPapetFabienPapet commentedOct 9, 2018
edited
Loading

QA
Branch?master
Bug fix?no
New feature?yes
BC breaks?no
Deprecations?no
Tests pass?no test yet
LicenseMIT
Doc PRNot yet

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

  • Add doc
  • Add tests

OskarStark reacted with laugh emojiOskarStark and HeahDude reacted with heart emoji
@FabienPapetFabienPapet changed the titleAdd is_granted feature for impersonator on AuthorizationChecker[Security Bundle]Add is_granted feature for impersonator on AuthorizationCheckerOct 9, 2018
@stof
Copy link
Member

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
Copy link
Author

FabienPapet commentedOct 10, 2018
edited
Loading

Agree, where do you think I should put this code ? Do you have any idea about a classname ?
ImpersonatorAccessDecisionManagerSwithUserDecisionManager ?

@FabienPapet
Copy link
Author

edited. ping@stof

use Symfony\Component\Security\Core\Role\SwitchUserRole;

/**
* SwitchUserAuthorizationChecker.
Copy link
Contributor

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
Copy link
Contributor

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

Copy link
Author

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);
Copy link
Contributor

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

Copy link
Author

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);

OskarStark reacted with thumbs up emoji
namespace Symfony\Component\Security\Core\Authorization;

/**
* The AuthorizationCheckerInterface.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

needed?

FabienPapet reacted with thumbs up emoji
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

removed

OskarStark reacted with thumbs up emoji
@FabienPapetFabienPapet changed the title[Security Bundle]Add is_granted feature for impersonator on AuthorizationChecker[Security][SecurityBundle] Add is_granted feature for impersonator on AuthorizationCheckerOct 11, 2018
Copy link
Contributor

@ro0NLro0NL left a 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
Copy link
Contributor

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

OskarStark reacted with thumbs up emoji
@FabienPapet
Copy link
Author

FabienPapet commentedOct 12, 2018
edited
Loading

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 ?

@nicolas-grekasnicolas-grekas added this to thenext milestoneOct 14, 2018
@xabbuh
Copy link
Member

I am not sure I understand the use case here. Can you elaborate a bit?

@FabienPapet
Copy link
Author

The use case is pretty simple.
I have an app where I have a User, a user admin and an administrator.

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
Copy link
Member

So if I understand this correctly, we are looking for a shortcut foris_granted('ROLE_ALLOWED_TO_SWITCH')?

@FabienPapet
Copy link
Author

No, because we can have different levels for user impersonation. And I want to check the roles of impersonator

@xabbuh
Copy link
Member

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
Copy link
Author

That totally fine 👍
I mean the impersonator can be for example a manager, or a member of the application support.
Both manager and support can impersonate a user, but the manager can do some actions that the support team can not. I want to check this on the user list. Not sure if it's fully clear now

@OskarStark
Copy link
Contributor

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...
But if I understand you correct, this is the goal of the PR, right?

@FabienPapet
Copy link
Author

It is :)

OskarStark and HeahDude reacted with thumbs up emoji

*
* @return TokenInterface|false The original TokenInterface instance, false if the current TokenInterface is not switched
*/
private function getOriginalToken(TokenInterface $token)
Copy link
Contributor

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

Copy link
Author

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
Copy link
Contributor

HeahDude commentedMar 11, 2019
edited
Loading

What about a voter that checks for aIMPERSONATOR_ATTRIBUTE_X withIMPERSONATOR_ prefix configurable, it would early return false if the token is not an instance ofSwitchUserToken then remove the prefix before calling its decorated auth checker (we are no tied by circular dependency anymore, but the voter should be in the SecurityBundle though)?

We could then have a Twig functionimpersonator_is_granted('ATTRIBUTE_X') that adds the prefix before callingis_granted in thebridge security bundle too?

@FabienPapet
Copy link
Author

Maybe an IMPERSONATOR_ROLE_X to be consistent with RoleVoter ?

@HeahDude
Copy link
Contributor

HeahDude commentedMar 11, 2019
edited
Loading

To be flexible this should be working with any attributes to trigger custom voters not just using roles or roles hierarchy.
Using aSwitchUserVoter would get rid of that new interface, and would be simple to implement:

// ...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 ofisGranted() anywhere (that's what I mean by more flexible), while we can decorate the method easily in twig, in raw PHP it requires a new contract.

FabienPapet reacted with thumbs up emoji

@HeahDude
Copy link
Contributor

The prefix would be easier to decorate also inSecurity andControllerTrait helpers.

class SwitchRoleVoter implements VoterInterface
{
/**
* @var AccessDecisionManager
Copy link
Contributor

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.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

from the constructor* right ?

Copy link
Contributor

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);
Copy link
Contributor

@HeahDudeHeahDudeMar 11, 2019
edited
Loading

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;}

Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Contributor

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
Copy link
Member

Closing as I don't think this feature (as explained by@OskarStark) should be in core.

@fabpotfabpot closed thisAug 11, 2020
@FabienPapetFabienPapet deleted the add-isgranted-impersonator branchAugust 11, 2020 11:57
@nicolas-grekasnicolas-grekas modified the milestones:next,5.2Oct 5, 2020
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@OskarStarkOskarStarkOskarStark approved these changes

+2 more reviewers

@ro0NLro0NLro0NL left review comments

@HeahDudeHeahDudeHeahDude requested changes

Reviewers whose approvals may not affect merge requirements

Assignees

No one assigned

Projects

None yet

Milestone

5.2

Development

Successfully merging this pull request may close these issues.

9 participants

@FabienPapet@stof@xabbuh@OskarStark@HeahDude@fabpot@ro0NL@nicolas-grekas@carsonbot

[8]ページ先頭

©2009-2025 Movatter.jp