Custom login function with cakephp

Here is a quick tutorial how to override the default cakephp authentication components and write your own login/authentication script. Using Auth components everyone will be familiar with two login variables called username name password so if you want to use email as username there is provision in app_controller to redefine login fields. But this article is more to that. Suppose we want to authenticate users against three variables than just username name password for example if we have email, password and owner fields in our user table where email id field is not unique and there can be multiple occurrence of same email but their owner values will differ this type of cases are common in multi tenant architecture or SaaS applications, now how do you distinguish between the two users and fetch the correct one. Another example can be authenticating against two passwords.

Flow of this approach

We need to write our own Auth component by extending original library Auth component and override its method called identify() also we need to customize how many fields a login form will pass. Now follow the steps below

Create a component MyAuth in a file my_auth.php placed under app/controllers/components the content of this file will be something like this

=== my_auth.php ===

</code></p>
<p>App::import('Component', 'Auth');<br />
class MyAuthComponent extends  AuthComponent {</p>
<p>}</p>
<p><code>

====

This is not complete script but just to show how to create this class,  Auth component is included in your app_controller.php  as

var $components = array(‘Auth’);  we need to replace Auth with MyAuth

var $components = array(‘MyAuth’);

Next this is there will be numerous occurrence of $this->Auth variable in app_controller as well as in other application controllers we need to replace all of them by $this->MyAuth

On app_controllers beforeFilter method there might be existing entry earlier created by you if yes edit or create this line

$this->MyAuth->fields = array(‘username’ => ‘email’, ‘password’ => ‘password’, ‘owner’ => ‘owner’);

Assuming that “owner” is the third field present in the users table that you want to use for authenticating login. Now there is last thing that remains is we need to override the identify($user = null, $conditions = null)  method from Auth controller this can be done by copying existing code from libraries Auth component to this MyAuth class so our class now becomes

==== my_auth.php ====

</code></p>
<p>App::import('Component', 'Auth');<br />
class MyAuthComponent extends  AuthComponent {<br />
var $owner;<br />
function identify($user = null, $conditions = null) {</p>
<p>if ($conditions === false) {<br />
$conditions = null;<br />
} elseif (is_array($conditions)) {<br />
$conditions = array_merge((array)$this->userScope, $conditions);<br />
} else {<br />
$conditions = $this->userScope;<br />
}<br />
if (empty($user)) {<br />
$user = $this->user();<br />
if (empty($user)) {<br />
return null;<br />
}<br />
} elseif (is_object($user) && is_a($user, 'Model')) {<br />
if (!$user->exists()) {<br />
return null;<br />
}<br />
$user = $user->read();<br />
$user = $user[$this->userModel];<br />
} elseif (is_array($user) && isset($user[$this->userModel])) {<br />
$user = $user[$this->userModel];<br />
}</p>
<p>if (is_array($user) && (isset($user[$this->fields['username']]) || isset($user[$this->userModel . '.' . $this->fields['username']]))) {</p>
<p>if (isset($user[$this->fields['username']]) && !empty($user[$this->fields['username']])  && !empty($user[$this->fields['password']])) {<br />
if (trim($user[$this->fields['username']]) == '=' || trim($user[$this->fields['password']]) == '=') {<br />
return false;<br />
}<br />
$find = array(<br />
$this->userModel.'.'.$this->fields['username'] => $user[$this->fields['username']],<br />
$this->userModel.'.'.$this->fields['password'] => $user[$this->fields['password']],<br />
$this->userModel.'.'.$this->fields['owner'] => OWNER<br />
);<br />
} elseif (isset($user[$this->userModel . '.' . $this->fields['username']]) && !empty($user[$this->userModel . '.' . $this->fields['username']])) {<br />
if (trim($user[$this->userModel . '.' . $this->fields['username']]) == '=' || trim($user[$this->userModel . '.' . $this->fields['password']]) == '=') {<br />
return false;<br />
}<br />
$find = array(<br />
$this->userModel.'.'.$this->fields['username'] => $user[$this->userModel . '.' . $this->fields['username']],<br />
$this->userModel.'.'.$this->fields['password'] => $user[$this->userModel . '.' . $this->fields['password']],<br />
$this->userModel.'.'.$this->fields['owner'] => OWNER<br />
);<br />
} else {<br />
return false;<br />
}<br />
$model =& $this->getModel();<br />
$data = $model->find(array_merge($find, $conditions), null, null, 0);<br />
if (empty($data) || empty($data[$this->userModel])) {<br />
return null;<br />
}<br />
} elseif (!empty($user) && is_string($user)) {<br />
$model =& $this->getModel();<br />
$data = $model->find(array_merge(array($model->escapeField() => $user), $conditions));</p>
<p>if (empty($data) || empty($data[$this->userModel])) {<br />
return null;<br />
}<br />
}</p>
<p>if (!empty($data)) {<br />
if (!empty($data[$this->userModel][$this->fields['password']])) {<br />
unset($data[$this->userModel][$this->fields['password']]);<br />
}<br />
return $data[$this->userModel];<br />
}<br />
return null;<br />
}<br />
}</p>
<p><code>

=======

Here the OWNER constant is defined from define() method in app_controller and therefore available in all classes. Thats it done…!

var $components = array(‘MyAuth’, ‘Log’);

Leave a Reply

*