Step 3 – Adding LDAP « benhavilland

Pages

Step 3 - Adding LDAP

From my first post: “As far as LDAP goes I need to have my users authenticate through LDAP but have their records added to the database so I can ACL them.  I will be starting with this by Nathaniel Price and modifying the code using some other posts that I have found like CakePHP with full CRUD, a living example! by analogrithems.  Both posts are excellent and I would not know where to begin without them.”

Step 3 will cover implementing Nathaniel Price’s method.  I will move on to fine tuning and using some of the code from analogrithems after I have all 3 concepts up and running.

I started by going to this by Nathaniel Price and doing what his post made on Nov 03, 2008; 12:56pm said to do.  My notes:

  • Pasting the code from the webpage did not come over cleanly because of some added line breaks.  I had to do a little cleanup to fix the breaks.
  • Did not do the MySQL command noted on the page but instead added the active field to users table in the DB
  • When pasting make sure that there are no blank spaces at the end of your paste or you will get errors causing the page not to display
  • Switching to allow the app to use LdapAuth is done by simply changing

var $components = array('Acl', 'Auth');

to

var $components = array('Acl', 'LdapAuth');

in your app_controller.php file.

  • After complete LDAP was authenticating and adding users to DB but it is not honoring ACL, changing the $components variable back to using Auth allows me to login with the new user and have ACL honored. hmmm… (answer a little below)
  • I removed unnecessary functions from ldap_user.php, keeping only those having to do with auth, just to keep it simple and easier to debug resulting in a ldap_user.php that looks like this:
<?php
class LdapUser extends AppModel
{
        var $name = 'LdapUser';
        var $useTable = false;
        var $primaryKey = 'uid';
 
        var $host       = 'some.host.com';
        var $port       = 389;
        var $baseDn     = 'ou=peeps,ou=inside,o=something';
        var $user       = 'cn=someuser,o=somewhere';
        var $pass       = 'somepass';
 
        var $ds;
 
        function __construct()
        {
                parent::__construct();
                $this->ds = ldap_connect($this->host, $this->port);
                ldap_set_option($this->ds, LDAP_OPT_PROTOCOL_VERSION, 3);
                if ($this->user) {
                        ldap_bind($this->ds, $this->user, $this->pass);
                } else {
                        //Do an anonymous bind.
                        ldap_bind($this->ds);
                }
        }
 
        function __destruct()
        {
                ldap_close($this->ds);
        }
 
        function findAll($attribute = 'uid', $value = '*', $baseDn = '')
        {
                if (!$baseDn) {
                        $baseDn = $this->baseDn;
                }
                $r = ldap_search($this->ds, $baseDn, $attribute . '=' . $value);
                if ($r)
                {
                        //if the result contains entries with surnames,
                        //sort by surname:
                        ldap_sort($this->ds, $r, "sn");
 
                        $result = ldap_get_entries($this->ds, $r);
                        return $this->convert_from_ldap($result);
                }
                return null;
        }
 
        // would be nice to read fields. left the parameter in as placeholder and to be compatible with other read()'s
        function read($fields=null, $uid)
        {
                $r = ldap_search($this->ds, $this->baseDn, 'uid='. $uid);
                if ($r)
                {
                        $l = ldap_get_entries($this->ds, $r);
                        $convert = $this->convert_from_ldap($l);
                        return $convert[0];
                }
        }
 
        function auth($uid, $password)
        {
                if (trim($password) == '') {
                        return false;
                }
                $result = $this->findAll('uid', $uid);
 
                if(isset($result[0]))
                {
                        if (@ldap_bind($this->ds, "uid=$uid,$this->baseDn", $password))
                        {
                                return $result;
                        }
                        else
                        {
                                return false;
                        }
                }
                else
                {
                        return false;
                }
        }
 
        private function convert_from_ldap($data)
        {
                $final = array();
                foreach ($data as $key => $row):
                if($key === 'count') continue;
 
                foreach($row as $key1 => $param):
                if(!is_numeric($key1)) continue;
                if($row[$param]['count'] === 1)
                $final[$key]['LdapUser'][$param] = $row[$param][0];
                else
                {
                        foreach($row[$param] as $key2 => $item):
                        if($key2 === 'count') continue;
                        $final[$key]['LdapUser'][$param][] = $item;
                        endforeach;
                }
                endforeach;
                endforeach;
                return $final;
        }
}
?>
  • Sorry if the code prints/copys weird, I need to get a better wordpress code-view plugin. Any suggestions?
  • So, I figured out why the permissions were not being applied.  It is mentioned in by Nathaniel Price that you must change all references of Auth to LdapAuth, like we did with setting the $components = array('Acl', 'LdapAuth'); variable. I had neglected to do this in the beforeFilter code in my app_controller.php. So after changing this:
$this->Auth->authorize = 'actions';
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login');
$this->Auth->loginRedirect = array('controller' => 'posts', 'action' => 'add');
$this->Auth->actionPath = 'controllers/';
$this->Auth->allowedActions = array('display');
  • to this:
$this->LdapAuth->authorize = 'actions';
$this->LdapAuth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->LdapAuth->logoutRedirect = array('controller' => 'users', 'action' => 'login');
$this->LdapAuth->loginRedirect = array('controller' => 'posts', 'action' => 'add');
$this->LdapAuth->actionPath = 'controllers/';
$this->LdapAuth->allowedActions = array('display');
  • the restrictions of the ACL begun to be applied.  Yay!
  • Now I have a limited user sitting in the database and I can no longer login with my user1 user so I manually modified the group_id in the users table of my new user to be 1 (administrators). Now my user can access everything including the /admin/acl management tool, which is a necessity.
  • We have a working demo so now I need to do some cleanup and try to fix that redirect error mentioned in step 2…
VN:R_U [1.7.3_972]
Rating: 0.0/10 (0 votes cast)

Post to Twitter Post to Delicious Post to Digg Post to Facebook


Unique visitors to post: 30

You must be logged in to post a comment.