<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Random Tech Articles &#187; CakePHP</title>
	<atom:link href="http://www.analogrithems.com/rant/category/cakephp/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.analogrithems.com/rant</link>
	<description>If I have seen a little further it is by standing on the shoulders of Giants. - Newton</description>
	<lastBuildDate>Thu, 02 Feb 2012 20:07:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>CakePHP 2.0 Ldap Authentication</title>
		<link>http://www.analogrithems.com/rant/2012/01/03/cakephp-2-0-ldapauth/</link>
		<comments>http://www.analogrithems.com/rant/2012/01/03/cakephp-2-0-ldapauth/#comments</comments>
		<pubDate>Wed, 04 Jan 2012 02:33:11 +0000</pubDate>
		<dc:creator>analogrithems</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[ldap]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.analogrithems.com/rant/?p=1079</guid>
		<description><![CDATA[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 &#8230; <a href="http://www.analogrithems.com/rant/2012/01/03/cakephp-2-0-ldapauth/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<a href='http://twitter.com/share?url=http%3A%2F%2Fwww.analogrithems.com%2Frant%2F%3Fp%3D1079&count=horizontal&related=&text=CakePHP%202.0%20Ldap%20Authentication' class='twitter-share-button' data-text='CakePHP 2.0 Ldap Authentication' data-url='http://www.analogrithems.com/rant/?p=1079' data-counturl='http://www.analogrithems.com/rant/2012/01/03/cakephp-2-0-ldapauth/' data-count='horizontal' data-via='analogrithems'></a><p>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.</p>
<p>You can get the new code at <a href="https://github.com/analogrithems/idbroker/tree/dev_cake2.0">https://github.com/analogrithems/idbroker/tree/dev_cake2.0</a></p>
<p>To get things going download the idbroker code from github and place it in your  plugin folder <strong>App/Plugin/Idbroker</strong> pay attention to the new capital first letter.  This is a new convention for the CakePHP 2.0 to help in automatic class loading.</p>
<p>Now in your <strong>App/Controller/AppController.php</strong> you need a minimal of the following</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
class AppController extends Controller {
        var $components = array('Auth', 'Session', 'RequestHandler');

        var $user;

        function beforeFilter(){
                global $menus;
                $this-&gt;Auth-&gt;authenticate = array('Idbroker.Ldap'=&gt;array('userModel'=&gt;'Idbroker.LdapAuth'));
                //If you want to do your authorization from the isAuthorized Controller use the following
                $this-&gt;Auth-&gt;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-&gt;Auth-&gt;user();
                if($user) return true;
                return false;
        }
}
</pre>
<p><strong>Notice:</strong>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&#8217;s Ldap Auth. Then you&#8217;re also telling your app to use the prepackaged model for the LDAP component.</p>
<p>The next step is to configure your Users controller and your views.</p>
<p>In your <strong>/App/Controller/UsersController.php</strong></p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
class UsersController extends AppController {
        var $name = 'Users';

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

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

        function logout(){
                $this-&gt;log(&quot;Destroying session&quot;,'debug');
                $this-&gt;Session-&gt;destroy();
                $this-&gt;redirect($this-&gt;Auth-&gt;logout());
        }
}
</pre>
<p>You&#8217;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 <strong>$this-&gt;Auth-&gt;login()</strong> to get it to actually check the username and password and run the login logic.</p>
<p>We&#8217;re not done yet, we also need to create our view <strong>/App/View/Users/login.ctp</strong></p>
<pre class="brush: php; title: ; notranslate">
&lt;div id='loginForm'&gt;
&lt;?php
        echo $this-&gt;Session-&gt;flash('auth');
        echo $this-&gt;Form-&gt;create('Users', array('action' =&gt; 'login'));
        echo $this-&gt;Form-&gt;input('username');
        echo $this-&gt;Form-&gt;input('password',array('value'=&gt;''));
        echo $this-&gt;Form-&gt;input('remember',array('type' =&gt; 'checkbox', 'label' =&gt; 'Remember me'));
        echo $this-&gt;Form-&gt;submit('Login');
?&gt;
&lt;/div&gt;
</pre>
<p>Last piece to tie this all together is telling your application how to access your LDAP server. Add something like this to youyr <strong>/App/Config/database.php</strong></p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
class DATABASE_CONFIG {
        public $ldap = array (
                        'datasource' =&gt; 'Idbroker.LdapSource',
                        'host' =&gt; 'localhost',
                        'port' =&gt; 389,
                        'basedn' =&gt; 'DC=example,DC=com',
                        'login' =&gt; 'CN=Manager,DC=example,DC=com',     //For Proxy Userdn
                        'password' =&gt; 'LdapPassword',  //For Proxy UserDN password
                        'database' =&gt; '',
                        'tls'         =&gt; false,
                        'type' =&gt; 'OpenLDAP', //Available types are 'OpenLDAP', 'ActiveDirectory', 'Netscape'
                        'version' =&gt; 3
        );
}
</pre>
<p>And in your <strong>/App/Config/bootstrap.php</strong> add the following to the very bottom</p>
<pre class="brush: php; title: ; notranslate">
CakePlugin::load('Idbroker');
Configure::load('ldap');
</pre>
<p>These two lines tell your app to first load the Idbroker plugin and then load the ldap config file which you will create next.</p>
<p>Then create an ldap config file <strong>/App/Config/ldap.php</strong>  with the following.  This config file will configure how Ldap is used through out your app.  </p>
<pre class="brush: php; title: ; notranslate">
/**
 * 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?
</pre>
<p>That last part was a lot, not all of that is needed. Really just the first line is <strong>$config['LDAP']['Db']['Config'] = &#8216;ldap&#8217;;</strong> &#8211; 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.</p>
<p>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 &amp; curl to access authorized parts of your application. It is also used for rest applications.</p>
<p>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.</p>
<pre class="brush: php; title: ; notranslate">
        $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
</pre>
<h2>Have a question?</h2>
<p>Discuss it in the <a href="http://www.analogrithems.com/rant/forums/forum/cakephp-2-0-ldap-plugin/">CakePHP 2.0 Ldap Plugin</a> Forum</p>
<p class="facebook"><a href="http://www.facebook.com/share.php?u=http://www.analogrithems.com/rant/2012/01/03/cakephp-2-0-ldapauth/" target="_blank" title="Share on Facebook">Share on Facebook</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.analogrithems.com/rant/2012/01/03/cakephp-2-0-ldapauth/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>Revisionable Behavior in CakePHP</title>
		<link>http://www.analogrithems.com/rant/2011/12/05/revisionable-behavior-in-cakephp/</link>
		<comments>http://www.analogrithems.com/rant/2011/12/05/revisionable-behavior-in-cakephp/#comments</comments>
		<pubDate>Tue, 06 Dec 2011 03:40:01 +0000</pubDate>
		<dc:creator>analogrithems</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.analogrithems.com/rant/?p=969</guid>
		<description><![CDATA[There have been many times where I need to have some sort of revision ability in my cake apps.  I&#8217;ve looked through the bakery and never found a very good clean solution.  I thought about it for a bit and &#8230; <a href="http://www.analogrithems.com/rant/2011/12/05/revisionable-behavior-in-cakephp/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<a href='http://twitter.com/share?url=http%3A%2F%2Fwww.analogrithems.com%2Frant%2F%3Fp%3D969&count=horizontal&related=&text=Revisionable%20Behavior%20in%20CakePHP' class='twitter-share-button' data-text='Revisionable Behavior in CakePHP' data-url='http://www.analogrithems.com/rant/?p=969' data-counturl='http://www.analogrithems.com/rant/2011/12/05/revisionable-behavior-in-cakephp/' data-count='horizontal' data-via='analogrithems'></a><p>There have been many times where I need to have some sort of revision ability in my cake apps.  I&#8217;ve looked through the bakery and never found a very good clean solution.  I thought about it for a bit and it seems like a pretty simple thing to do, so I made a light weight simple behavior that provides this</p>
<p>The behavior is built into a plugin because it also has an simple model(table) that it uses to store revisions for all the other tables.  The idea is that when ever you update your table this behavior will jump in, grab the current copy of the data and save it to the revisions table with the current timestamp.  It then adds a few functions to your model you&#8217;ve added the behavior on to make sure it can see the previous behaviors.</p>
<p>One of the best features of this plugin is that it will store multiple models revisions all in the same table.</p>
<p>I&#8217;ve written this for CakePHP 1.3.x so it make not work with older or newer versions. Let me know if you have any questions or feedback</p>
<p>You may now be asking your self, where can one find such a fine piece of code?  As with most of my code it resides on github  <a href="https://github.com/analogrithems/revisionable">https://github.com/analogrithems/revisionable</a></p>
<p>So far it is very simple, all you have to do add re-visioning to your models is add the revisionable behavior to your plugin.</p>
<h3>Setup</h3>
<p>1) First you need to add the table to your project  use the following to generate that<br />
	cake schema create Revisionable.revision</p>
<p>2) add the behavior to your model like so </p>
<pre class="brush: php; title: ; notranslate">
	var $actAs = array('Revisionable.Revisionable');
</pre>
<h3>Some Configure options</h3>
<p>If you already have a table named revisions in your project and need to call the it something else then<br />
make a new table/model in your project that has the same schema as this plugin and pass that model name<br />
to the actAs setup like so</p>
<pre class="brush: php; title: ; notranslate">
	var $actAs('Revisionable.Revisionable'=&gt;array('revisionableModel'=&gt;$newModelName));
</pre>
<h2>To Do</h2>
<p>So far aside from creating a revision everytime the data changes the only other feature of this plugin<br />
is the listRevisions function.  It works like this</p>
<pre class="brush: php; title: ; notranslate">
	$revisions = $this-&gt;Model-&gt;listRevisions($this-&gt;Model-&gt;id);

	print_r($revisions);
	array(
		'2011-12-05 01:01:01'=&gt; array(
			'Pages' =&gt; array(
				'id'=&gt; '4edd8cc3-a628-490b-8cbf-6435ac1005e9',
				'name'=&gt; 'foobar',
				'body'=&gt; '....'
			)
		)
	);
</pre>
<p>Need to create some more functions that add to this, like a a restore where you pass the id &amp; date and<br />
it will do a restore and perhaps a diff viewer.  Patches are warmly welcome.</pre>
<p>&nbsp;<br />
Also I use uuid as my primaryKeys  I will try to find some time to ad a configuration option that will allow for int as the primaryKey.  In all reality, nothing really prevents this from working with int except for the table schema, so if you just change the table schema to use int then the rest of the plugin will follow.</p>
<p class="facebook"><a href="http://www.facebook.com/share.php?u=http://www.analogrithems.com/rant/2011/12/05/revisionable-behavior-in-cakephp/" target="_blank" title="Share on Facebook">Share on Facebook</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.analogrithems.com/rant/2011/12/05/revisionable-behavior-in-cakephp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ldap authentication in CakePHP</title>
		<link>http://www.analogrithems.com/rant/2011/08/26/ldap-authentication-in-cakephp/</link>
		<comments>http://www.analogrithems.com/rant/2011/08/26/ldap-authentication-in-cakephp/#comments</comments>
		<pubDate>Sat, 27 Aug 2011 04:49:22 +0000</pubDate>
		<dc:creator>analogrithems</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[ldap]]></category>

		<guid isPermaLink="false">http://www.analogrithems.com/rant/?p=305</guid>
		<description><![CDATA[It&#8217;s been over a year since I wrote the first version of the CakePHP LdapAuth &#38; Ldap Datasource. What I&#8217;ve learned over the last year is that a simple component &#38; datasource is not enough and it should really be &#8230; <a href="http://www.analogrithems.com/rant/2011/08/26/ldap-authentication-in-cakephp/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<a href='http://twitter.com/share?url=http%3A%2F%2Fwww.analogrithems.com%2Frant%2F%3Fp%3D305&count=horizontal&related=&text=Ldap%20authentication%20in%20CakePHP' class='twitter-share-button' data-text='Ldap authentication in CakePHP' data-url='http://www.analogrithems.com/rant/?p=305' data-counturl='http://www.analogrithems.com/rant/2011/08/26/ldap-authentication-in-cakephp/' data-count='horizontal' data-via='analogrithems'></a><p>It&#8217;s been over a year since I wrote the first version of the CakePHP LdapAuth &amp; Ldap Datasource. What I&#8217;ve learned over the last year is that a simple component &amp; datasource is not enough and it should really be a full plugin. So I started working on Idbroker. The new plugin offers the following</p>
<p>* A ldap Datasource that bad been tested with Iplanet, Netscape Directory Server, OpenLDAP &amp; Active Directory</p>
<p>* A revised Ldap Auth component that works with CakePHP 1.3</p>
<p>* A simple application (Which is still in development) that uses both and will give great examples of how to use.</p>
<p>Using this plugin you can get Ldap authentication in CakePHP.</p>
<p>To get started place a copy of the plugin in your plugins directory. Simplest way is to clone it from github</p>
<p>git clone https://github.com/analogrithems/idbroker</p>
<h1>Auth LDAP</h1>
<p>To make use of the LDAPAuth,</p>
<p>1) Add the following to either the controller you want to add LDAPAuth to or to app_controller to give all our controllers LDAPAuth</p>
<pre class="brush: php; title: ; notranslate">
var $components = array( 'Idbroker.LDAPAcl'=&gt;array('groupType'=&gt;'group'), 'Idbroker.LDAPAuth');
</pre>
<p>For the groupType, this really has to do with how your LDAP group objectClass is. For active directory your groupType will be &#8216;group&#8217; for most other LDAP v# implementations it will be either posixGroup (If the group stores membership info as memberUid=jdoe) or groupOfNames( if your group stores membership info as uniquemember=cn=jdoe,ou=people,dc=example,dc=com). If not set, it defaults to groupOfNames. If you are using Active Directory, set this to &#8216;group&#8217;</p>
<p>2) Add the LDAP settings to your /APP/config/database.php<br />
Now we need to get the LDAP settings plugged into the database.php file. This hasn&#8217;t changed much since the last version.</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
class DATABASE_CONFIG {
	var $ldap = array (
			'datasource' =&gt; 'Idbroker.Ldap',
			'host' =&gt; 'ldap.example.com',
			'port' =&gt; 389,
			'basedn' =&gt; 'DC=example,DC=com',
			'login' =&gt; 'CN=authservice,CN=Users,DC=example,DC=com',     //For Proxy Userdn Active Directory and sometimes iPlanet require this
			'password' =&gt; 'superSecretPassword',  //For Proxy UserDN password
			'database' =&gt; '',
			'tls'      =&gt; false, //If you are using TLS encryption set to true.
			'type' =&gt; 'ActiveDirectory', //Available types are 'OpenLDAP', 'ActiveDirectory', 'Netscape'
			'version' =&gt; 3
	);
}
?&gt;
</pre>
<p>3) The last step is to setup the LDAP settings. Create a file called /APP/config/ldap.php with the following. See comments for explanation of vars</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
/**
 * LDAP Settings
 *
 */
	$config['LDAP']['Db']['Config'] = 'ldap'; //What ever the config was called in the database.php file, defaults to ldap if not specified
	$config['LDAP']['User']['Identifier'] = 'samAccountName'; //The LDAP attribute that holds the username, defaults to uid, use samaccountname for AD
	$config['LDAP']['LdapAuth']['Model'] = 'Idbroker.LdapAuth'; //The model to use for the LDAPAuth Component, Should probably just set it to 'Idbroker.LdapAuth for must users
	$config['LDAP']['LdapACL']['Model'] = 'Idbroker.LdapAcl';  //The model to use for the developing LDAPAcl don't change unless you know what your doing
	$config['LDAP']['LdapACL']['groupType'] = 'group'; //group type refers to the group objectclass your ldap server uses.  can also be overwriten in the components array
?&gt;
</pre>
<p>add the following to the bottom of /APP/config/core.php</p>
<pre class="brush: php; title: ; notranslate">
//Ldap Config
Configure::load('ldap');
</pre>
<p class="facebook"><a href="http://www.facebook.com/share.php?u=http://www.analogrithems.com/rant/2011/08/26/ldap-authentication-in-cakephp/" target="_blank" title="Share on Facebook">Share on Facebook</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.analogrithems.com/rant/2011/08/26/ldap-authentication-in-cakephp/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Find the Schema Path In LDAP</title>
		<link>http://www.analogrithems.com/rant/2010/03/29/find-the-schema-path-in-ldap/</link>
		<comments>http://www.analogrithems.com/rant/2010/03/29/find-the-schema-path-in-ldap/#comments</comments>
		<pubDate>Tue, 30 Mar 2010 03:35:49 +0000</pubDate>
		<dc:creator>analogrithems</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[ldap]]></category>

		<guid isPermaLink="false">http://www.analogrithems.com/rant/?p=161</guid>
		<description><![CDATA[So I&#8217;ve been trying to find a good way to discover the schema path in LDAP that would work across Netscape style ldap servers as well as Active Directory.  See the problem is each one hides their schema path in &#8230; <a href="http://www.analogrithems.com/rant/2010/03/29/find-the-schema-path-in-ldap/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<a href='http://twitter.com/share?url=http%3A%2F%2Fwww.analogrithems.com%2Frant%2F%3Fp%3D161&count=horizontal&related=&text=Find%20the%20Schema%20Path%20In%20LDAP' class='twitter-share-button' data-text='Find the Schema Path In LDAP' data-url='http://www.analogrithems.com/rant/?p=161' data-counturl='http://www.analogrithems.com/rant/2010/03/29/find-the-schema-path-in-ldap/' data-count='horizontal' data-via='analogrithems'></a><p>So I&#8217;ve been trying to find a good way to discover the schema path in LDAP that would work across Netscape style ldap servers as well as Active Directory.  See the problem is each one hides their schema path in a different place.  Netscap style servers (Redhat-DS, Project 389, iPlanet, Sun One, etc) use &#8216;cn=schema&#8217;, while openldap has been known to use &#8216;cn=subschema&#8217; and Active Directory uses  <tt>'CN=Schema</tt>, <tt>CN= Configuration</tt>, <tt>DC=<em>forest_root_domain'</em></tt> this makes it really difficult to create a universal tool that can find any schema path.  In the past I would lift code from the PhpLDAPAdmin tool, but even they changed their methods.  Usually you get stuck using several case statements.  Recently I discovered a way to do a query to the Root DSE and have it just tell you where it has stored it&#8217;s schema data.   Use the <strong>subschemaSubentry </strong>to tell you exactly where the schema path is.</p>
<p>Here is an example of how to get it in PHP</p>
<p>$checkDN = @ldap_read($this-&gt;database, &#8221;, &#8216;objectClass=*&#8217;);<br />
$schemaEntry = ldap_get_entries($this-&gt;database, $checkDN);<br />
$SchemaDN = $schemaEntry[0]['subschemaSubentry'];</p>
<p class="facebook"><a href="http://www.facebook.com/share.php?u=http://www.analogrithems.com/rant/2010/03/29/find-the-schema-path-in-ldap/" target="_blank" title="Share on Facebook">Share on Facebook</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.analogrithems.com/rant/2010/03/29/find-the-schema-path-in-ldap/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>LdapAuth component for CakePHP</title>
		<link>http://www.analogrithems.com/rant/2009/06/13/ldapauth-component-for-cakephp/</link>
		<comments>http://www.analogrithems.com/rant/2009/06/13/ldapauth-component-for-cakephp/#comments</comments>
		<pubDate>Sat, 13 Jun 2009 22:08:52 +0000</pubDate>
		<dc:creator>analogrithems</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[ldap]]></category>
		<category><![CDATA[centralized authentication]]></category>

		<guid isPermaLink="false">http://www.analogrithems.com/rant/?p=40</guid>
		<description><![CDATA[So I was looking for a way to authenticate against LDAP with cake but I&#8217;ve found that it doesn&#8217;t support it by default. I found one that checks the auth against ldap then creates a local mysql account. This also &#8230; <a href="http://www.analogrithems.com/rant/2009/06/13/ldapauth-component-for-cakephp/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<a href='http://twitter.com/share?url=http%3A%2F%2Fwww.analogrithems.com%2Frant%2F%3Fp%3D40&count=horizontal&related=&text=LdapAuth%20component%20for%20CakePHP' class='twitter-share-button' data-text='LdapAuth component for CakePHP' data-url='http://www.analogrithems.com/rant/?p=40' data-counturl='http://www.analogrithems.com/rant/2009/06/13/ldapauth-component-for-cakephp/' data-count='horizontal' data-via='analogrithems'></a><p>So I was looking for a way to authenticate against LDAP with cake but I&#8217;ve found that it doesn&#8217;t support it by default.  I found one that checks the auth against ldap then creates a local mysql account.  This also didn&#8217;t use a actual ldap data sourc e either, it just handeled it&#8217;s own ldap connection.  After I read through the standard cakphp auth component I saw that it wouldn&#8217;t be that hard to write an LDAP based auth component.</p>
<p>First you need to download this file <a href="http://www.analogrithems.com/rant/wp-content/uploads/2009/06/ldap_auth.phps">ldap_auth.php</a> to your <strong>&#8216;app/controllers/components/&#8217;</strong> directory.</p>
<p>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</p>
<pre lang="php">
<?php
class User extends AppModel {
	var $name = 'User';
	var $useDbConfig = 'ldap';
	var $primaryKey = 'uid';
	var $useTable = 'ou=people';
}
?>
</pre>
<p>If some of these options are odd looking please have a look at my <a href="http://www.analogrithems.com/rant/?p=3">ldap data source </a> post.  </p>
<p>Next you are going to need your controller.  Here is the one I used  It defines the required functions like login, logout &#038; authorize. </p>
<pre lang="php">
<?php
class UsersController extends AppController {

	var $name = 'Users';
        var $components = array('RequestHandler', 'LdapAuth');
        var $helpers = array('Form','Html','Javascript', 'Ajax');

	function login() {
	}

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

        function isAuthorized() {
                return true;
        }

}
?>
</pre>
<p>7</p>
<p class="facebook"><a href="http://www.facebook.com/share.php?u=http://www.analogrithems.com/rant/2009/06/13/ldapauth-component-for-cakephp/" target="_blank" title="Share on Facebook">Share on Facebook</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.analogrithems.com/rant/2009/06/13/ldapauth-component-for-cakephp/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>CakePHP: LDAP with full CRUD, a living example!</title>
		<link>http://www.analogrithems.com/rant/2009/06/12/cakephp-with-full-crud-a-living-example/</link>
		<comments>http://www.analogrithems.com/rant/2009/06/12/cakephp-with-full-crud-a-living-example/#comments</comments>
		<pubDate>Fri, 12 Jun 2009 22:14:35 +0000</pubDate>
		<dc:creator>analogrithems</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[ldap]]></category>

		<guid isPermaLink="false">http://www.analogrithems.com/rant/?p=13</guid>
		<description><![CDATA[I&#8217;ve been using CakePHP for a while now and I&#8217;ve been thinking for a while it was time to see if I could give something back. As an IT leader I&#8217;m in love with LDAP. It makes life so simple &#8230; <a href="http://www.analogrithems.com/rant/2009/06/12/cakephp-with-full-crud-a-living-example/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<a href='http://twitter.com/share?url=http%3A%2F%2Fwww.analogrithems.com%2Frant%2F%3Fp%3D13&count=horizontal&related=&text=CakePHP%3A%20LDAP%20with%20full%20CRUD%2C%20a%20living%20example%21' class='twitter-share-button' data-text='CakePHP: LDAP with full CRUD, a living example!' data-url='http://www.analogrithems.com/rant/?p=13' data-counturl='http://www.analogrithems.com/rant/2009/06/12/cakephp-with-full-crud-a-living-example/' data-count='horizontal' data-via='analogrithems'></a><p><span>I&#8217;ve been using <span>CakePHP</span> for a while now and I&#8217;ve been thinking for a while it was time to see if I could give something back.  As an IT leader I&#8217;m in love with LDAP.  It makes life so simple for me and my team.  The big downside to LDAP is it&#8217;s not very easy to learn how all the <span>objectClasses</span> and attributes work with various applications.  Microsoft has eliminated this with the </span><em>Microsoft Management Console</em> (<em>MMC</em><span>).   It amazes me that no open source project has developed a tools such as this before.  I&#8217;ve worked on a open source tool in the past that was a web interface wrapper around <span>ldap</span> to do account management, so I&#8217;m familiar with the requirements such an application should have. Being that <span>CakePHP</span> is so powerful, I wanted to see if I could do this with that.</span></p>
<p><span>When I first started, I realized that <span>CakePHP</span> didn&#8217;t have an LDAP data source officially supported yet.  I did find two articles about some good attempts.  One by </span><a href="http://bakery.cakephp.org/articles/view/ldap-datasource-for-cakephp" target="_blank"><span><span><span>euphrate</span></span></span></a><span>, unfortunately this one was only for reading from <span>ldap</span>.  The second one was by </span><a href="http://memdump.wordpress.com/2008/04/26/ldap-data-source-now-with-full-crud/"><span><span>Gservat</span></span></a><span>, this one was a bit more complete, but was not really working for me and  as i read from his comments many others.  I think we wrote his for <span>CakePHP</span> 1.1.  Since I wanted to use Current cake 1.2.8xxx  I set out to use this as my start and fix/extend it.</span></p>
<p><span>Before we get started I want to state the environment I was using to do my work was <span>Redhat</span> Enterprise 5.2 &amp; Fedora 10 (Work requirement) with <span>redhat</span> directory server 8.1 and Fedora directory server 1.2.  Now while LDAP is a standard protocol, some of the driver may have become centric to those platforms, so if this is the case, please leave me a comment and I will try to correct the <span>ldap</span> data source I&#8217;m working on.  My hope is to get <span>ldap</span> as an <span>offical</span> <span>CakePHP</span> data source.  With that said the reason i call this a living example is because I&#8217;ve continued to upgrade and improve this data source as well as this article.  Some of the next features I want to implement is data associations.  Basically has and belongs to many relations.  This way when y<span>ou</span> look up an user account it also shows y<span>ou</span> all the groups that user is in.  This will take some time but I&#8217;ll get there.  This work is all being done in the hopes that I can use this data source and <span>CakePHP</span> to build a really user friendly web interface for managing enterprise LDAP infrastructures without a whole lot of LDAP knowledge.</span></p>
<p><strong><span>6/1/2011 &#8211; This <span>datasource</span> has gotten picked up by the <span>CakePHP</span> core guys and they may be </span><span>officially</span> adding it in the future.  I&#8217;ve also added some changes to support Active Directory better.</strong></p>
<p><strong><span>4/15/2010 &#8211; Made several changes to the code to hopefully play nicely with active directory.  Tested it with <span>CakePHP</span>-1.3 everything looks good.  Please test and leave feedback.  The new <span>datasource</span> requires y<span>ou</span> to add a new field to the database.<span>cfg</span> <span>ldap</span> entry.  See the <span>config</span> below</span><br />
</strong></p>
<p><strong><span>8/20/2009 &#8211; New Home for the source.  I&#8217;ve got this <span>datasource</span> in my  <span>github</span> tree now </span><a href="http://github.com/analogrithems/idbroker/tree/master/models/datasources"><span>http://<span>github</span>.com/<span>analogrithems</span>/<span>idbroker</span>/tree/master/models/<span>datasources</span></span></a> enjoy, and feel free to submit bugs or request there.</strong></p>
<p><strong><span>7/13/2009 &#8211; updated <span>ldap</span>_source.<span>php</span> to make better use of the debug describe code.  Also fixed the way things update.  Only update what has changed instead of whole record.  This will help with LDAP <span>aci</span> rules when logging in as non-admin users and trying to do things like update your <span>userpassword</span> or email.</span></strong></p>
<p><strong><span>6/20/2009 &#8211; Updated <span>ldap</span>_source.<span>php</span> to work with <span>OpenLDAP</span> 2.3 schema system.  First it will try &#8216;<span>cn</span>=schema&#8217;, if that doesn&#8217;t return any results then it looks for <span>schemas</span> in &#8216;<span>cn</span>=subschema&#8217;  this make sure the code will work with <span>OpenLDAP</span> as well as the Netscape based versions like <span>iPlanet</span>, <span>Redhat</span> Directory Server, Fedora Directory Server etc.</span></strong></p>
<p><span>First things first, here is my <span>ldap</span> data source for <span>CakePHP</span>.  Y<span>ou</span> will need to download this </span><a href="http://www.analogrithems.com/rant/wp-content/uploads/2009/07/ldap_source.phps" target="_blank"><span><span>ldap</span>_source.<span>php</span></span></a><span> to your &#8216;app/models/<span>datasources</span>/&#8217; directory.</span></p>
<p><span>So lets dive right in below is the database <span>config</span> we will use.</span></p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
class DATABASE_CONFIG {
var $ldap = array (
 		'datasource' =--&gt; 'ldap',
		'host' =&gt; 'localhost',
		'port' =&gt; 389,
		'basedn' =&gt; 'dc=examnple,dc=com',
		'login' =&gt; '',
		'password' =&gt; '',
		'database' =&gt; '',
                'tls'         =&gt; false,
                'type' =&gt; 'Netscape', //Available types are 'OpenLDAP', 'ActiveDirectory', 'Netscape'
		'version' =&gt; 3
	);
}
?&gt;
</pre>
<p><span>Y<span>ou</span> notice that the variables database, <span>login</span> and password are blank.  Keep at least database this way.  Y<span>ou</span> can populate <span>login</span> and password if don&#8217;t want your <span>ldap</span> connections to be anonymous.  I keep mine blank because I have written my own <span>auth</span> component that uses <span>ldap</span>,   So once I&#8217;m <span>authed</span> that gets passed to the <span>datasource</span> instead.  This is a ugly hack that I&#8217;ve written another </span><a href="http://www.analogrithems.com/rant/2009/06/13/ldapauth-component-for-cakephp/">post about</a>.</p>
<p><span>Please note that if y<span>ou</span> are using <span>Redhat</span> directory server, <span>iPlanet</span> or Fedora Project 389 then the </span><strong>type</strong> is Netscape as these all evolved off the Netscape LDAP server code base.  The other available types are &#8216;OpenLDAP&#8217; or &#8216;ActiveDirectory&#8217;  (case matters).</p>
<p>Here is our people model for accessing the users in your LDAP tree.</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
class Person extends AppModel {
        var $name = 'Person';
        var $useDbConfig = 'ldap';

        // This would be the ldap equivalent to a primary key if your dn is
        // in the format of uid=username, ou=people, dc=example, dc=com
        var $primaryKey = 'uid';

        // The table would be the branch of your basedn that you defined in
        // the database config
        var $useTable = '';

        var $validate = array(
                'cn' =&gt; array(
                        'alphaNumeric' =&gt; array(
                                'rule' =&gt; array('custom', '/^[a-zA-Z ]+$/'),
                                'required' =&gt; true,
                                'on' =&gt; 'create',
                                'message' =&gt; 'Only Letters, Numbers and spaces	 can be used for Display Name.'
                        ),
                        'between' =&gt; array(
                                'rule' =&gt; array('between', 5, 40),
                                'on' =&gt; 'create',
                                'message' =&gt; 'Between 5 to 40 characters'
                        )
                ),
                'sn' =&gt; array(
                                'rule' =&gt; array('custom', '/^[a-zA-Z]*$/'),
                                'required' =&gt; true,
                                'on' =&gt; 'create',
                                'message' =&gt; 'Only Letters and Numbers can be used for Last Name.'
                ),
                'userpassword' =&gt; array(
                                'rule' =&gt; array('minLength', '8'),
                                'message' =&gt; 'Mimimum 8 characters long.'
                ),
                'uid' =&gt; array(
                                'rule' =&gt; array('custom', '/^[a-zA-Z0-9]*$/'),
                                'required' =&gt; true,
                                'on' =&gt; 'create',
                                'message' =&gt; 'Only Letters and Numbers can be used for Username.'
                )
        );
}
?&gt;
</pre>
<p>Here is a very basic controller to accompany our people model.  It demonstrates the important core functions and should get you started on using this data source with your own application.</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
class PeopleController extends AppController {

	var $name = 'People';
	var $components = array('RequestHandler', 'Ldap');
	var $helpers = array('Form','Html','Javascript', 'Ajax');

	function add(){
		if(!empty($this-&gt;data)){
			$this-&gt;data['Person']['objectclass'] = array('top', 'organizationalperson', 'inetorgperson','person','posixaccount','shadowaccount');

			if($this-&gt;data['Person']['password'] == $this-&gt;data['Person']['password_confirm']){
				$this-&gt;data['Person']['userpassword'] = $this-&gt;data['Person']['password'];
				unset($this-&gt;data['Person']['password']);
				unset($this-&gt;data['Person']['password_confirm']);

				if(!isset($this-&gt;data['Person']['homedirectory'])&amp;&amp; isset($this-&gt;data['Person']['uid'])){
					$this-&gt;data['Person']['homedirectory'] = '/home/'.$this-&gt;data['Person']['uid'];
				}

				$cn = $this-&gt;data['Person']['cn'];
				if ($this-&gt;Person-&gt;save($this-&gt;data)) {
					$this-&gt;Session-&gt;setFlash($cn.' was added Successfully.');
					$id = $this-&gt;Person-&gt;id;
					$this-&gt;redirect(array('action' =&gt; 'view', 'id'=&gt; $id));
				}else{
					$this-&gt;Session-&gt;setFlash(&quot;$cn couldn't be created.&quot;);
				}
			}else{
				$this-&gt;Session-&gt;setFlash(&quot;Passwords don't match.&quot;);
			}
		}
		$attributes = array('uidnumber', 'uid', 'homedirectory');
		$preset = $this-&gt;autoSet($attributes);
		foreach($this-&gt;data['Person'] as $key =&gt; $value){
			$preset[$key] = $value;
		}
		$this-&gt;data['Person'] = $preset;

		$groups = $this-&gt;Ldap-&gt;getGroups(array('cn','gidnumber'),null,'posixgroup');
		foreach($groups as $group){
			$groupList[$group['gidnumber']] = $group['cn'];
		}
		natcasesort($groupList);
		$this-&gt;set('groups',$groupList);
		$this-&gt;layout = 'people';
	}

	function view( $id ){
		if(!empty($id)){
			$filter = $this-&gt;Person-&gt;primaryKey.&quot;=&quot;.$id;
			$people = $this-&gt;Person-&gt;find('first', array( 'conditions'=&gt;$filter));
			$this-&gt;set(compact('people'));
		}
		$this-&gt;layout = 'people';
	}

	function delete($id = null) {
		$this-&gt;Person-&gt;id = $id;
		return $this-&gt;Person-&gt;del($id);
	}

	/**
	*  The AuthComponent provides the needed functionality
	*  for login, so you can leave this function blank.
	*/
	function login() {
	}

	function logout() {
		$this-&gt;redirect($this-&gt;LdapAuth-&gt;logout());
	}

	//Very Ugly, fix this.,
	function isAuthorized() {
		return true;
	}

}
</pre>
<p>So lets talk about somethings here,  in our model we define <strong><span>$<span>primaryKey</span></span></strong> &amp; <strong><span>$<span>useTable</span></span></strong> variables.  The <strong><span>$<span>useTable</span></span></strong><span> is the branch of the <span>ldap</span> server.  For this models purpose we define our table as </span><strong>&#8216;ou=people&#8217;</strong>.  This makes sure that objects we create (I.E. Users/people)  will be added under the organization unit people.  It also makes sure that when you pass something like &#8216;jdoe&#8217; to the delete action it will search that branch for the user object to delete.  The <strong><span>$<span>primaryKey</span></span></strong><span> also helps in the creation and deleting of users.  It makes sure that the <span>dn</span> is created as <span>uid</span>, this is helpful to make sure that a user doesn&#8217;t already have that user name.  Also since <span>ldap</span> is case insensitive y<span>ou</span> don&#8217;t have to worry about the possible variations of the object names when checking the existence.</span></p>
<p>Now your model isn&#8217;t limited to one branch or object type.  If you wanted to create a browser for example your could define a model like the following.</p>
<p>You&#8217;ll notice here we set our <strong><span>$<span>useTable</span></span></strong><span> to nothing (important, y<span>ou</span> get errors about no db defined from <span>CakePHP</span> if this missing).  The really interesting part here is that we set </span><strong>$primaryKey</strong><span> to <span>dn</span>.  This is the ultimate primary key for our type or data source.  The difference here is that when we create/delete an object we have to pass it the full <span>dn</span>.</span></p>
<p>Our new data source also adds some new options to the find function.<br />
<strong>$options['targetDN'] :</strong><span> This is more like the point in the tree we want to start our search.  If y<span>ou</span> don&#8217;t define it it defaults to the $<span>useTable</span>.$<span>config</span>[$<span>useDbConfig</span>]['basedn']  if your $<span>useTable</span> variable is empty it defaults to the <span>basedn</span> configured in your database <span>config</span>.</span></p>
<p><strong>$options['scope'] :</strong><span> If you&#8217;ve worked with <span>ldap</span> before then y<span>ou</span> are familiar with the concept of search scopes.  Y<span>ou</span> have three search scopes, &#8216;sub&#8217;, &#8216;one, &amp; &#8216;base&#8217;.  Basically </span><strong>sub</strong> means search from this point down the tree.  <strong>one</strong> means search one level below this point and <strong>base</strong><span> means search just this point.  For example if y<span>ou</span> wanted to see if a user already existed y<span>ou</span> could set the targetDn to <span>uid</span>=<span>jdoe</span>,<span>ou</span>=people,dc=example,dc=com and it will check if this object already exists.   The default scope is </span><strong>sub</strong></p>
<p class="facebook"><a href="http://www.facebook.com/share.php?u=http://www.analogrithems.com/rant/2009/06/12/cakephp-with-full-crud-a-living-example/" target="_blank" title="Share on Facebook">Share on Facebook</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.analogrithems.com/rant/2009/06/12/cakephp-with-full-crud-a-living-example/feed/</wfw:commentRss>
		<slash:comments>60</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic

Served from: www.analogrithems.com @ 2012-02-05 02:09:05 -->
