Home » CakePHP » CakePHP 2.0 Ldap Authentication

With CakePHP 2.0 the authentication system has been completely redesigned to allow for extending the Auth component to allow other methods of authentication and authorization.  I finally sat down last weekend and updated my LDAPAuth component to work with the new version.  While I was doing it I added a few new features that people had been asking for. Also by updating this component I ended up also updating the Ldap Datasource. This included a lot of code cleanup as well.

You can get the new code at https://github.com/analogrithems/idbroker/tree/dev_cake2.0

To get things going download the idbroker code from github and place it in your  plugin folder App/Plugin/Idbroker pay attention to the new capital first letter.  This is a new convention for the CakePHP 2.0 to help in automatic class loading.

Now in your App/Controller/AppController.php you need a minimal of the following

<?php
class AppController extends Controller {
        var $components = array('Auth', 'Session', 'RequestHandler');

        var $user;

        function beforeFilter(){
                global $menus;
                $this->Auth->authenticate = array('Idbroker.Ldap'=>array('userModel'=>'Idbroker.LdapAuth'));
                //If you want to do your authorization from the isAuthorized Controller use the following
                $this->Auth->authorize = array('Controller');
        }


        /*
        * This just says aslong as this is a valid user let them in, you can also modify this to restrict to a group
        */
        public function isAuthorized(){
                $user = $this->Auth->user();
                if($user) return true;
                return false;
        }
}

Notice:That in the components you define the Auth component. This is making all your controllers register the authentication component. In the beforeFilter you are specifically stating you want to use the Idbroker’s Ldap Auth. Then you’re also telling your app to use the prepackaged model for the LDAP component.

The next step is to configure your Users controller and your views.

In your /App/Controller/UsersController.php

<?php
class UsersController extends AppController {
        var $name = 'Users';

        /*
        * Make sure to define which functions don't require auth to be accessed
        */
        function beforeFilter(){
                $this->Auth->allow('usernameExists', 'forgotPassword', 'signup','login','logout');
                parent::beforeFilter();
        }

        function login(){
                if ($this->request->is('post')) {
                        if ($this->Auth->login()) {
                                return $this->redirect($this->Auth->redirect());
                        } else {
                                $this->Session->setFlash(__('Username or password is incorrect'), 'default', array('class'=>'error-message'), 'auth');
                        }
                }
        }

        function logout(){
                $this->log("Destroying session",'debug');
                $this->Session->destroy();
                $this->redirect($this->Auth->logout());
        }
}

You’ll notice compared to previous version of the authcomponent you used to just have the Auth component automatically do the auth, now you actually call $this->Auth->login() to get it to actually check the username and password and run the login logic.

We’re not done yet, we also need to create our view /App/View/Users/login.ctp

<div id='loginForm'>
<?php
        echo $this->Session->flash('auth');
        echo $this->Form->create('Users', array('action' => 'login'));
        echo $this->Form->input('username');
        echo $this->Form->input('password',array('value'=>''));
        echo $this->Form->input('remember',array('type' => 'checkbox', 'label' => 'Remember me'));
        echo $this->Form->submit('Login');
?>
</div>

Last piece to tie this all together is telling your application how to access your LDAP server. Add something like this to youyr /App/Config/database.php

<?php
class DATABASE_CONFIG {
        public $ldap = array (
                        'datasource' => 'Idbroker.LdapSource',
                        'host' => 'localhost',
                        'port' => 389,
                        'basedn' => 'DC=example,DC=com',
                        'login' => 'CN=Manager,DC=example,DC=com',     //For Proxy Userdn
                        'password' => 'LdapPassword',  //For Proxy UserDN password
                        'database' => '',
                        'tls'         => false,
                        'type' => 'OpenLDAP', //Available types are 'OpenLDAP', 'ActiveDirectory', 'Netscape'
                        'version' => 3
        );
}

And in your /App/Config/bootstrap.php add the following to the very bottom

CakePlugin::load('Idbroker');
Configure::load('ldap');

These two lines tell your app to first load the Idbroker plugin and then load the ldap config file which you will create next.

Then create an ldap config file /App/Config/ldap.php with the following. This config file will configure how Ldap is used through out your app.

/**
 * LDAP Settings
 *
 */
        $config['LDAP']['Db']['Config'] = 'ldap'; //What is the name of the db config that has the LDAP credentials
        $config['LDAP']['User']['Identifier'] = 'uid'; //What is the LDAP attribute that identifies the username attribute,
                                                       // openldap, iplant, netscapr use uid, AD uses samaccountname
        $config['LDAP']['Group']['Identifier'] = 'cn'; //What is the LDAP attribute that identifies the group name, usually cn
        $config['LDAP']['Model'] = 'Idbroker.LdapAuth'; //Default model to use for LDAP components
        $config['LDAP']['LdapAuth']['Model'] = 'Idbroker.LdapAuth';
        $config['LDAP']['LdapAuth']['MirrorSQL']['Users'] = 'User'; //A SQL table to duplicate ldap records in for user
        $config['LDAP']['LdapAuth']['MirrorSQL']['Groups'] = 'Group'; //A SQL table to duplicate LDAP records in for groups
        $config['LDAP']['LdapACL']['Model'] = 'Idbroker.LdapAcl';
        $config['LDAP']['LdapACL']['groupType'] = 'group';
        $config['LDAP']['groupType'] = 'groupofuniquenames'; //What object class do you use for your groups?
        $config['LDAP']['Group']['behavior']['tree']['parent_id'] = '49db8df1-5e74-4e91-b15f-4d33e927f14e'; //Are you using a tree behavior?  Need to set the default parent_id?

That last part was a lot, not all of that is needed. Really just the first line is $config[‘LDAP’][‘Db’][‘Config’] = ‘ldap’; – this part tells your application which database config to use for LDAP. The other config options are for new extended features that I will explain below.

When creating this plugin I made use of the new extended features to allow you to use the HTTP basic authentication. In this method you can actually pass your username and password credentials in the http request header. This is useful for allowing command line tools like wget & curl to access authorized parts of your application. It is also used for rest applications.

Another new features that has been added to this Auth Component is the ability to have Ldap Auth mirror a SQL table. What this means is that if you really want to have your user information in SQL but just have authentication come from Ldap you can do that. You need to add the following configuration options to the bootstrap.php These tell it which Models to use to mirror the data to and what the LDAP identifiers are for the data.

        $config['LDAP']['LdapAuth']['MirrorSQL']['Users'] = 'User'; //A SQL table to duplicate ldap records in for user
        $config['LDAP']['LdapAuth']['MirrorSQL']['Groups'] = 'Group'; //A SQL table to duplicate LDAP records in for groups
        $config['LDAP']['User']['Identifier'] = 'uid'; //What is the LDAP attribute that identifies the username attribute,
                                                       // openldap, iplant, netscapr use uid, AD uses samaccountname
        $config['LDAP']['Group']['Identifier'] = 'cn'; //What is the LDAP attribute that identifies the group name, usually cn

Have a question?

Discuss it in the CakePHP 2.0 Ldap Plugin Forum

50 thoughts on “CakePHP 2.0 Ldap Authentication

  1. Brett says:

    Hi,

    This looks exactly what I need for a project however I can’t get it to work… I’ve followed your instructions carefully and placed this plugin in a fresh cakephp install but I get this error:

    Authentication adapter "Ldap" was not found.

    Error: An Internal Error Has Occurred.
    Stack Trace

    #0 C:\wamp\www\catnetv2\lib\Cake\Controller\Component\AuthComponent.php(637): AuthComponent->constructAuthenticate()
    #1 C:\wamp\www\catnetv2\lib\Cake\Controller\Component\AuthComponent.php(514): AuthComponent->identify(Object(CakeRequest), Object(CakeResponse))
    #2 C:\wamp\www\catnetv2\app\Controller\UsersController.php(7): AuthComponent->login()
    #3 [internal function]: UsersController->login()
    #4 C:\wamp\www\catnetv2\lib\Cake\Controller\Controller.php(473): ReflectionMethod->invokeArgs(Object(UsersController), Array)
    #5 C:\wamp\www\catnetv2\lib\Cake\Routing\Dispatcher.php(104): Controller->invokeAction(Object(CakeRequest))
    #6 C:\wamp\www\catnetv2\lib\Cake\Routing\Dispatcher.php(86): Dispatcher->_invoke(Object(UsersController), Object(CakeRequest), Object(CakeResponse))
    #7 C:\wamp\www\catnetv2\app\webroot\index.php(96): Dispatcher->dispatch(Object(CakeRequest), Object(CakeResponse))
    #8 {main}

  2. Brett says:

    LOL… nevermind I must have accidentally downloaded the 1.3 version.

  3. good to hear, if you run into an issue with the 2.0 branch email your current project and I’ll try to debug it for you.

  4. Rodrigo says:

    hello,

    I’m trying to use your code but after do all steps above my app is returning the following errors:

    “Error: Database table app_models for model AppModel was not found.”

    #0 /var/www/html/artigos/lib/Cake/Model/Model.php(3236): Model->setSource(‘app_models’)
    #1 /var/www/html/artigos/lib/Cake/Model/Model.php(2458): Model->getDataSource()
    #2 /var/www/html/artigos/app/Plugin/Idbroker/Controller/Component/Auth/LdapAuthenticate.php(135): Model->find(‘first’, Array)
    #3 /var/www/html/artigos/app/Plugin/Idbroker/Controller/Component/Auth/LdapAuthenticate.php(70): LdapAuthenticate->_getDn(‘id’, ‘rodrigo’)
    #4 /var/www/html/artigos/lib/Cake/Controller/Component/AuthComponent.php(635): LdapAuthenticate->authenticate(Object(CakeRequest), Object(CakeResponse))
    #5 /var/www/html/artigos/lib/Cake/Controller/Component/AuthComponent.php(509): AuthComponent->identify(Object(CakeRequest), Object(CakeResponse))
    #6 /var/www/html/artigos/app/Controller/UsersController.php(7): AuthComponent->login()
    #7 [internal function]: UsersController->login()
    #8 /var/www/html/artigos/lib/Cake/Controller/Controller.php(473): ReflectionMethod->invokeArgs(Object(UsersController), Array)
    #9 /var/www/html/artigos/lib/Cake/Routing/Dispatcher.php(107): Controller->invokeAction(Object(CakeRequest))
    #10 /var/www/html/artigos/lib/Cake/Routing/Dispatcher.php(89): Dispatcher->_invoke(Object(UsersController), Object(CakeRequest), Object(CakeResponse))
    #11 /var/www/html/artigos/app/webroot/index.php(96): Dispatcher->dispatch(Object(CakeRequest), Object(CakeResponse))
    #12 {main}

    Do you know what i did wrong?

    Thank you!

    • update from github and the issue should be resolved. Also see the changes in the post above, I added more information to help out with the authorization since you may not be using a user table and need to authorize actions

  5. Quentin says:

    Hi,

    Your code is very useful for me, and for a lot of people I think, please keep doing such an amazing job !

    However, I’m running into an issue (I experimented the two issues above also …).
    It’s about “datasource missing config”.

    My app is returning the following errors :

    Error: The datasource configuration was not found in database.php.

    #0 C:\inetpub\wwwroot\tds\lib\Cake\Model\ConnectionManager.php(91): ConnectionManager::_getConnectionObject(NULL)
    #1 C:\inetpub\wwwroot\tds\app\Plugin\Idbroker\Model\IdbrokerAppModel.php(9): ConnectionManager::getDataSource(NULL)
    #2 C:\inetpub\wwwroot\tds\app\Plugin\Idbroker\Model\LdapAuth.php(13): IdbrokerAppModel->__construct()
    #3 C:\inetpub\wwwroot\tds\lib\Cake\Utility\ClassRegistry.php(136): LdapAuth->__construct(Array)
    #4 C:\inetpub\wwwroot\tds\app\Plugin\Idbroker\Controller\Component\Auth\LdapAuthenticate.php(50): ClassRegistry::init(‘Idbroker.LdapAu…’)
    #5 C:\inetpub\wwwroot\tds\lib\Cake\Controller\Component\AuthComponent.php(677): LdapAuthenticate->__construct(Object(ComponentCollection), Array)
    #6 C:\inetpub\wwwroot\tds\lib\Cake\Controller\Component\AuthComponent.php(638): AuthComponent->constructAuthenticate()
    #7 C:\inetpub\wwwroot\tds\lib\Cake\Controller\Component\AuthComponent.php(515): AuthComponent->identify(Object(CakeRequest), Object(CakeResponse))
    #8 C:\inetpub\wwwroot\tds\app\Controller\UsersController.php(15): AuthComponent->login()
    #9 [internal function]: UsersController->login()

    My config in database.php :

    public $ldap = array (
    ‘datasource’ => ‘Idbroker.LdapSource’,
    ‘host’ => ‘192.168.56.2’,
    ‘port’ => 389,
    ‘basedn’ => ‘CN=Users,DC=test,DC=com’,
    ‘login’ => ‘CN=Administrateur,CN=Users,DC=test,DC=com’, //For Proxy Userdn
    ‘password’ => ‘xxxxx’, //For Proxy UserDN password
    ‘database’ => ”,
    ‘tls’ => false,
    ‘type’ => ‘ActiveDirectory’, //Available types are ‘OpenLDAP’, ‘ActiveDirectory’, ‘Netscape’
    ‘version’ => 3
    );

    Do you have any idea where this comes from ?
    In the same time, I send you the entire project by email.

    Thank you !
    Quentin

  6. Brett says:

    Tried again with updated code and instructions above and just get this:
    Missing Datasource Configuration

    Error: The datasource configuration was not found in database.php.

    Notice: If you want to customize this error message, create app\View\Errors\missing_datasource_config.ctp
    Stack Trace

    #0 C:\wamp\www\catnetv2\lib\Cake\Model\ConnectionManager.php(94): ConnectionManager::_getConnectionObject(NULL)
    #1 C:\wamp\www\catnetv2\app\Plugin\Idbroker\Model\IdbrokerAppModel.php(9): ConnectionManager::getDataSource(NULL)
    #2 C:\wamp\www\catnetv2\app\Plugin\Idbroker\Model\LdapAuth.php(13): IdbrokerAppModel->__construct()
    #3 [internal function]: LdapAuth->__construct(Array)
    #4 C:\wamp\www\catnetv2\lib\Cake\Utility\ClassRegistry.php(141): ReflectionClass->newInstance(Array)
    #5 C:\wamp\www\catnetv2\app\Plugin\Idbroker\Controller\Component\Auth\LdapAuthenticate.php(50): ClassRegistry::init(‘Idbroker.LdapAu…’)
    #6 C:\wamp\www\catnetv2\lib\Cake\Controller\Component\AuthComponent.php(676): LdapAuthenticate->__construct(Object(ComponentCollection), Array)
    #7 C:\wamp\www\catnetv2\lib\Cake\Controller\Component\AuthComponent.php(590): AuthComponent->constructAuthenticate()
    #8 C:\wamp\www\catnetv2\lib\Cake\Controller\Component\AuthComponent.php(314): AuthComponent->_getUser()
    #9 [internal function]: AuthComponent->startup(Object(PagesController))
    #10 C:\wamp\www\catnetv2\lib\Cake\Utility\ObjectCollection.php(104): call_user_func_array(Array, Array)
    #11 C:\wamp\www\catnetv2\lib\Cake\Controller\Controller.php(606): ObjectCollection->trigger(‘startup’, Array)
    #12 C:\wamp\www\catnetv2\lib\Cake\Routing\Dispatcher.php(101): Controller->startupProcess()
    #13 C:\wamp\www\catnetv2\lib\Cake\Routing\Dispatcher.php(86): Dispatcher->_invoke(Object(PagesController), Object(CakeRequest), Object(CakeResponse))
    #14 C:\wamp\www\catnetv2\app\webroot\index.php(96): Dispatcher->dispatch(Object(CakeRequest), Object(CakeResponse))
    #15 {main}

    In my database.php file I have this:
    public $ldap = array (
    ‘datasource’ => ‘Idbroker.LdapSource’,
    ‘host’ => ‘server’,
    ‘port’ => 389,
    ‘basedn’ => ‘DC=domain,DC=local’,
    ‘login’ => ‘user’,
    ‘password’ => ‘pass’,
    ‘database’ => ”,
    ‘tls’ => false,
    ‘type’ => ‘ActiveDirectory’, //Available types are ‘OpenLDAP’, ‘ActiveDirectory’, ‘Netscape’
    ‘version’ => 3
    );

    Any ideas?

  7. Quentin says:

    Hi Brett,

    Try to copy the LDAP settings from bootstrap.php to ldap.php for example and load it in the bootstrap :

    //app/Config/bootstrap.php
    Configure::load(‘ldap’);
    CakePlugin::loadAll();

    and

    //app/Config/ldap.php
    <?php
    $config['LDAP']['Db']['Config'] = 'ldap';
    $config['LDAP']['User']['Identifier'] = 'samaccountname';

    It worked for me.

    But I have still some issues with the _getDn function of LdapAuthenticate.
    The function doesn't return a value for $dn.

    Quentin

    • did your debug show the query? It should be the first line and look something like

      search | scope: sub | cond: uid=analogrithems | targetDn: DC=analogrithems,DC=net | order: | limit: 1

      • Quentin says:

        It was a little mistake in my config … 😉

        I have no more issue, except one :
        First step) I’m logging in with invalid credentials.
        Reaction : $this->Auth->login() returns false.

        Second step) I’m logging in with valid credentials.
        Reaction : $this->Auth->login() returns true.

        Third step) I’m logging out then I try with invalid credentials.
        Reaction : $this->Auth->login() returns true !

        I see with wireshark that, in the third step, LDAP messages contain credentials of second step…
        Rebooting my browser resets the problem (really weird…).

        Any ideas ?

        Also, I don’t know how to use the debug to show queries you talked about.

        • Quentin says:

          I solved my problem by removing :

          $this->Session->destroy();
          before
          $this->redirect($this->Auth->logout());

          I think Auth->logout() needs the session to work properly.
          I will try your new features today… I keep you informed.

          Thank you !

  8. Quentin says:

    Hi !

    I come back with a new issue and a little correction.

    First, the correction : in LdapAuthenticate.php, function existsOrCreateSQLUser, it should be :

    if(isset($result) && !empty($result)){
    instead of
    if(isset($result)){

    Yes… it was almost nothing 😉
    Your SQLMirroring feature is very useful for me, thanks again !

    Then, an issue I try to debug since yesterday :
    -> I’m logging in with valid credentials.
    Reaction : login is successfull and user informations are stored in the session variable (ldap/user mixed, normal ?)
    -> I’m going to another page or refresh.
    Reaction : session is lost, I’m not logged in anymore …

    It’s very frustrating because it could be caused by a lot of things, but do you have any idea about that ?

    • It sounds like you may have accidentally placed that session->destroy somewhere else, or you have a redirect directing you at logout.

    • Brett says:

      Think I’m having a similar problem but nothing seems to go into the session in the first place (except for username or password), ldap lookup seems to go ok finds the user then plonks me back on the login page (LoggedInUser is empty).

      • are you doing sqlMirroring? If so what does your user schema look like?

        • Brett says:

          No not using mirroring at this point.

          • Heidi says:

            Sorry that I missed the two warnings that that followed the three notices mentioned in my earlier post. So all together there are three notices (as in Brett’s case) and two warnings. I also found that when the login credentials are right, the username is inserted into the users table.

            Warning (2): Cannot modify header information – headers already sent by (output started at C:\…\cake\lib\Cake\Utility\Debugger.php:744) [CORE\Cake\Model\Datasource\CakeSession.php, line 666]

            Warning (2): session_regenerate_id() [function.session-regenerate-id]: Cannot regenerate session id – headers already sent [CORE\Cake\Model\Datasource\CakeSession.php, line 668]

        • Brett says:

          Also tried with sql mirroring, seems to add user/group ok to db. Doesn’t leave me logged in though and get these errors at top:

          Notice (8): Undefined property: LdapAuthenticate::$sqlModel [APP\Plugin\Idbroker\Controller\Component\Auth\LdapAuthenticate.php, line 219]

          Notice (8): Trying to get property of non-object [APP\Plugin\Idbroker\Controller\Component\Auth\LdapAuthenticate.php, line 219]

          Notice (8): Undefined index: [APP\Plugin\Idbroker\Controller\Component\Auth\LdapAuthenticate.php, line 219]

          Users table just looks like:
          `id` int(11) NOT NULL AUTO_INCREMENT,
          `username` varchar(255) NOT NULL,
          `group_id` int(11) NOT NULL,
          `created` datetime DEFAULT NULL,
          `modified` datetime DEFAULT NULL,
          PRIMARY KEY (`id`),
          UNIQUE KEY `username` (`username`)

          Is anything else required for it to work?

          Thanks,

          -Brett

          • email me your project and I’ll see if it happens on my server.

          • Heidi says:

            I encountered exactly the same errors as Brett did (the post on January 18, 2012 at 7:41 pm). Is there any solution available? Thanks a lot in advance.

            My user table is like this:
            CREATE TABLE `users` (
            `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
            `name` varchar(100) DEFAULT NULL,
            `email` varchar(150) DEFAULT NULL,
            `firstname` varchar(60) DEFAULT NULL,
            `lastname` varchar(60) DEFAULT NULL,
            `username` varchar(100) NOT NULL,
            `created` datetime DEFAULT NULL,
            `modified` datetime DEFAULT NULL,
            PRIMARY KEY (`id`)
            )

            Heidi

          • Here is the schema I was using

            CREATE TABLE IF NOT EXISTS `users` (
            `id` char(36) COLLATE utf8_unicode_ci NOT NULL,
            `firstname` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
            `lastname` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
            `username` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
            `password` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
            `displayname` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
            `email` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
            `dn` varchar(256) COLLATE utf8_unicode_ci DEFAULT NULL,
            PRIMARY KEY (`id`),
            UNIQUE KEY `username` (`username`),
            UNIQUE KEY `email` (`email`),
            UNIQUE KEY `dn` (`dn`)
            ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

            In the auth component the function existsOrCreateSQLUser($user) is currently designed for use against openldap. A little modification may be needed to make it work with active directory. Look around line 211 you’ll need to define the ldap attributes you want to map to your sql table. In the future I’ll find a cleaner to map them.

          • Heidi says:

            Hi

            Thanks so much for your reply.

            I recreated the table according to your post (February 21, 2012 at 11:08 pm) and did what benef said (February 16, 2012 at 9:16 am) by changing line 219 to $this->sqlUserModel. I tried to login again and the fields (username, displayname, email, dn) were populated.

            I still wasn’t able to login though and the log (ldap.error.log) was printed “Ldap.error: Failed to update sql mirrored groups:”.

            It turned out that when the method existsOrCreateSQLGroup was called around line 116, the second argument $groups was FALSE as returned by getGroups.

            So I looked into getGroups and found that the model wasn’t able to find, based on the conditions (‘objectclass’=>’groupofuniquenames’, ‘uniquemember’=>$user[‘dn’])) what it was supposed to find on line 233 to 234.

            Is there any way to solve this problem?

            I’ve to say this plugin is awesome, especially on the part of sqlmirroring. I really hope we could find the solution so that it works for Active Directory.

            Heidi

  9. Brett says:

    Just a tip if you’re getting “LDAP not configured on this server.”… make sure you have the ldap php module loaded! 😀

  10. Andreas says:

    I just dl your plugin, put it in an new installation of cakephp 2 and now I always get this error:

    Authentication adapter "Ldap" was not found.
    Error: An Internal Error Has Occurred.

    Stack Trace

    #0 /Users/awidmer/Dropbox/Projects/excelsis/lib/Cake/Controller/Component/AuthComponent.php(637): AuthComponent->constructAuthenticate()
    #1 /Users/awidmer/Dropbox/Projects/excelsis/lib/Cake/Controller/Component/AuthComponent.php(514): AuthComponent->identify(Object(CakeRequest), Object(CakeResponse))
    #2 /Users/awidmer/Dropbox/Projects/excelsis/app/Controller/UsersController.php(15): AuthComponent->login()
    #3 [internal function]: UsersController->login()
    #4 /Users/awidmer/Dropbox/Projects/excelsis/lib/Cake/Controller/Controller.php(473): ReflectionMethod->invokeArgs(Object(UsersController), Array)
    #5 /Users/awidmer/Dropbox/Projects/excelsis/lib/Cake/Routing/Dispatcher.php(104): Controller->invokeAction(Object(CakeRequest))
    #6 /Users/awidmer/Dropbox/Projects/excelsis/lib/Cake/Routing/Dispatcher.php(86): Dispatcher->_invoke(Object(UsersController), Object(CakeRequest), Object(CakeResponse))
    #7 /Users/awidmer/Dropbox/Projects/excelsis/app/webroot/index.php(96): Dispatcher->dispatch(Object(CakeRequest), Object(CakeResponse))
    #8 {main}

  11. Saito says:

    Hi,
    Your plugin and tutorial are both great!
    However, i noticed some things that didn’t figured in the tutorials for Active Directory users.
    I’m very new to cakephp and don’t know any of the tricks except the blog tutorial. 🙁
    I’m using Active Directory, and i