{"id":1079,"date":"2012-01-03T19:33:11","date_gmt":"2012-01-04T02:33:11","guid":{"rendered":"http:\/\/www.analogrithems.com\/rant\/?p=1079"},"modified":"2012-01-18T23:05:52","modified_gmt":"2012-01-19T06:05:52","slug":"cakephp-2-0-ldapauth","status":"publish","type":"post","link":"https:\/\/www.analogrithems.com\/rant\/cakephp-2-0-ldapauth\/","title":{"rendered":"CakePHP 2.0 Ldap Authentication"},"content":{"rendered":"<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. \u00c2\u00a0I finally sat down last weekend and updated my LDAPAuth component to work with the new version. \u00c2\u00a0While 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>\n<p>You can get the new code at\u00c2\u00a0<a href=\"https:\/\/github.com\/analogrithems\/idbroker\/tree\/dev_cake2.0\">https:\/\/github.com\/analogrithems\/idbroker\/tree\/dev_cake2.0<\/a><\/p>\n<p>To get things going download the idbroker code from github and place it in your \u00c2\u00a0plugin folder\u00c2\u00a0<strong>App\/Plugin\/Idbroker<\/strong>\u00c2\u00a0pay attention to the new capital first letter. \u00c2\u00a0This is a new convention for the CakePHP 2.0 to help in automatic class loading.<\/p>\n<p>Now in your <strong>App\/Controller\/AppController.php<\/strong>\u00c2\u00a0you need a minimal of the following<\/p>\n<p>[php]<br \/>\n&lt;?php<br \/>\nclass AppController extends Controller {<br \/>\n        var $components = array(&#8216;Auth&#8217;, &#8216;Session&#8217;, &#8216;RequestHandler&#8217;);<\/p>\n<p>        var $user;<\/p>\n<p>        function beforeFilter(){<br \/>\n                global $menus;<br \/>\n                $this-&gt;Auth-&gt;authenticate = array(&#8216;Idbroker.Ldap&#8217;=&gt;array(&#8216;userModel&#8217;=&gt;&#8217;Idbroker.LdapAuth&#8217;));<br \/>\n                \/\/If you want to do your authorization from the isAuthorized Controller use the following<br \/>\n                $this-&gt;Auth-&gt;authorize = array(&#8216;Controller&#8217;);<br \/>\n        }<\/p>\n<p>        \/*<br \/>\n        * This just says aslong as this is a valid user let them in, you can also modify this to restrict to a group<br \/>\n        *\/<br \/>\n        public function isAuthorized(){<br \/>\n                $user = $this-&gt;Auth-&gt;user();<br \/>\n                if($user) return true;<br \/>\n                return false;<br \/>\n        }<br \/>\n}<br \/>\n[\/php]<\/p>\n<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>\n<p>The next step is to configure your Users controller and your views.<\/p>\n<p>In your <strong>\/App\/Controller\/UsersController.php<\/strong><\/p>\n<p>[php]<br \/>\n&lt;?php<br \/>\nclass UsersController extends AppController {<br \/>\n        var $name = &#8216;Users&#8217;;<\/p>\n<p>        \/*<br \/>\n        * Make sure to define which functions don&#8217;t require auth to be accessed<br \/>\n        *\/<br \/>\n        function beforeFilter(){<br \/>\n                $this-&gt;Auth-&gt;allow(&#8216;usernameExists&#8217;, &#8216;forgotPassword&#8217;, &#8216;signup&#8217;,&#8217;login&#8217;,&#8217;logout&#8217;);<br \/>\n                parent::beforeFilter();<br \/>\n        }<\/p>\n<p>        function login(){<br \/>\n                if ($this-&gt;request-&gt;is(&#8216;post&#8217;)) {<br \/>\n                        if ($this-&gt;Auth-&gt;login()) {<br \/>\n                                return $this-&gt;redirect($this-&gt;Auth-&gt;redirect());<br \/>\n                        } else {<br \/>\n                                $this-&gt;Session-&gt;setFlash(__(&#8216;Username or password is incorrect&#8217;), &#8216;default&#8217;, array(&#8216;class&#8217;=&gt;&#8217;error-message&#8217;), &#8216;auth&#8217;);<br \/>\n                        }<br \/>\n                }<br \/>\n        }<\/p>\n<p>        function logout(){<br \/>\n                $this-&gt;log(&quot;Destroying session&quot;,&#8217;debug&#8217;);<br \/>\n                $this-&gt;Session-&gt;destroy();<br \/>\n                $this-&gt;redirect($this-&gt;Auth-&gt;logout());<br \/>\n        }<br \/>\n}<br \/>\n[\/php]<\/p>\n<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>\n<p>We&#8217;re not done yet, we also need to create our view <strong>\/App\/View\/Users\/login.ctp<\/strong><\/p>\n<p>[php]<br \/>\n&lt;div id=&#8217;loginForm&#8217;&gt;<br \/>\n&lt;?php<br \/>\n        echo $this-&gt;Session-&gt;flash(&#8216;auth&#8217;);<br \/>\n        echo $this-&gt;Form-&gt;create(&#8216;Users&#8217;, array(&#8216;action&#8217; =&gt; &#8216;login&#8217;));<br \/>\n        echo $this-&gt;Form-&gt;input(&#8216;username&#8217;);<br \/>\n        echo $this-&gt;Form-&gt;input(&#8216;password&#8217;,array(&#8216;value&#8217;=&gt;&#8221;));<br \/>\n        echo $this-&gt;Form-&gt;input(&#8216;remember&#8217;,array(&#8216;type&#8217; =&gt; &#8216;checkbox&#8217;, &#8216;label&#8217; =&gt; &#8216;Remember me&#8217;));<br \/>\n        echo $this-&gt;Form-&gt;submit(&#8216;Login&#8217;);<br \/>\n?&gt;<br \/>\n&lt;\/div&gt;<br \/>\n[\/php]<\/p>\n<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>\n<p>[php]<br \/>\n&lt;?php<br \/>\nclass DATABASE_CONFIG {<br \/>\n        public $ldap = array (<br \/>\n                        &#8216;datasource&#8217; =&gt; &#8216;Idbroker.LdapSource&#8217;,<br \/>\n                        &#8216;host&#8217; =&gt; &#8216;localhost&#8217;,<br \/>\n                        &#8216;port&#8217; =&gt; 389,<br \/>\n                        &#8216;basedn&#8217; =&gt; &#8216;DC=example,DC=com&#8217;,<br \/>\n                        &#8216;login&#8217; =&gt; &#8216;CN=Manager,DC=example,DC=com&#8217;,     \/\/For Proxy Userdn<br \/>\n                        &#8216;password&#8217; =&gt; &#8216;LdapPassword&#8217;,  \/\/For Proxy UserDN password<br \/>\n                        &#8216;database&#8217; =&gt; &#8221;,<br \/>\n                        &#8216;tls&#8217;         =&gt; false,<br \/>\n                        &#8216;type&#8217; =&gt; &#8216;OpenLDAP&#8217;, \/\/Available types are &#8216;OpenLDAP&#8217;, &#8216;ActiveDirectory&#8217;, &#8216;Netscape&#8217;<br \/>\n                        &#8216;version&#8217; =&gt; 3<br \/>\n        );<br \/>\n}<br \/>\n[\/php]<\/p>\n<p>And in your <strong>\/App\/Config\/bootstrap.php<\/strong> add the following to the very bottom<\/p>\n<p>[php]<br \/>\nCakePlugin::load(&#8216;Idbroker&#8217;);<br \/>\nConfigure::load(&#8216;ldap&#8217;);<br \/>\n[\/php]<\/p>\n<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>\n<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>\n<p>[php]<br \/>\n\/**<br \/>\n * LDAP Settings<br \/>\n *<br \/>\n *\/<br \/>\n        $config[&#8216;LDAP&#8217;][&#8216;Db&#8217;][&#8216;Config&#8217;] = &#8216;ldap&#8217;; \/\/What is the name of the db config that has the LDAP credentials<br \/>\n        $config[&#8216;LDAP&#8217;][&#8216;User&#8217;][&#8216;Identifier&#8217;] = &#8216;uid&#8217;; \/\/What is the LDAP attribute that identifies the username attribute,<br \/>\n                                                       \/\/ openldap, iplant, netscapr use uid, AD uses samaccountname<br \/>\n        $config[&#8216;LDAP&#8217;][&#8216;Group&#8217;][&#8216;Identifier&#8217;] = &#8216;cn&#8217;; \/\/What is the LDAP attribute that identifies the group name, usually cn<br \/>\n        $config[&#8216;LDAP&#8217;][&#8216;Model&#8217;] = &#8216;Idbroker.LdapAuth&#8217;; \/\/Default model to use for LDAP components<br \/>\n        $config[&#8216;LDAP&#8217;][&#8216;LdapAuth&#8217;][&#8216;Model&#8217;] = &#8216;Idbroker.LdapAuth&#8217;;<br \/>\n        $config[&#8216;LDAP&#8217;][&#8216;LdapAuth&#8217;][&#8216;MirrorSQL&#8217;][&#8216;Users&#8217;] = &#8216;User&#8217;; \/\/A SQL table to duplicate ldap records in for user<br \/>\n        $config[&#8216;LDAP&#8217;][&#8216;LdapAuth&#8217;][&#8216;MirrorSQL&#8217;][&#8216;Groups&#8217;] = &#8216;Group&#8217;; \/\/A SQL table to duplicate LDAP records in for groups<br \/>\n        $config[&#8216;LDAP&#8217;][&#8216;LdapACL&#8217;][&#8216;Model&#8217;] = &#8216;Idbroker.LdapAcl&#8217;;<br \/>\n        $config[&#8216;LDAP&#8217;][&#8216;LdapACL&#8217;][&#8216;groupType&#8217;] = &#8216;group&#8217;;<br \/>\n        $config[&#8216;LDAP&#8217;][&#8216;groupType&#8217;] = &#8216;groupofuniquenames&#8217;; \/\/What object class do you use for your groups?<br \/>\n        $config[&#8216;LDAP&#8217;][&#8216;Group&#8217;][&#8216;behavior&#8217;][&#8216;tree&#8217;][&#8216;parent_id&#8217;] = &#8217;49db8df1-5e74-4e91-b15f-4d33e927f14e&#8217;; \/\/Are you using a tree behavior?  Need to set the default parent_id?<br \/>\n[\/php]<\/p>\n<p>That last part was a lot, not all of that is needed. Really just the first line is <strong>$config[&#8216;LDAP&#8217;][&#8216;Db&#8217;][&#8216;Config&#8217;] = &#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>\n<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>\n<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>\n<p>[php]<br \/>\n        $config[&#8216;LDAP&#8217;][&#8216;LdapAuth&#8217;][&#8216;MirrorSQL&#8217;][&#8216;Users&#8217;] = &#8216;User&#8217;; \/\/A SQL table to duplicate ldap records in for user<br \/>\n        $config[&#8216;LDAP&#8217;][&#8216;LdapAuth&#8217;][&#8216;MirrorSQL&#8217;][&#8216;Groups&#8217;] = &#8216;Group&#8217;; \/\/A SQL table to duplicate LDAP records in for groups<br \/>\n        $config[&#8216;LDAP&#8217;][&#8216;User&#8217;][&#8216;Identifier&#8217;] = &#8216;uid&#8217;; \/\/What is the LDAP attribute that identifies the username attribute,<br \/>\n                                                       \/\/ openldap, iplant, netscapr use uid, AD uses samaccountname<br \/>\n        $config[&#8216;LDAP&#8217;][&#8216;Group&#8217;][&#8216;Identifier&#8217;] = &#8216;cn&#8217;; \/\/What is the LDAP attribute that identifies the group name, usually cn<br \/>\n[\/php]<\/p>\n<h2>Have a question?<\/h2>\n<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>\n","protected":false},"excerpt":{"rendered":"<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. \u00c2\u00a0I finally sat down last weekend and updated my LDAPAuth component to work with the new version. \u00c2\u00a0While I was doing it I added a few new features that people [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8,3,40],"tags":[],"class_list":["post-1079","post","type-post","status-publish","format-standard","hentry","category-cakephp","category-ldap","category-web-development"],"_links":{"self":[{"href":"https:\/\/www.analogrithems.com\/rant\/wp-json\/wp\/v2\/posts\/1079","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.analogrithems.com\/rant\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.analogrithems.com\/rant\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.analogrithems.com\/rant\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.analogrithems.com\/rant\/wp-json\/wp\/v2\/comments?post=1079"}],"version-history":[{"count":13,"href":"https:\/\/www.analogrithems.com\/rant\/wp-json\/wp\/v2\/posts\/1079\/revisions"}],"predecessor-version":[{"id":1151,"href":"https:\/\/www.analogrithems.com\/rant\/wp-json\/wp\/v2\/posts\/1079\/revisions\/1151"}],"wp:attachment":[{"href":"https:\/\/www.analogrithems.com\/rant\/wp-json\/wp\/v2\/media?parent=1079"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.analogrithems.com\/rant\/wp-json\/wp\/v2\/categories?post=1079"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.analogrithems.com\/rant\/wp-json\/wp\/v2\/tags?post=1079"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}