Tag Archives: authentication

CakePHP and the (in)famous Auth component

After struggling for a while with CakePHP (specifically 1.2 rc3, but also in general) and the Auth Component, I finally found out how it works. While working freelance on a site for a customer, I had to make some form of Authentication in order to login the users of the system etc. What better place to start than CakePHP’s own documentation: http://book.cakephp.org/view/172/Authentication… This didn’t really help me on my quest, as all they started was:

<?php
class UsersController extends AppController {
	var $name = 'Users';    
	var $components = array('Auth'); // Not necessary if declared in your app controller

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

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

And you need to have a users table with the following information as well:

CREATE TABLE users (
	id integer auto_increment,
	username char(50),
	password char(50),
	PRIMARY KEY (id)
);

And all else is Cake… however… this isn’t entirely correct though.

As I found out, a lot more actually has to be done before “the rest Cake”. So in order for you not to do the same as I did, here’s what I did…

In the example i’m using the following database table:

CREATE TABLE users (
	id integer auto_increment,
	username char(50),
	password char(50),
	PRIMARY KEY (id)
);

insert into users(username,password) values('jimmi',md5('12345'));

And the following model:

path: app/models/user.php

<?php
class User extends AppModel {
	var $name = 'User';
}
?>

In order to make Authentication work on all my pages, I created an AppController that extended Controller:

path: app/app_controller.php

<?php

class AppController extends Controller {	
	var $components = array('Auth');
	
	function beforeFilter() {
		// Handle the user auth filter
		// This, along with no salt in the config file allows for straight
		// md5 passwords to be used in the user model
		Security::setHash("md5");
		
		$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');  
		$this->Auth->loginRedirect = array('controller' => 'users', 'action' => 'login');
		$this->Auth->logoutRedirect = '/'; 
		$this->Auth->allow('display');  
		
		// Controller autorization is the simplest form.

		$this->Auth->authorize = 'controller'; 
	}

	function isAuthorized() {  
		return true;  
	}
	
	function beforeRender() {
		$this->set('user', $this->Auth->user());
	}
}

?>

I use md5 for encrypting my passwords in the database, hence the Security::setHash(“md5″).

All of the $this->Auth->xxx-things are explained here A Hopefully Useful Tutorial For Using CakePHP’s Auth Component and CakePHP Auth Component For Dummies Tutorial (so no need to go through it here as well).

The real “magic” of my AppController is, that i’ve created the beforeRender() function. Here I set the Auth->user() in the $user variable, in order to be able to access it from the views.
The reason why I did this, was because I couldn’t access the Auth component through the session

<?php echo $session->read('Auth.user'); ?>

as suggested here: groups.google.com/cake-php

I created a simple UsersController that extended my AppController:

path: app/controllers/users_controller.php

<?php

class UsersController extends AppController {
	var $name = 'Users';
	var $helpers = array('Html', 'Form', 'Session' );
	
	function login() {
		
	}
	
	function logout() {
		$this->redirect($this->Auth->logout());
	}
}

?>

Here I included the Form helper. The reason why I used the Form-helper was, that when did the following:

<form method="post" action="/users/login">
	username:<br/>
	<input type="text" name="username"/><br/>
	password:<br/>
	<input type="password" name="password"/><br/>
	<input type="submit" value="Sign In"/>
</form>

my data wasn’t sent properly to the Auth component and no Cake magic was being performed. By using the Form-helper to create a login-view, the data was properly sent to the Auth component:

path: app/controllers/users_controller.php

<?php
/*
 * just to test that the user is actually logged in, i'm getting the username 
 * from the $user variable, set in the AppController->beforeRender()
 */
echo "Current user: ".$user['User']['username']."<br/>";
?>

<div class="user">

	<?php
		echo $form->create('User', array('action' => 'login'));

		echo $form->input('username');

		echo $form->input('password');

		echo $form->end('Sign In');
	?>

</div>

This made it all work for me.

Just a small extra tip. When setting $this->Auth->allow(‘xxx’) in the different controller’s beforeFilter() function, remember to make a call to parent::beforeFilter(); first.
The reason why it gave me some problems (which it might not do for you), was because of the fact that I did some other stuff in my AppController’s beforeFilter() function…
This also took me some time to figure out, since I just assumed that Cake did the call for me… but nope.
An example could be in the UsersController where i’d like to have a view($userId) function… e.g.:

path: app/controllers/users_controller.php

<?php

class UsersController extends AppController {
	var $name = 'Users';
	var $helpers = array('Html', 'Form', 'Session' );
	
	function beforeFilter() {
		parent::beforeFilter();
		
		$this->Auth->allow('view');
	}
	
	function login() {
		
	}
	
	function logout() {
		$this->redirect($this->Auth->logout());
	}
	
	function view($userId) {
		// do interesting stuff here...
	}
}

?>

That was it for now… I like CakePHP, but the documentation is sometime… kinda… well… rather lacking…