-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[SecurityBundle] fix(security): user login programmatically with dedicated user checker on a firewall #54287
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
Sounds like a bugfix to me |
a93196b
to
be547b5
Compare
yes |
961db7e
to
2527d07
Compare
d5db9d8
to
e4ea9f8
Compare
@@ -98,6 +98,7 @@ public function load(array $configs, ContainerBuilder $container) | |||
{ | |||
if (!array_filter($configs)) { | |||
trigger_deprecation('symfony/security-bundle', '6.3', 'Enabling bundle "%s" and not configuring it is deprecated.', SecurityBundle::class); | |||
|
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.
fabbot cs fixer issue
@@ -424,6 +425,14 @@ private function createFirewall(ContainerBuilder $container, string $id, array $ | |||
$container->register('security.user_checker.chain.'.$id, ChainUserChecker::class) | |||
->addArgument(new TaggedIteratorArgument('security.user_checker.'.$id)); | |||
|
|||
// Register Firewall-specific user checker for 'security.helper' login() | |||
$securityUserCheckerLocator = $container->getDefinition('security.user_checker_locator'); |
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 "copied" such things for another locator
please tell me if its the right thing to do
@@ -127,7 +127,11 @@ public function login(UserInterface $user, ?string $authenticatorName = null, ?s | |||
|
|||
$authenticator = $this->getAuthenticator($authenticatorName, $firewallName); | |||
|
|||
$this->container->get('security.user_checker')->checkPreAuth($user); | |||
if ($this->container->get('security.user_checker_locator')->has('security.user_checker.'.$firewallName)) { | |||
$this->container->get('security.user_checker_locator')->get('security.user_checker.'.$firewallName)->checkPreAuth($user); |
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 is the PR fix: calling the proper firewall user checker if any
$securityUserCheckerLocator = $container->getDefinition('security.user_checker_locator'); | ||
$securityUserCheckerLocator | ||
->replaceArgument(0, array_merge($securityUserCheckerLocator->getArgument(0), [ | ||
'security.user_checker.'.$id => new ServiceClosureArgument(new Reference('security.user_checker.'.$id)), |
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.
You should reuse the chain defined just before
security.user_checker.chain.'.$id
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.
Thx for your comment
I fear not getting it, you mean i should add it in the locator or i should not use locator at all but inject this chained instead and use it in the security helper?
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'm not sure a locator is needed. There are already "ChainChecker" registered per firewall, that have all the checkers you reference there.
The problem is -imho- that no Event is triggered during this execution (there is one for the standard behaviour (see UserCheckerListener) login or SwitchUser) So the checkPreAuth is called only with the "main" UserChecker and not the one registered, as you already pointed.
I'm thinking instead of adding services there, it would maybe be prefereable to add a new Event ("manualLogin" -- with a better name haha) and plug the checkers in the same way they are called in the authentication events.
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.
Thanks for the ping.
I'm thinking instead of adding services there, it would maybe be prefereable to add a new Event
Indeed, relying on UserCheckerListener
sounds better. Maybe make it listen to a CheckUserEvent
in addition to CheckPassportEvent
? As this is a bugfix, that new event class should be internal at first. On 7.x we'll be able to make it public, dispatch it in the regular authentication flow and deprecate listening on CheckPassportEvent
in UserCheckerListener
.
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 try to find some time this week to address both of your reviews
Thx
9d29a40
to
29a65f9
Compare
@smnandre @chalasr I've push something related to our discussion please come back to me if it is what you had in mind, so I can continue if its the legit path |
…cated user checker on a firewall
29a65f9
to
6d1cf68
Compare
friendly ping 👋🏻 |
up please ? I really think this is important |
Sorry, had a lot going on those last weeks .. seems good to me, but my opinion will have no importance here. I think you should maybe add some tests for this new feature, and check the previous ones still pass :) |
@@ -127,7 +128,7 @@ public function login(UserInterface $user, ?string $authenticatorName = null, ?s | |||
|
|||
$authenticator = $this->getAuthenticator($authenticatorName, $firewallName); | |||
|
|||
$this->container->get('security.user_checker')->checkPreAuth($user); |
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.
not sure that this will solve #57706, security.user_checker
is still bound to InMemoryUserChecker
as default.
We probably need create service that will be aware about all user_checker's per firewall and based on firewall name, all required service.
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.
thanks for commenting
to be franc I've tested several things, see all PR force push
so for now I am quite waiting core devs hints
i do also have created a workaround on my project until core is fixed so for now it really dont bother much in a security POV on my side
Is it like my first approach on this PR (prior to reviews/force push) with a locator @xabbuh ? |
It really looks like that. Can you push your initial approach as I think you should then get the credit for the bugfix. |
Its not about the credit but more confirming my first understanding of this core code :) |
closing in favor of #57748 then 👍 |
@94noni Indeed. Looking again at the code, your original approach was correct. The My apologies for the confusion and thanks a lot for your work here. |
Original PR at #41274 as of Symfony v6.2 => so lets target v6.4 here
When defining an user checker on a firewall
This user checker logic for
checkPreAuth
is not called at all when using theSymfony/Bundle/SecurityBundle/Security::login
feature=> this can lead to unwanted security issue
In the reproducer, check the https://github.com/94noni/userchecker/blob/master/src/Security/UserChecker.php (logged in user must be enabled)
The controller https://github.com/94noni/userchecker/blob/master/src/Controller/AnonymousController.php get the user by its id and log
=> the user checker is not called and the user is logged in even if not enabled