User Registration with CakePHP 1.2 and Auth Component

With CakePHP 1.2 nearly reaching the RC release, I have started using it as the framework for my own applications.  Once of the new features of 1.2 over 1.1 is the addition of numerous core Components for handling things such as Cookies, Email and Authentication (all of which I rolled myself in 1.1).  Today’s article is going to focus on the Auth Component and a couple of problems it threw up whilst I was trying to create a simple registration page.

Before starting with the code listings for a simple registation action, a little bit of background as to why I’m writing this post. CakePHP 1.2′s Auth Component will automatically hash the value of $this->data['User']['password'] – this is helpful in many ways and allows for a lot of Cake’s auto-magic, however it can cause problems. For example, as the passowrd is automatically being hashed into a 40 character value before any other logic is applied, any validation rules in the Model will be ignored (including NOT_EMPTY like checks). Take this as a hypothetical situation:

  • User goes to /users/register to create a new account
  • User enters their username and password correctly, they then enter an invalid email address
  • Controller fails to validate() the invalid email address supplied so takes the user back to the registration page – Cake helpfully re-populates the form with the values in $this->data array
  • This unfortunatley means the user’s password has been turned into a 40 Character SHA-1 Hash! If the user fails to notice this fact, fixes their email address and clicks submit then that 40 Character SHA-1 Hash is going to get hashed again – now the user has no idea what their password is set to – whoops!

Getting around this problem is pretty straight forward, it just requires a little bit of thought – change the fieldname from password (Which CakePHP 1.2′s Auth Component will automatically hash) to something else, ie: passwrd. Now Cake won’t hash this value, your model’s validation checks can run and everyone is happy – just don’t forget to use AuthComponent::password() to hash this value before storing it.

User Model Class

 array
		(
			'alphanumeric' => array
			(
				'rule' => 'alphaNumeric',
				'message' => 'Only the letters A-z and digits 0-9 are allowed',
			),
			'length' => array
			(
				'rule' => array('between', 4, 20),
				'message' => "Your username must be between 4 and 20 characters long",
			),
		),
		'passwrd' => array
		(
			'rule' => array('minLength', 6),
			'message' => 'Your password must be at least 6 characters long',
 
		),
		'email' => 'email',
	);
}
?>

User Controller Class

Auth->allow('register');
	}
 
	/**
	 * Allows a user to sign up for a new account
	*/
	function register()
	{
		// If the user submitted the form...
		if (!empty($this->data))
		{
			// Turn the supplied password into the correct Hash.
			// and move into the 'password' field so it will get saved.
			$this->data['User']['password'] = $this->Auth->password($this->data['User']['passwrd']);
 
			// Always Sanitize any data from users!
			$this->User->data = Sanitize::clean($this->data);
			if ($this->User->save())
			{
				// Use a private method to send a confirmation
				// email to the new user (code not shown)
				$this->__sendConfirmationEmail();
 
				// Success! Redirect to a thanks page.
				$this->redirect('/users/thanks');
			}
 
			// The plain text password supplied has been hashed into the 'password' field so
			// should now be nulled so it doesn't get render in the HTML if the save() fails
			$this->data['User']['passwrd'] = null;
		}
	}
}

User/Register.ctp View

<h2>Create an Account</h2>
 
 
create('User', array('action' =&gt; 'register'));
echo $form-&gt;input('username', array('between' =&gt; 'Pick a username'));
 
// Force the FormHelper to render a password field, and change the label.
echo $form-&gt;input('passwrd', array('type' =&gt; 'password', 'label' =&gt; 'Password'));
echo $form-&gt;input('email', array('between' =&gt; 'We need to send you a confirmation email to check you are human'));
echo $form-&gt;submit('Create Account');
echo $form-&gt;end();
?&gt;
This entry was posted in CakePHP and tagged , . Bookmark the permalink.

6 Responses to User Registration with CakePHP 1.2 and Auth Component

  1. casey says:

    im so glad someone wrote something about authentication in 1.2. theres not a whole lot using the new components and the old stuff is kinda hackish and not cake-like

    thanks

  2. ben says:

    It’s probably better to unset the passwrd field before you save it anyway, so that way it doesn’t get saved to the model, if you have a field in the db for it, and it doesn’t get printed on form invalidation.

  3. Vikram says:

    Great writeup! However, if $this->data[‘User’][‘passwrd’] = null; before the User is saved, the validation on passwrd will always fail. The ideal location would be after the if ($this->User->save()) { … } block. Resetting is not really necessary prior to the redirect, but is not a bad idea.

  4. dan says:

    where does this go?
    Auth->allow(‘register’);

  5. mzee.richo says:

    Nice stuff . trully cool .

  6. Bryan says:

    Hey all – well I posted this problem to another blog but see that this one is more recent. I am in need of help – I’m struggling with having the authComponent use email instead of username for login. Cake Version 1.2

    This is what I have in app_controller:
    var $components = array(’Auth’);

    function beforeFilter() {
    $this->Auth->fields = array(
    ‘username’ => ‘email’,
    ‘password’ => ‘password’
    );
    }

    This is what I have in login.ctp:
    echo $form->create(’User’, array(’action’ => ‘login’));
    echo $form->input(’email’);
    echo $form->input(’password’);
    echo $form->end(’Login’);

    I have verified that the registration is working – db is storing users perfectly w/ hashed password. Even after changing the fields in the app_controller before filter, I am getting “Login failed. Invalid username or password.” as the auth flash message.

    Any help would be appreciated!

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">