Skip to content

json_login_ldap in chain with json_login and new authenticator #41892

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

Open
oliverreese opened this issue Jun 29, 2021 · 27 comments
Open

json_login_ldap in chain with json_login and new authenticator #41892

oliverreese opened this issue Jun 29, 2021 · 27 comments
Labels
Bug Help wanted Issues and PRs which are looking for volunteers to complete them. Security Status: Reviewed

Comments

@oliverreese
Copy link

Symfony version(s) affected: 5.3.2

Description
a combination of json_login_ldap and json_login will not work when the new authentication manager is enabled. They both
on their own work properly but not in combination. When new authentication manager is disabled they work properly together
in a chain.

How to reproduce
see attached repository with 4 different configuration cases to reproduce:
https://github.com/oliverreese/symfony-security-ldap-login

Possible Solution

Additional context

@OskarStark
Copy link
Contributor

cc @wouterj

@xabbuh xabbuh added the Security label Jul 1, 2021
@raphaelriehl
Copy link

raphaelriehl commented Oct 18, 2021

Hi, maybe it's another issue, but I encounter same thing with form_login and form_login_ldap.
When I disable the new authentication manager it's works.
Same problem describe here.

@diversantvlz
Copy link
Contributor

diversantvlz commented Nov 2, 2021

here when the parent method is called, the base authenticator is replaced another with a different config. Parent method have hardcoded service id

@B4rb4ross4
Copy link

I can reproduce this issue aswell. I have the following firewall config:

main:
            lazy: true
            provider: app_user_provider
            user_checker: Some\Namespace\Infrastructure\Security\UnconfirmedUserChecker
            entry_point: 'form_login_ldap'
            form_login:
                login_path: login
                check_path: login
            form_login_ldap:
                service: Symfony\Component\Ldap\Ldap
                dn_string: 'MyOrganization\{username}'
                login_path: login
                check_path: ldap_login_check
            logout:
                path: logout

Then you can see that the wrong options are injected into the "normal" form login authenticator.

array (
  'username_parameter' => '_username',
  'password_parameter' => '_password',
  'check_path' => 'ldap_login_check',
  'post_only' => true,
  'form_only' => false,
  'enable_csrf' => false,
  'csrf_parameter' => '_csrf_token',
  'csrf_token_id' => 'authenticate',
  'login_path' => 'login',
  'use_forward' => false,
  'require_previous_session' => false,
)

@franzwilding
Copy link
Contributor

I also can produce the problem with SH 6.0.1: When using only the form_login_ldap authenticator, everything is working, however if I also add form_login (entry_point: 'form_login_ldap') the LDAP authenticator is not called.

@B4rb4ross4
Copy link

The problem is exactly in the place @diversantvlz linked. There is an optimization in place which shares the form_login config for all authenticators for all firewalls and that simply does not work and it breaks all the ldap decorators aswell.

@B4rb4ross4
Copy link

With symfony/security-bundle v6.0.3 the same error now occurs when disabling the new authentication manager.

@wiser
Copy link

wiser commented Mar 29, 2022

Same problem here chaining form_loginand form_login_ldap with symfony/security-bundle v5.4.5 (LTS).

Somebody else describes the same issue here : https://stackoverflow.com/questions/71576619/symfony-6-security-login-from-two-providers-entity-and-ldap => The post has been deleted...

For now I changed back for the old way to configure it disabling the authenticator manager...

@wiser
Copy link

wiser commented Apr 8, 2022

Does it take a big effort to solve this issue ?
I don’t realize how difficult it could be.
It seems a piece of code is shared for optimization, so is it "just" the upper linked part by @diversantvlz which needs to be reviewed ?

@raphaelriehl
Copy link

raphaelriehl commented Sep 28, 2022

Is there any news about fix this problem ?

@chalasr
Copy link
Member

chalasr commented Sep 28, 2022

Talking for myself, the reasons for not looking into this "naturally" are that I don't suffer from this bug and it's about ldap which I don't use and for which I don't have the required setup to reproduce locally. If you can, please have a look into this so you can come up with a patch to propose in a PR.

@Padam87
Copy link
Contributor

Padam87 commented Dec 1, 2022

@B4rb4ross4 's example is good.

LdapFactoryTrait calls the parent method, which overrides the service added by the form_login part, because it has the same name.

https://github.com/symfony/symfony/blob/6.3/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/LdapFactoryTrait.php#L38

Changing $firewallName to $firewallName.'_ldap' fixes it by avoiding the override.

@chalasr This is not really an LDAP issue, just a naming clash... Solutions:

  1. Add a suffix to the firewall name like above - hacky
  2. Remove the parent call - a lot of code duplication
  3. Add a parameter for service name - breaking

(Nr 1 might not be an option, as it would break success and failure handlers)

@OskarStark OskarStark changed the title json_login_ldap in chain with json_login and new authenticator json_login_ldap in chain with json_login and new authenticator Dec 1, 2022
@wouterj
Copy link
Member

wouterj commented Dec 1, 2022

If I read correctly, the issue is not adding a _ldap suffix to $kid here, resulting in the same service ID for both LDAP and non-LDAP authenticator:

$ldapAuthenticatorId = 'security.authenticator.'.$key.'.'.$firewallName;

Anyone up for a PR?

@Padam87
Copy link
Contributor

Padam87 commented Dec 1, 2022

@wouterj Unfortunately it is not that easy. The line you mentioned is fine, because $key already has an ldap suffix, and works fine.

The problem is that the LdapAuthenticator is a wrapper around another auhtenticator, passed as the 1st argument.

public function __construct(AuthenticatorInterface $authenticator, string $ldapServiceId, string $dnString = '{user_identifier}', string $searchDn = '', string $searchPassword = '', string $queryString = '')

The inner authenticator is created here:

$authenticatorId = parent::createAuthenticator($container, $firewallName, $config, $userProviderId);

Which makes sense, always call the parent, either form_login, json_login etc, but this created inner service will have the same name as a regular form_login authenticator.

$authenticatorId = parent::createAuthenticator($container, $firewallName, $config, $userProviderId);
$authenticatorId = parent::createAuthenticator($container, $firewallName.'_ldap', $config, $userProviderId);

This change fixes it, but the $firewallName parameter is also used for actual firewall related code, so that whould break for example success and failure handlers.
There is no other way to change the name of the inner service.

https://github.com/symfony/symfony/blob/6.3/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/FormLoginFactory.php#L70

@wouterj
Copy link
Member

wouterj commented Dec 4, 2022

Thanks for the explanation, this is clear to me now.

I've written a failing test case showing what is going wrong: 6.3...wouterj:symfony:issue-41892/ldap-decoration Let us know in this thread if you're working on fixing this in Symfony (you can use my commit as a start) :)

@wouterj wouterj added Status: Reviewed Help wanted Issues and PRs which are looking for volunteers to complete them. and removed Status: Needs Review labels Dec 4, 2022
@carsonbot
Copy link

Hey, thanks for your report!
There has not been a lot of activity here for a while. Is this bug still relevant? Have you managed to find a workaround?

@etiennerousseau
Copy link

Hi,
For me the bug is still relevant.

I find a workaround by developing a custom LoginFormAuthenticator which test if he can (in my context) do the authentification (with the supports() method). If not the authentification is done by the Ldap Authenticator.

@carsonbot
Copy link

Hey, thanks for your report!
There has not been a lot of activity here for a while. Is this bug still relevant? Have you managed to find a workaround?

@chalasr
Copy link
Member

chalasr commented Jan 14, 2024

Anyone up to work on this?

@MindfulPol
Copy link

MindfulPol commented May 28, 2024

Hello there 👋🏿 ,
@xopino and myself have been pair programming a bit. Together we came up with a possible approach to resolve the issue.

We've iterated the test provided by @wouterj , thnx for that, please let us know what you think :)

@MindfulPol
Copy link

MindfulPol commented Jun 1, 2024

Closing the first pull request to fix the bug on the earlier mantained branch, aKa 5.4 🤗

There's one issue about the test, given the enable_authenticator_manager parameter was removed, tests will break starting at 6.2, by removing the param it will work fine again, how should we take that into account?

@vasanth-kumar-m-y
Copy link

vasanth-kumar-m-y commented Jun 14, 2024

Is there a way to implement both form_login for in memory users and form_login_ldap for ldap users on same firewall
using Symfony 6.4

@MindfulPol @oliverreese @franzwilding @wouterj @Padam87 @OskarStark

@luggesexe
Copy link

Having the same issue on 6.3.12 as @vasanth-kumar-m-y, the authenticator does not seem to work with both in place. The form_login sets the fail response and no later authenticator is called. That way in_memory and LDAP can not co-exist.

@keichitokuna
Copy link

keichitokuna commented Jul 17, 2024

Hello,
I spend two days trying to understand why form_login wasn't working with form_login_ldap.

I have this security.yaml:

providers:
        local_users:
            entity:
                class: App\Entity\User
                property: username
        ldap_users:
            ldap:
                service: Symfony\Component\Ldap\Ldap
                base_dn: '%env(LDAP_BASE_DN)%'
                search_dn: '%env(LDAP_SEARCH_DN)%'
                search_password: '%env(LDAP_SEARCH_PASSWORD)%'
                uid_key: "uid"
        all_users:
            chain:
                providers: ['ldap_users', 'local_users']
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            lazy: true
            provider: all_users
            entry_point: form_login
            form_login_ldap:
                service: Symfony\Component\Ldap\Ldap
                login_path: app_login
                check_path: app_login
                enable_csrf: true
                dn_string: '%env(LDAP_BASE_DN)%'
                query_string: '(uid={user_identifier})'
                search_dn: '%env(LDAP_SEARCH_DN)%'
                search_password: '%env(LDAP_SEARCH_PASSWORD)%'
            form_login:
                login_path: app_login
                check_path: app_login
                enable_csrf: true

But everytime, form_login sets the fail response and the form_login_ldap is never called...

Anyone succeeded with that ?
Thanks

@vasanth-kumar-m-y
Copy link

It doesn't work on same firewall. Need to use Custom Authenticator https://symfony.com/doc/current/security/custom_authenticator.html

@carsonbot
Copy link

Hey, thanks for your report!
There has not been a lot of activity here for a while. Is this bug still relevant? Have you managed to find a workaround?

@vasanth-kumar-m-y
Copy link

vasanth-kumar-m-y commented Jan 23, 2025

yes @carsonbot, it worked using Custom Authenticator https://symfony.com/doc/current/security/custom_authenticator.html

@carsonbot carsonbot removed the Stalled label Jan 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Help wanted Issues and PRs which are looking for volunteers to complete them. Security Status: Reviewed
Projects
None yet
Development

No branches or pull requests