Nitecon / zfcuser-ldap

ZFCUser addon to provide LDAP authentication access.
BSD 3-Clause "New" or "Revised" License
15 stars 19 forks source link

ServiceManager could not locate ZfcUserLdap\Authentication\Adapter\Ldap #1

Closed aarbrown closed 11 years ago

aarbrown commented 11 years ago

Hello,

I followed your instructions in the README, although I was unsure of how to properly set up the ZfcUserLdap\Authentication\Adapter\Ldap so that the ServiceManager could get it. I ended up adding this to config/autoload/local.php: ... 'factories' => array( ... 'ZfcUserLdap\Authentication\Adapter\Ldap' => function ($sm) { return new ZfcUserLdap\Authentication\Adapter\Ldap; }, ... )

It seems to be working (though I am getting a fatal error which I believe is a separate issue). Is this how you would recommend setting it up?

Thanks

Nitecon commented 11 years ago

The service requires zfcuser, within the zfcuser config file is where you specify the use of the adapter itself. In the readme I note the following:

ZfcUser Configuration

For the initial release please make sure to set the following settings in your zfcuser configuration:

array(
    'enable_registration' => false,
    'enable_username' => true,
    'auth_adapters' => array( 100 => 'ZfcUserLdap\Authentication\Adapter\Ldap' ),
    'auth_identity_fields' => array( 'username','email' ),
),

The zfcuser configuration is separate from zfcuser-ldap module and you need to configure that part for this module to work as it is an addon to zfcuser, so to sum things up quickly what you will need to do is:

copy vendor/zf-commons/zfc-user/config/zfcuser.global.php.dist to config/autoload/zfcuser.global.php then open the file and edit it as per the instructions above. Thats all you need to do beyond setting the ldap array key and values for your ldap server as per the readme instructions.

aarbrown commented 11 years ago

It looks like my problems were due to my application.config.php. I changed it the order so that ZfcUserLdap loads after ZfcUser and it seems to be working. I thought I had already tried this configuration but I may have also had some ZfcUserLdap configuration errors at that time. Everything is working as expected now. Thanks for the great module!

trainerbill commented 11 years ago

I am getting the same error. I followed the directions except I just did a git clone of the repo to vendor/ZfcUserLdap. Do I have to use the composer.phar to install this module? I am also new to ZF2 so any help/explanations would be appreciated.

Putting 'ZfcUserLdap\Authentication\Adapter\Ldap' => 'ZfcUserLdap\ServiceFactory\LdapServiceFactory', in global.php under factories fixes the exeption. But I am still unable to authenticate so I'm not sure if it is still a problem.

I am now getting the error: Missing argument 2 for ZfcUserLdap\Service\LdapInterface::authenticate() in /home//git/ZendMVCTutorial/vendor/ZfcUserLdap/src/ZfcUserLdap/Service/LdapInterface.php on line 123

aarbrown commented 11 years ago

Hi trainerbill,

The problem in my situation was that I loaded ZfcUserLdap before loading ZfcUser in my zf2-app/config/application.config.php. I should have loaded ZfcUserLdap after ZfcUser (as Nitecon has noted in the Readme)

array( 'ZfcUser', 'ZfcUserLdap', /* It's important to load ZfcUser before ZfcUserLdap as ZfcUserLdap is an addon to ZfcUser */ );

hope that helps

trainerbill commented 11 years ago

Yeah I double checked that:

<?php return array( // This should be an array of module namespaces used in the application. 'modules' => array( 'Application', 'ZfcBase', 'ZfcUser', 'ZfcUserLdap',

),
aarbrown commented 11 years ago

Remove this bit 'ZfcUserLdap\Authentication\Adapter\Ldap' => 'ZfcUserLdap\ServiceFactory\LdapServiceFactory' from your global.php and double check your ldap credentials (the username / password and baseDn in particular).

You could also check the data/logs/ldap.log file if you are indeed failing ldap auth.

trainerbill commented 11 years ago

Still saying: ServiceManager could not locate ZfcUserLdap\Authentication\Adapter\Ldap. I don't get any files in root/data/logs/

Thanks for the help btw.

trainerbill commented 11 years ago

I validated my connection information:

$options = array(MY_OPTIONS); $ldap = new Zend\Ldap\Ldap($options); if($ldap->bind()) echo 'Bound'; else echo 'Unbound';

So my connect information is correct but I am still getting the error: Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for ZfcUserLdap\Authentication\Adapter\Ldap. Any ideas @Nitecon

witt commented 11 years ago

Same here! I think I'm getting the same error as @trainerbill

Zend\ServiceManager\Exception\ServiceNotFoundException File: /var/www/skeleton/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:496 Message: Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for ZfcUserLdap\Authentication\Adapter\Ldap

Stack Trace

0 /var/www/skeleton/vendor/zf-commons/zfc-user/src/ZfcUser/Authentication/Adapter/AdapterChainServiceFactory.php(26): Zend\ServiceManager\ServiceManager->get('ZfcUserLdap\Aut...')

... ...

I did follow all the instructions. I used Composer to add:

Any ideas?

Nitecon commented 11 years ago

I am currently on paternity leave I'll take a look as soon as I have some spare time

witt commented 11 years ago

@Nitecon thanks and congrats!

GehringerFlorian commented 11 years ago

Hi I've got the same problem ( unable to fetch or create an instance for ZfcUserLdap\Authentication\Adapter\Ldap). But I think it depends on "bjyoungblood/BjyAuthorize": "1.2.*": When I remove BjyAuthorize from modules It seams to work. But I don't want to remove BjyAuthorize. Any suggestions?

aarbrown commented 11 years ago

@GehringerFlorian - I am using BjyAuthorize and I don't have any issues with ZfcUserLdap. I'm not sure why it would be breaking yours.

trainerbill commented 11 years ago

@GehringerFlorian @aarbrown Can you guys explain your setup and how you got this working? I am running Apache PHP on Debian with the php-ldap module installed. I cloned the skeleton application, then cloned the ZfcBase, ZfcUser, and ZfcUserLdap modules into the vendor directory. I followd the rest of the setup documentation. I can manually create an LDAP adapter and successfully bind.

seg7 commented 11 years ago

Also have the same problem: Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for ZfcUserLdap\Authentication\Adapter\Ldap

Server configuration is loaded in ZDT, binding manually also works. No logs written.

amajot commented 11 years ago

I've been struggling with this exact same issue for about a week now but I think I solved the issue, can you guys see if you can replicate?

In the getServiceConfig() method inside of Module.php add this in the array:

'invokables' => array( 'ZfcUserLdap\Authentication\Adapter\Ldap' => 'ZfcUserLdap\Authentication\Adapter\Ldap', ),

I guess something changed in either ZF2 or zfcuser in the past couple months that requires that to be explicit or something? not sure ....

seg7 commented 11 years ago

Adding that code all i get is a blank page...

trainerbill commented 11 years ago

@commiejim Yeah I tried that a couple weeks ago. It does get you past the service manager issue but it still errors out with some sort of authenticate error. You will find the exact error in your apache error log, I can't remember what it is. I am not sure if that error is in addition to the service manager error or a result of the workaround.

amajot commented 11 years ago

Strange, after I added what I said above it is working like a dream? Writes to the ldap.log file, and i've tailed apache error logs and its showing nothing. I can authenticate successfully with my LDAP server and it all seems vanilla.

Do you have the PHP LDAP extension installed? I had that issue a while back but installed it and its fine after that.

seg7 commented 11 years ago

yes of course, otherwise i would be unable to bind manually. nothing appears on data/logs, zf is version 2.2.0. Just to clear it up what Module file did you modified? vendor/zf-commons/zfc-user/Module.php or vendor/nitecon/zfcuser-ldap/Module.php

Also i have not configured anything besides the required values in zfcuser...

there is also a problem with the route after i installed the ldap plugin was working fine before having only zfcuser.

The requested URL could not be matched by routing

Not commenting the zfcuser-ldap out of the config, i still have the problem (i have AllowOverride All in apache's vh set for the redirects)

amajot commented 11 years ago

Forgot that you mentioned that you could bind manually, my bad.

I have the same zf version as you too

I edited: vendor/nitecon/zfcuser-ldap/Module.php

Not sure what the routing issue could be, I didn't run into that. All I did was just move the zfcuser.global.php.dist file into the root ZF config/autoload, removed the .dist at the end, and did was was in the instructions.

seg7 commented 11 years ago

yeah, well i tried both files and it gives me the same :(

can u up your singleton app somewhere so i could compare it with mine?

Nitecon commented 11 years ago

I have a few minutes so I'm going to test a couple of my applications that are using this to make sure the fix that @commiejim noted works across the board and will put in a new commit for this regarding it. There has been similar stuff like this that has happened in the past and I will most likely start setting the composer libraries to work with specific versions of zf2 only so that this doesn't become a problem again.

trainerbill commented 11 years ago

That fix seems to work for me.

Nitecon commented 11 years ago

So far I haven't been able to replicate the problem yet, I did however update to the latest dev-master of zf2 but still no issues as listed above. I am going to try it with bjyoungblood/BjyAuthorize to see if I can replicate the problem. I will also create a seperate demo repository for use so you can verify your settings against what I currently have.

seg7 commented 11 years ago

Ok finally got it working with the fix, now is there possible to configure the basedn so it searches the entire subtree (scope)? Right now it only works if i point it to where the user is located.

GehringerFlorian commented 11 years ago

commiejim's fix solves my "...ServiceManager::get was unable to fetch or create ..." problem. Thanks a lot!

I'm using MS Active Directoy so I had to change some things:

vendor\nitecon\zfcuser-ldap\src\ZfcUserLdap\Service\LdapInterface.php

public function findByUsername($username)
 {
    try {
        $this->bind();
    } catch (\Exception $exc) {
        return $this->error;
    }
    try {
        $hm = $this->ldap->search("sAMAccountName=$username", $this->active_server['baseDn'], \Zend\Ldap\Ldap::SEARCH_SCOPE_ONE);
        foreach ($hm as $item) {
            $this->log($item);
            return $item;
        }
        return FALSE;
    } catch (LdapException $exc) {
        $msg = $exc->getMessage();
        $this->log($msg);
        return $msg;
    }
}

vendor\nitecon\zfcuser-ldap\src\ZfcUserLdap\Mapper\User.php

public function findByEmail($email)
{
    //...
    $this->entity->setId(0); //ToDo: Find Solution to work with Entity ...
    $this->entity->setUsername($obj['samaccountname']['0']);
    //...
}

public function findByUsername($username)
{
    //...
    $this->entity->setId(0); //ToDo: Find Solution to work with Entity ...
    $this->entity->setUsername($obj['samaccountname']['0']);
    //...
}

Now I'm able to Login. data\logs\ldap.log -> 2013-05-23T15:11:10+02:00 DEBUG (7): XXX logged in successfully!

But how can I get it working with the User-Entity? I'm using ZfcUserDoctrineORM.

bjyoungblood/BjyAuthorize says "403 Forbidden"

GehringerFlorian commented 11 years ago

Any errors in data\logs\ldap.log?

GehringerFlorian commented 11 years ago

Hi I think it works now for my special purpose using ZfcUserDoctrineORM AND MS Active Directory.

This is not deeply tested code! It's just a suggestion.

I did the following changes to the code:

vendor\nitecon\zfcuser-ldap\Module.php

<?PHP
    //...
    //old
        public function getServiceConfig() {
            return array(
                'factories' => array(
                    'zfcuser_ldap_service' => 'ZfcUserLdap\ServiceFactory\Ldap',
                    'ldap_interface' => 'ZfcUserLdap\ServiceFactory\LdapServiceFactory',
                    'zfcuser_module_options' => function ($sm) {
                        $config = $sm->get('Configuration');
                        return new Options\ModuleOptions(isset($config['zfcuser']) ? $config['zfcuser'] : array());
                    },
                    'zfcuser_user_mapper' => function ($sm) {
                        return new \ZfcUserLdap\Mapper\User(
                                $sm->get('ldap_interface'), $sm->get('zfcuser_module_options')
                        );
                    },
                ),
            );
        }
    //new
        public function getServiceConfig() {
            return array(
                'aliases' => array(
                    'zfcuser_doctrine_em' => 'doctrine.entitymanager.orm_default',
                ),
                'factories' => array(
                    'zfcuser_ldap_service' => 'ZfcUserLdap\ServiceFactory\Ldap',
                    'ldap_interface' => 'ZfcUserLdap\ServiceFactory\LdapServiceFactory',
                    'zfcuser_module_options' => function ($sm) {
                        $config = $sm->get('Configuration');
                        return new Options\ModuleOptions(isset($config['zfcuser']) ? $config['zfcuser'] : array());
                    },
                    'zfcuser_user_mapper' => function ($sm) {
                        return new \ZfcUserLdap\Mapper\User(
                                $sm->get('ldap_interface'), 
                                $sm->get('zfcuser_doctrine_em'),
                                $sm->get('zfcuser_module_options')
                        );
                    },
                ),
                // Thanks a lot to commiejim for the tip
                'invokables' => array(
                    'ZfcUserLdap\Authentication\Adapter\Ldap' => 'ZfcUserLdap\Authentication\Adapter\Ldap',
                ),
            );
        }
    //...
?>

vendor\nitecon\zfcuser-ldap\src\ZfcUserLdap\Authentication\Adapter\Ldap.php

<?PHP
    //...
    //old
        use ZfcUserLdap\Mapper\User as UserMapperInterface;
    //new
        use ZfcUserDoctrineORM\Mapper\User as UserMapperInterface; 
    //...
    //old
        $mapper = new \ZfcUserLdap\Mapper\User(
            $this->getServiceManager()->get('ldap_interface'), $this->getServiceManager()->get('zfcuser_module_options')
        );
    //new
        $mapper = new \ZfcUserLdap\Mapper\User(
            $this->getServiceManager()->get('ldap_interface'), 
            $this->getServiceManager()->get('zfcuser_doctrine_em'),
            $this->getServiceManager()->get('zfcuser_module_options')
        );
    //...
?>

vendor\nitecon\zfcuser-ldap\src\ZfcUserLdap\Mapper\User.php

<?PHP
    //...
    //old
        use ZfcUser\Mapper\User as ZfcUserMapper;
        use ZfcUserLdap\Options\ModuleOptions;
    //new
        use ZfcUserDoctrineORM\Mapper\User as ZfcUserMapper;
        use ZfcUserDoctrineORM\Options\ModuleOptions;
        use Doctrine\ORM\EntityManager;
    //...
    //old
        /**
         * @var \ZfcUserLdap\Options\ModuleOptions
         */
        protected $options;
        public function __construct(LdapInterface $ldap, ModuleOptions $options)
        {
            $this->ldap      = $ldap;
            $this->options = $options;
            $entityClass = $this->options->getUserEntityClass();
            $this->entity = new $entityClass();
        }
    //new
        /**
         * @var \Doctrine\ORM\EntityManager
         */
        protected $em;

        /**
         * @var \ZfcUserDoctrineORM\Options\ModuleOptions
         */
        protected $options;
        public function __construct(LdapInterface $ldap, EntityManager $em, ModuleOptions $options)
        {
            $this->ldap      = $ldap;
            $this->em      = $em;
            $this->options = $options;
            $entityClass = $this->options->getUserEntityClass();
            $this->entity = new $entityClass();
        }
    //...
    //remove function findByEmail
    //remove function findByUsername
    //remove function findById
    //remove function insert
    //remove function update
    //...
?>

vendor\nitecon\zfcuser-ldap\src\ZfcUserLdap\Options\ModuleOptions.php

<?PHP
    //...
    //old
        use ZfcUser\Options\ModuleOptions as BaseModuleOptions;
    //new
        use ZfcUserDoctrineORM\Options\ModuleOptions as BaseModuleOptions;
    //...
?>

vendor\nitecon\zfcuser-ldap\src\ZfcUserLdap\Service\LdapInterface.php

<?PHP
    //...
    //old
        public function findByUsername($username) {
            try {
                $this->bind();
            } catch (\Exception $exc) {
                return $this->error;
            }
            $entryDN = "uid=$username," . $this->active_server['baseDn'];
            try {
                $hm = $this->ldap->getEntry($entryDN);
                return $hm;
            } catch (LdapException $exc) {
                return $exc->getMessage();
            }
        }
    //new
        public function findByUsername($username) {
            try {
                $this->bind();
            } catch (\Exception $exc) {
                return $this->error;
            }
            try {
                $hm = $this->ldap->search("sAMAccountName=$username", $this->active_server['baseDn'], \Zend\Ldap\Ldap::SEARCH_SCOPE_ONE);
                foreach ($hm as $item) {
                    $this->log($item);
                    return $item;
                }
                return FALSE;
            } catch (LdapException $exc) {
                $msg = $exc->getMessage();
                $this->log($msg);
                return $msg;
            }
        }
    //...
?>

Greetings from rainy Germany Florian

Nitecon commented 11 years ago

The module was never developed to handle active directory in the entity manager as I don't have an AD server to test / dev against. But it's something that will be in the works in the near future. For now I will add in the commit as suggested by adding the invokables.

Nitecon commented 11 years ago

Closing this issue as it appears the fix as per @commiejim has provided the permanent fix. Next up will be working on making zfcuser-ldap available on active directory as well as providing the ability to specify your own user mapper.

m1st0 commented 9 years ago

With @GehringerFlorian 's changes for Active Directory, I got it working on my part except for the setId porton on line 42 and 55 of "vendor\nitecon\zfcuser-ldap\src\ZfcUserLdap\Mapper\User.php" as he had it:

$this->entity->setId(0); //ToDo: Find Solution to work with Entity ...

I found the following solution which cleared up "NOTICE (5): Undefined index: uidnumber {"errno":8,"file":".../vendor/nitecon/zfcuser-ldap/src/ZfcUserLdap/Mapper/User.php","line":55}"

 $this->entity->setId($obj['dn']['0']);

The notice is cleared, but I have a way to go. It appears successful in the log file returning all the correct LDAP info, but the "/user/login" page still relates "Authentication failed. Please try again." I got the idea from https://www.drupal.org/node/1899336 .

Nitecon commented 8 years ago

If you would like to provide a pull request then I'll be happy to merge it in.

Sent from my Verizon Wireless 4G LTE smartphone

-------- Original message -------- From: navlan21 notifications@github.com Date: 2015/09/18 5:27 PM (GMT-05:00) To: Nitecon/zfcuser-ldap zfcuser-ldap@noreply.github.com Cc: Willem Hattingh w.hattingh@nitecon.com Subject: Re: [zfcuser-ldap] ServiceManager could not locate ZfcUserLdap\Authentication\Adapter\Ldap (#1)

PLEASE NOTE THIS, the initial issue on this thread was wrong class name. Setting in documentation has ZfcUserLdap\Authentication\Adapter\Ldap While it should be ZfcUserLdap\Authentication\Adapter\LdapAuth

array( 'enable_registration' => false, 'enable_username' => true, 'auth_adapters' => array( 100 => 'ZfcUserLdap\Authentication\Adapter\Ldap' ), //<--- this should be LdapAuth 'auth_identity_fields' => array( 'username','email' ), ),

Reply to this email directly or view it on GitHubhttps://github.com/Nitecon/zfcuser-ldap/issues/1#issuecomment-141573072.

navlan21 commented 8 years ago

Hi,I am not sure if that was really the issue.ZfcUserLdap still not working for me.

  From: Will <notifications@github.com>

To: Nitecon/zfcuser-ldap zfcuser-ldap@noreply.github.com Cc: navlan21 nav911@yahoo.com Sent: Sunday, September 20, 2015 10:10 PM Subject: Re: [zfcuser-ldap] ServiceManager could not locate ZfcUserLdap\Authentication\Adapter\Ldap (#1)

If you would like to provide a pull request then I'll be happy to merge it in.

Sent from my Verizon Wireless 4G LTE smartphone

-------- Original message -------- From: navlan21 notifications@github.com Date: 2015/09/18 5:27 PM (GMT-05:00) To: Nitecon/zfcuser-ldap zfcuser-ldap@noreply.github.com Cc: Willem Hattingh w.hattingh@nitecon.com Subject: Re: [zfcuser-ldap] ServiceManager could not locate ZfcUserLdap\Authentication\Adapter\Ldap (#1)

PLEASE NOTE THIS, the initial issue on this thread was wrong class name. Setting in documentation has ZfcUserLdap\Authentication\Adapter\Ldap While it should be ZfcUserLdap\Authentication\Adapter\LdapAuth

array( 'enable_registration' => false, 'enable_username' => true, 'auth_adapters' => array( 100 => 'ZfcUserLdap\Authentication\Adapter\Ldap' ), //<--- this should be LdapAuth 'auth_identity_fields' => array( 'username','email' ), ),

Reply to this email directly or view it on GitHubhttps://github.com/Nitecon/zfcuser-ldap/issues/1#issuecomment-141573072. — Reply to this email directly or view it on GitHub.