Demystifying Auth features in CakePHP 1.2

This is actually a quick follow-up to the tutorial I’ve posed recently, which had a few simple, but not very obvious Auth component techniques.

I’d like to cover them in more detail here…

Let’s take a look at the app_controller.php again:

class AppController extends Controller {
    var $components = array('Auth');

    function beforeFilter() {
        $this->Auth->allow('display');
        $this->Auth->loginRedirect = array('controller'=>'users', 'action'=>'index');
    }
}

$this->Auth->allow(‘display’); tells the Auth component to allow a special action called ‘display’. This action is actually part of the Pages Controller, which you can find in the cake’s core. The main purpose of this controller is to serve static pages. You can take a look at the API to see how it works exactly, but one thing to keep in mind is that ‘display’ action is responsible for the… well… display of your static pages. If not allowed, by default, Auth will restrict access to your homepage or ‘About us’ page, for example. This effect is probably not desired in many cases.

$this->Auth->loginRedirect = array(‘controller’=>’users’, ‘action’=>’index’); tells Auth component where to redirect the user after the login. By default Auth would redirect to the main page (root) of your site, or previously visited page… depending on the situation.

Next, in the Users Controller you’ll notice the following:

if($this->action == 'add') {
  $this->Auth->authenticate = $this->User;
}

$this->Auth->authenticate = $this->User; tells the Auth component that it should use the User Model object to override the way hashPasswords() is handled. In other words, if there is a hashPasswords() method in the $this->User object, it will be used instead of the default hashPasswords() method in the Auth controller. As you see, this override only applies during the ‘add’ action.

Why bother?

Well, you might have noticed that by default Auth will hash the password before the validation. This creates a few problems. First of all you can’t apply ‘minLength’ and ‘notEmpty’ rules correctly, since validation method will get the hashed value (which is always long and not empty) rather than the actual value the user typed-in. Secondly, if there are errors in the form, a hashed value will be populated back in the password field.

By making a simple override in the User Model, the little problems and hacks can be avoided:

function hashPasswords($data, $enforce=false) {
   if($enforce && isset($this->data[$this->alias]['password'])) {
              if(!empty($this->data[$this->alias]['password'])) {
                  $this->data[$this->alias]['password'] = Security::hash($this->data[$this->alias]['password'], null, true);
                }
            }

        return $data;
    }

    function beforeSave() {
         $this->hashPasswords(null, true);

         return true;
    }

The benefits are simple, but worthwhile:

  • When building the view I don’t need to be concerned about how the form field name is going to affect my model or controller
  • I can use the field ‘password’ (no need to use some other field name, such as ‘passwd’) to apply my validation rules, as I normally would
  • I do not believe in clearing out the ‘password’ field in case of a form error. There is no need to punish the user, who’ve made a mistake in the ’email’ field by also making him/her re-type the ‘password’
  • You don’t need any additional code in the controller to re-assign/unset virtual ‘password’ fields

To explain the above code, hashPasswords() will not perform the hashing unless the $enforce flag is true, which i will set manually to true in beforeSave().

Hopefully this clarifies some things and gives you some more ideas for the further tweaking of Auth…

%d bloggers like this: