-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Security] Deprecated not being logged out after user change #23882
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
Test failure not related to this PR it seems |
Woohoo! I'll try to review this tonight. Simple patch... but I'd like to try it in a few situations to check for side effects. About deprecating this in 3.4 and actually changing it in 4.0, I think I agree. It's a potentially impactful change... and a non-obvious one (if you upgraded to 3.4 and the new code logged you out, you might not notice this at first - as it may only affect an edge-case situation). Due to the fact that this may only happen in some situations, the deprecation also isn't a perfect notifier, but it'll give people a better chance. |
Actually, on second thought, the deprecation is not quite right: there is no action the developer could take on 3.4 to stop hitting the deprecation. Instead, it's just a warning that says "hey! This code path will change in the future". Then, on 4.0, they will have different results than 3.4. That's a problem, since it's not how we intend for deprecations to work. @iltar wdyt about this? |
@weaverryan it's a default behavior change that can break a lot of things, so I feel a deprecation is in place. However, you're right about this being kind of passive. What about a temporary parameter that you can turn on to trigger an exception here? Could be done in a similar fashion to several changes in 2.8 and 3.0, like swapping the choice keys/values, where the option gets removed for 5.0. I'm not entirely sure on how to pass a message to the front-end though. |
$this->logger->debug('Token was deauthenticated after trying to refresh it.', array('username' => $refreshedUser->getUsername(), 'provider' => get_class($provider))); | ||
} | ||
|
||
@trigger_error('Refreshing a deauthenticated user is deprecated as of 3.4 and will trigger a logout in 4.0.', E_USER_DEPRECATED); |
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.
a changelog+upgrade entries would be great
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 will add them as soon as I know how to proceed with the actual logging out users, as this might need more additions to the changelog and upgrade entries 👍
Yea, it seems to me, that we indeed do need to do something similar to the choice keys/values thing. Perhaps someone else has an idea but I think it's a good start. So, we could add the following config: security:
firewall:
main:
logout_on_user_change: true If this new config key is NOT set, then we'll trigger the deprecation warning. This would require everyone to set this value explicitly (to true or false)... which is kind of annoying, but super explicit. In 4.0, this option would still exist, but would throw an exception if not set. Then, if we wanted, in 5.0, it could default to This is the most conservative option I can think of: it absolutely doesn't break BC... but it's also kind of annoying. If you can't think of a better idea, let's do this first - it's easier to get a +1 or -1 from people if we're looking at real code. |
Such key should not be mandatory for |
@iltar Would you have time to finish this? I can try to help otherwise, feature freeze is coming. |
@chalasr I'll put it on my todo list for upcoming Friday |
I've updated the code to actually return null in the case where the context is set to true. I have not yet added this config to the firewall, I first wanted to know if this is okay. It doesn't trigger a message for the user after it was unset though, not sure if that's possible to add in this scenario. |
Not sure if the test failures are something I can fix, seems to be an issue because it pulls in a different version than what my PR provides |
@iltar - thanks a lot for looking into this! Very much appreciated. In the meantime should we update the page at https://symfony.com/doc/current/security/entity_provider.html#understanding-serialize-and-how-a-user-is-saved-in-the-session, especially the line of "For example, if the username on the 2 User objects doesn't match for some reason, then the user will be logged out for security reasons". At the moment it sounds like the appropriate description there should be "it checks the properties to determine if the roles should be reloaded" Just an example right here how people follow this guidance and accept answers (hope they test all that, to find out it is not working): https://stackoverflow.com/questions/42877881/symfony-check-if-users-email-changed-while-logged-in Also, when you currently change behind the scenes what the isEnabled() function returns between requests, it will log the user out (it is just other properties for which it does not log out the user), do you know where this behvaiour is triggered? Finally, is there any workaround at the moment for this - to logout the user if any serialized properties change? Cheers! |
I guess you can reproduce a similar result by overriding some of the pre-defined classes and change the behavior in the authenticators, not 100% sure on that as it's quite a complicated change. |
UPGRADE-3.4.md
Outdated
@@ -269,6 +269,11 @@ SecurityBundle | |||
as first argument. Not passing it is deprecated and will throw a `TypeError` | |||
in 4.0. | |||
|
|||
* Added `logout_on_user_change` to the firewall options. This config item will | |||
trigger a logout when the user has changed. should be set to true to avoid |
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.
should -> Should
@@ -13,6 +13,10 @@ CHANGELOG | |||
* `SetAclCommand::__construct()` now takes an instance of | |||
`Symfony\Component\Security\Acl\Model\MutableAclProviderInterfaceConnection` | |||
as first argument | |||
* Added `logout_on_user_change` to the firewall options. This config item will | |||
trigger a logout when the user has changed. should be set to true to avoid |
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.
should -> Should
status: Needs Review |
@@ -198,7 +220,7 @@ protected function refreshUser(TokenInterface $token) | |||
} | |||
|
|||
if ($userNotFoundByProvider) { | |||
return; | |||
return null; |
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.
To be reverted as it should be applied to the 2.7 branch. But it is worth a dedicated PR on the whole codebase. Related to #17201.
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.
Will fix
In that case, I've added a note here. It feels a bit weird having a non-deprecated method that does nothing in 4.0, but it's even weirder to have a fresh installation of 4.0 cause a deprecation. |
Great to see that finally being taken care of 👍 |
@@ -61,14 +61,23 @@ public function __construct(TokenStorageInterface $tokenStorage, $userProviders, | |||
|
|||
$this->tokenStorage = $tokenStorage; | |||
$this->userProviders = $userProviders; | |||
$this->contextKey = $contextKey; |
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 we need to deprecate the constructor argument if the class doesn't need it anymore. That can be done in another PR, could you revert this change (with the property removal)?
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.
It's still used for the sessionKey
below. Only the property is removed because it's not used. (However again, it could have been done on the 2.7 branch ^^)
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.
Correct, I've merely removed the property because the property wasn't used anymore. If desired, I can change this in a lower branch instead.
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.
@iltar that would be nice
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.
see #24329
…tar) This PR was merged into the 2.7 branch. Discussion ---------- Added null as explicit return type (?TokenInterface) | Q | A | ------------- | --- | Branch? | 2.7 | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #23882 (comment) | License | MIT | Doc PR | ~ This fixes the returntype in the `ContextListener` so it can be merged upwards. /cc @chalasr Commits ------- 1ba4dd9 Added null as explicit return type (?TokenInterface)
…iltar) This PR was merged into the 2.7 branch. Discussion ---------- Removed unused private property in the ContextListener | Q | A | ------------- | --- | Branch? | 2.7 | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #23882 (comment) | License | MIT | Doc PR | ~ The context property is unused, the local variable (constructor argument) is only concatenated to a string inside (session key). Commits ------- 6522c05 Removed unused private property
Thank you @iltar. |
…change (iltar) This PR was squashed before being merged into the 3.4 branch (closes #23882). Discussion ---------- [Security] Deprecated not being logged out after user change | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | yes | Tests pass? | yes | Fixed tickets | #17023 | License | MIT | Doc PR | ~ This PR is an alternative approach to #19033. Due to a behavioral change that could break a lot of applications and websites, I've decided to trigger a deprecation instead of actually changing the behavior as that can be done for 4.0. Whenever a user object is considered changed (`AbstractToken::hasUserChanged`) when setting a new user object after refreshing, it will now throw a deprecation, paving the way for a behavioral change in 4.0. The idea is that in 4.0 Symfony will simply trigger a logout when this case is encountered. Commits ------- 22f525b [Security] Deprecated not being logged out after user change
Woohoo! Thank you @iltar! |
Thank you very much @iltar! |
This works as expected for the session but when remember_me is used, the user remains logged in (and authenticated). How can I address this? |
@kbond would you mind opening an issue so we can keep track of this bug and discuss the possible solutions if needed? |
Ok, opened issue #24525 |
oh, |
@eXtreme guard is affected. |
This PR is an alternative approach to #19033. Due to a behavioral change that could break a lot of applications and websites, I've decided to trigger a deprecation instead of actually changing the behavior as that can be done for 4.0.
Whenever a user object is considered changed (
AbstractToken::hasUserChanged
) when setting a new user object after refreshing, it will now throw a deprecation, paving the way for a behavioral change in 4.0. The idea is that in 4.0 Symfony will simply trigger a logout when this case is encountered.