Search code examples
phpauthenticationsilex

Custom authentication provider in silex application


I try to write custom authentication provider for LDAP-authentication using silex documentation - Defining a custom Authentication Provider.

But if I look into $app['security.authentication_providers'] there are two providers. One that I defined App\LdapAuthenticationProvider and one Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationProvider

And when I try to authorize user I get error because there is call of a App\LdapUserProvider::loadUserByUsername() from class DaoAuthenticationProvider.

If I would have only one provider in $app['security.authentication_providers'] I think I should not get error because my LDAP-provider do not call loadUserByUsername.

Here is dump of $app['security.authentication_providers']

array (size=2)
  0 => object(App\LdapAuthenticationProvider)[194]
    private 'userProvider' => 
      object(App\LdapUserProvider)[176]
        private 'ldap' => resource(57, ldap link)
        private 'defaultRoles' => 
          array (size=1)
          ...
    private 'providerKey' => string 'default' (length=7)
  1 => object(Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationProvider)[195]
    private 'encoderFactory' => 
      object(Symfony\Component\Security\Core\Encoder\EncoderFactory)[197]
        private 'encoders' => 
          array (size=1)
          ...
    private 'userProvider' => 
      object(App\LdapUserProvider)[176]
        private 'ldap' => resource(57, ldap link)
        private 'defaultRoles' => 
          array (size=1)
          ...
    private 'hideUserNotFoundExceptions' (Symfony\Component\Security\Core\Authentication\Provider\UserAuthenticationProvider) => boolean true
    private 'userChecker' (Symfony\Component\Security\Core\Authentication\Provider\UserAuthenticationProvider) => object(Symfony\Component\Security\Core\User\UserChecker)[196]
    private 'providerKey' (Symfony\Component\Security\Core\Authentication\Provider\UserAuthenticationProvider) => string 'default' (length=7)

So, does anybody know why there are extra provider and how can I get rid of it?

There are code for bootstraping application, LdapAuthenticationListener and LdapAuthenticationProvider.


Solution

  • Problem is solved.

    I've just extended my LdapAuthenticationListener class with symfony2 UsernamePasswordFormAuthenticationListener and change bootstarp like this:

    $app['security.authentication_listener.factory.ldap'] = $app->protect(
        function ($name, $options) use ($app) {
            $app['security.authentication_provider.'.$name.'.ldap'] = $app->share(
                function () use ($app) {
                    return new LdapAuthenticationProvider(
                        $app['security.user_provider.default'],
                        'ldap'
                    );
                }
            );
    
            $app['security.authentication_listener.'.$name.'.ldap'] = $app->share(
                function () use ($app, $name, $options) {
                    $app['security.authentication.success_handler.'.$name] =
                        $app['security.authentication.success_handler._proto']($name, $options);
                    $app['security.authentication.failure_handler.'.$name] =
                        $app['security.authentication.failure_handler._proto']($name, $options);
    
                    return new LdapAuthenticationListener(
                        $app['security'],
                        $app['security.authentication_manager'],
                        $app['security.session_strategy'],
                        $app['security.http_utils'],
                        $name,
                        $app['security.authentication.success_handler.'.$name],
                        $app['security.authentication.failure_handler.'.$name],
                        array_merge(
                            array(
                                'check_path' => '/admin/login_check',
                                'login_path' => '/login',
                            ),
                            $options
                        ),
                        $app['logger'],
                        $app['dispatcher'],
                        null
                    );
                }
            );
    
            return array(
                'security.authentication_provider.'.$name.'.ldap',
                'security.authentication_listener.'.$name.'.ldap',
                null,
                'pre_auth'
            );
        }
    

    I need custom authentication listener to overwrite token in authentication method and authentication provider retrieve user from user provider by username and password $this->userProvider->loadUserByUsernameAndPassword($usernam, $password)