-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Security] Fix user role restriction. #35533
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
It was impossible to restrict user roles on the fly without deauthentication.
Can you add a test case please? |
@gorshkov-ag Can you explain a bit what you mean with that? |
I have some user roles in application and need a possibility to switch them without changing user or user roles. |
Added test cases. Updated rule don't compare count of current user roles with count of applicable roles. |
@oleg-andreyev could you please have a look, since this changes the logic from #31177? |
@@ -276,7 +276,7 @@ private function hasUserChanged(UserInterface $user): bool | |||
$userRoles[] = 'ROLE_PREVIOUS_ADMIN'; | |||
} | |||
|
|||
if (\count($userRoles) !== \count($this->getRoleNames()) || \count($userRoles) !== \count(array_intersect($userRoles, $this->getRoleNames()))) { | |||
if (\count($this->getRoleNames()) !== \count(array_intersect($this->getRoleNames(), $userRoles))) { |
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 you please update also
$rolesChanged = \count($currentRoles) !== \count($newRoles) || \count($currentRoles) !== \count(array_intersect($currentRoles, $newRoles)); |
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.
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.
Now is it problem in User equals test: User without role now is equivalent with user with role "ROLE", but opposite is not true.
https://github.com/gorshkov-ag/symfony/blob/9de09f0cfbfed2af1f7ae0a63597171615a51ac3/src/Symfony/Component/Security/Core/Tests/User/UserTest.php#L120
@@ -72,5 +72,53 @@ public function getSalt() | |||
$token = new SwitchUserToken($impersonated, 'bar', 'provider-key', ['ROLE_USER', 'ROLE_PREVIOUS_ADMIN'], $originalToken); | |||
$token->setUser($impersonated); | |||
$this->assertTrue($token->isAuthenticated()); | |||
|
|||
$impersonator = new class() implements UserInterface { |
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.
I think it's better to create a separate unit for this
|
||
$token = new SwitchUserToken($impersonator, 'foo', 'provider-key', ['ROLE_TEST', 'ROLE_PREVIOUS_ADMIN'], $originalToken); | ||
$token->setUser($impersonator); | ||
$this->assertFalse($token->isAuthenticated()); |
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.
assertFalse
contradicts with the unit name testSetUserDoesNotDeauthenticate
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.
The current behavior is the expected one. Removing a role must trigger deauthentication. |
Not removing role for user, just for token to use one or some user roles, not all of them. |
The token roles must contain all the roles of the user it holds. There is no valid use case for having a token that knows only part of the user roles, as it does not reflect the real state of the user. |
I think this default behavior of de-authenticating on any role change seems good. So not sure we should change anything here as @chalasr said. @gorshkov-ag maybe for your usecase its enough to make your user implement |
Closing as I agree with @chalasr |
@fabpot this has bitten us after symfony4.4 upgrade because by default we give ROLE_USER role but when user accesses admin panel (separate symfony instance which shares session with main website) and he is in the list of admins we add ROLE_ADMIN for him. After symfony upgrade this does not work anymore as adding ROLE_ADMIN deauthenticates user. This is one of the multiple breaking changes in symfony authentication in minor versions we have to deal with :/ |
@jmalinens its hard (impossible) to anticipate every possible way people are using symfony and rely on behavior that was never intended 😉 So see the positive side here: now this makes things more secure by default. If you need to restore the previous behavior its quite simple: make your user implement |
@jmalinens I'm not aware of your implementation but you need to make sure that you ADD not REPLACE your ROLE_USER. Probably |
Thanks guys. |
It was impossible to restrict user roles on the fly without deauthentication.
Allowed to restrict current user roles without changing roles for user object.