Home » CakePHP » LdapAuth component for CakePHP

So I was looking for a way to authenticate against LDAP with cake but I’ve found that it doesn’t support it by default. I found one that checks the auth against ldap then creates a local mysql account. This also didn’t use a actual ldap data sourc e either, it just handeled it’s own ldap connection. After I read through the standard cakphp auth component I saw that it wouldn’t be that hard to write an LDAP based auth component.

First you need to download this file ldap_auth.php to your ‘app/controllers/components/’ directory.

Then just like the original auth component you add that component to a model. I followed the usual auth example and created a model called Users.php like so



If some of these options are odd looking please have a look at my ldap data source post.

Next you are going to need your controller. Here is the one I used It defines the required functions like login, logout & authorize.

redirect($this->LdapAuth->logout());
	}

        function isAuthorized() {
                return true;
        }

}
?>

7

18 thoughts on “LdapAuth component for CakePHP

  1. Philippe says:

    Hi,

    Since your component is much more elaborated than mine, it will replace mine very soon 😉 Thank you!
    Just a note: if you authenticate with ldap, you should do this with encryption, otherwise you’ll be passing username and password together in clear text over the network, thus opening a wide security hole.
    As I wrote in my comment (http://memdump.wordpress.com/2008/04/26/ldap-data-source-now-with-full-crud/#comment-33), it is very easy to implement tls support. Just need to add 3 lines of code to the connect function!

    regards

    Philippe

    • analogrithems says:

      I’m looking into doing this right now, but as most people use self signed certs for ldap, I’ve gotta add documentation on how to make PHP/Apache trust unsigned certs. But I’m right on board with you. I haven’t worried about this yet as my development server is also my ldap server and the traffic never actually hits the network.

    • analogrithems says:

      I’ve added support for both TLS and SSL See my database example in my data source for settings

  2. […] You notice that the variables database, login and password are blank. Keep at least database this way. You can populate login and password if don’t want your ldap connections to be anonymous. I keep mine blank because I have written my own auth component that uses ldap, So once I’m authed that gets passed to the datasource instead. This is a ugly hack that I’ve written another post about. […]

  3. Robert says:

    Very cool component. I need to write a tiny cake-based app this week and need to authenticate users via Microsoft Active directory. I also want to lock down the app to allow only users in a certain group to use any of it. Any suggestions on where to add that logic? I’m a bit new to cake and have been picking things up via the manual.

    Thank You,

    • analogrithems says:

      This shouldn’t be an issue, make it use the ldap datasource http://www.analogrithems.com/rant/2009/06/12/cakephp-with-full-crud-a-living-example/ then add the auth componet in this article. In your config/database.php place an entry for you active directory stuff. like any normal ldap connection. Active directory is just a standard ldap v3 (mostly). Also i believe you must use a proxy user account in your ‘config/database.php’ file for the inital dn lookup. (When you type in your username the script needs to translate that to a dn, it uses the proxy account you initially specify in config/database.php login & password fields to do the inital lookup then binds with the returned dn and the password you passed.)

      The only other thing I can think of is changing the attribute on line 156
      `$dn = $this->getDn(‘uid’, $uid);` to `$dn = $this->getDn(‘samaccountname’, $uid);` if you want to use a regular username format
      of change it to `$dn = $this->getDn(‘userprincipalname’, $uid);` if you are going to use username@domain format

      see http://www.computerperformance.co.uk/Logon/LDAP_attributes_active_directory.htm

      Let me know if you have any trouble and I’ll to try to drum up an AD server to test my code against.

  4. Shawn Parr says:

    I got your ldap_source working, and can do lookups against our Active Directory setup. However I just can’t get this component to work at all.

    I’d like to give more info, but I’m getting the infamous ‘Cannot modify header information – headers already sent by’ error. I’ve done my research, and typically that is caused by white space after the ?> tag, but I’ve searched all my files and do not have any with the extra whitespace outside of my view template files.

    That being said, the one page that does load is my login page /users/login. When it is submitted I get the following on my mostly blank page:

    1 search | scope: sub | cond: samaccountname=user | targetDn: dc=example,dc=com | order: 1: Operations error

    I’m pretty sure that Operations error is an issue, but I’m not sure what is causing it. I have a bind user and password set in my Ldap config in the database config file, and they are obviously working since ldap lookups work fine (trust me, if the bind user can’t connect the lookups wouldn’t work!).

    Any ideas? Any pointers? I’m going nuts trying to figure this out. Feel free to email me if you want more details or have other instructions.

    I should note that I’m pretty new to cakephp, but have done a little bit of MVC php development.

  5. Shawn Parr says:

    I got your auth working. A couple odd things were happening. For some reason on our AD domain, when just searching you can specify the root (dc=example, dc=edu) and it will find everything, however when using authentication it fails. This is especially weird since it is in the getDn function: $userObj$ = $this->ldap->find, which I would have imagined should work since it is seemingly identical to the code that does it when just doing lookups.

    To make things weirder, when that failed, it was returning nothing, which then got passed on to ldapauth, which for some reason would return 1 to the login function when the dn was empty. So I had a situation where anyone could log in with any username/password combo.

    To solve this I first changed the getDn function to individually search the two OU’s set up in our AD where all valid users are stored (in sub OU’s). I then added a statement to ldapauth to return a zero if the dn was empty.

    Technically the above getDn change I had already implemented in my controller and model due to the fact that our AD has a lot of extra stuff in many of the object records. As such a typical search someone would setup for ldap will return computer records and other special items (computers are tagged with objectclass=person for some odd reason), so I added a new line to the model that uses an array to hold multiple OU statements, then use a foreach loop to go through them, then a bit of logic to deal with getting the results back to something the system can deal with as it is.

    I want to thank you for:
    1) creating these ldap tools. They work well, and are pretty well thought out
    2) for creating full documentation for how to do something in cakephp.

    That second one is really what I appreciate most. As I start learning cakephp I tend to find plenty of articles and info on how to do things, but almost all of them require a pretty full knowledge of the logic behind cakephp. Having an article like this to reference which gives full working examples was EXTREMELY helpful.

    • analogrithems says:

      in the getDN function did you have to change the call to look for an attribute besides uid? I recall windows uses something different like userPrincipal. Can you post your code changes so i can make this component more universal?

  6. Kit Peters says:

    it’s worth noting that the call to __getLDAPSchema() will fail if you bind anonymously to an Active Directory 2003 server (see http://serverfault.com/questions/10208/disable-requiring-authentication-to-bind-in-active-directory). You can turn this behavior off in AD, but if you don’t have access to the AD configuration, you’ll have to do a bind with a username/password.

  7. Scott says:

    You may want to consider adding the following to your component so that the Auth examples from the book still work as described.

    /**
    * Initialize method ensures Auth methods remain working as described in the book.
    */
    function initialize(&$controller) {
    parent::initialize($controller);
    $controller->Auth =& $this;
    }

    Now every reference to $this->Auth is still valid.

  8. Sean Traynor says:

    Hi Analogrithems,

    Firstly – thank you for this article and all of your efforts towards CakePHP’s LDAP integration!

    I am having issues however. If I use the ldap_source listed in the article LDAP is properly queried however I have the issues above with blank output without debug and header already sent with debug on.

    With the latest version of ldap_source on github I recieve the message “-1: Can’t contact LDAP server” – even though it works with the older version of ldap_source! Are there any changes that need to be made to the LdapAuth component to make it compatible with the latest version of the ldap_source datasource?

    Many thanks!
    Sean

    • analogrithems says:

      I added a new attribute that needs to be added to the database config, Here is my database.php This is to make the datasource work with different ldap servers operational attributes and know how to find the schemas that exists in different locations between them.

      vi config/core.php

      < ?php
       class DATABASE_CONFIG {
              //This will be used for extensions/plugins.  if you plugin needs a db, define it here.
              var $default = array(
                      'driver' => 'mysql',
                      'persistent' => false,
                      'host' => 'localhost',
                      'login' => 'user',
                      'password' => 'password',
                      'database' => 'database_name',
                      'prefix' => '',
              );
              var $ldap = array (
                      'datasource' => 'ldap',
                      'host' => 'localhost',
                      'port' => 389,
                      'basedn' => 'dc=analogrithems,dc=com',
                      'login' => '',     //For Proxy Userdn
                      'password' => '',  //For Proxy UserDN password
                      'database' => '',  //Needed to prevent cakePHP from throwing errors about database missing
                      'tls' => '', //Set this to true if using tls
                      'type' => 'Netscape', //Type Can be either 'Netscape', 'OpenLDAP', 'ActiveDirectory'
                      'version' => 3 //LDAP Version 3
               );
       }
      ?>
      
  9. Jay says:

    I’m trying to use your ldap_auth (which is pretty slick, by the way)…but I’m having a problem in which the ldap lookup is getting sent a full array instead of the username during login, resulting in a login failure. I’m not sure how that’s happening, but could use some help

  10. Fabien says:

    Thanks you for this great work.

    It’s work great with Mac OS X Server OpenLDAP.
    I just have one bug in ldap_source.php on line 573. I’ve changed :
    if(ldap_count_entries($this->database, $check) > 0){
    Into
    if($check && ldap_count_entries($this->database, $check) > 0){
    because $check was false in my case.

    And to be compatible with ARO table (for ACL), i’ve changed uid into uidnumber in User model.

  11. David says:

    Just downloaded your source code and reading through it (slowly). Thank you for this!!

  12. Chung says:

    I kept on getting these errors and nothing comes back when I do /people/view/jsmith. Please help. Thanks a lot.

    Warning (2): ldap_count_entries(): supplied argument is not a valid ldap result resource [APP\models\datasources\ldap_source.php, line 573]

    Notice (8): Undefined variable: schema_entries [APP\models\datasources\ldap_source.php, line 598]

    Notice (8): Undefined variable: return [APP\models\datasources\ldap_source.php, line 702]

    Warning (2): ksort() expects parameter 1 to be array, null given [APP\models\datasources\ldap_source.php, line 1216]

    Warning (2): Cannot modify header information – headers already sent by (output started at C:\Users\jsmith\Documents\wamp\www\test_app\cake\libs\debugger.php:673) [CORE\cake\libs\controller\controller.php, line 746]

Leave a Reply to Philippe Cancel reply

Your email address will not be published. Required fields are marked *

</Random> is Stephen Fry proof thanks to caching by WP Super Cache