I've searched through many posts on stackoverflow for an answer, and prehaps I'm just overlooking something, but I can't seem to get $this->Auth->login() to work. I've tried many different suggestions from other posts. I will try to be as thorough as possible when describing other methods I've tried.
I do have adding a user working. The MD5 hashing is working correctly. I hashed a password and then checked it using miracle salad md5 http://www.miraclesalad.com/webtools/md5.php
I do not use a salt for hashing. I use MD5 without a salt.
The database I'm using is Postgresql 9.0. I know some of the CakePhp magic doesn't work for all databases (or so I've been told).
Configure::write('Security.level', 'medium');
/**
* A random string used in security hashing methods.
*/
Configure::write('Security.salt', '');
I was using Auth->fields to map password to user_password and username to user_name in the DB. user_password and user_name are the columns in the core_users table. I also had in the beforeFilter() method.
$this->Auth->fields = array('username' => 'user_name', 'password' => 'user_password');
class AppController extends Controller {
public $components = array(
'Session',
'Auth' => array(
'loginRedirect' => array('controller' => 'pages', 'action' => 'index'),
'logoutRedirect' => array('controller' => 'pages', 'action' => 'display', 'home'),
'loginAction' => array('admin' => false, 'controller' => 'CoreUsers', 'action' => 'login'),
/*'fields' => array('password' => 'user_password', 'username' => 'user_name'),*/
'userModel' => 'CoreUser'
)
);
public function beforeFilter() {
Security::setHash('md5');
$this->Auth->allow('login');
//debug($this->Auth);
}
}
I left the debugs in so you can see the order that they are processed and I will show you how they are printed.
public function login() {
Security::setHash('md5');
//debug($this->Auth);
if ($this->request->is('post')) {
debug(Security::hash($this->Auth->request->data['CoreUser']['user_password']));
debug($this->Auth);
debug(Configure::version());
debug($this->Auth->request->data['CoreUser']['user_password']);
debug($this->Auth->request->data['CoreUser']['user_name']);
if ($this->Auth->login()) {
debug($this->Auth->request->data['CoreUser']['user_password']);
$this->redirect($this->Auth->redirect());
} else {
debug($this->Auth->request->data['CoreUser']['user_password']);
$this->Session->setFlash(__('Invalid username or password, try again'));
}
}
}
public function logout() {
$this->redirect($this->Auth->logout());
}
App::uses('AuthComponent', 'Controller/Component');
class CoreUser extends AppModel{
public $primaryKey = 'user_id';
public $sequence = 'core_user_id_seq';
public $name = 'CoreUser';
public $validate = array(
'user_name' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'User name is required'
)
),
'user_password' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'Password is required'
)
),
'privilege_id' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'Privilege ID is required'
),
'legalValues' => array(
'rule' => array('between',1,4),
'message' => 'Privilege must be between 1 and 4'
)
),
'user_initial' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'User initials is required'
)
),
'email' => array(
'rule' => array('email',true),
'message' => 'Email must have an \'@\' symbol and a domain e.g. .com'
)
);
public function beforeSave() {
Security::setHash('md5');
if (isset($this->data[$this->alias]['user_password'])) {
$this->data[$this->alias]['user_password'] = AuthComponent::password($this->data[$this->alias]['user_password']);
}
return true;
}
}
<h3>Login</h3>
<div class="users form">
<?php echo $this->Session->flash('auth'); ?>
<?php echo $this->Form->create('CoreUser');?>
<fieldset>
<legend><?php echo __('Please enter your username and password'); ?></legend>
<?php
echo $this->Form->input('user_name');
echo $this->Form->input('user_password');
?>
</fieldset>
<?php echo $this->Form->end(__('Login'));?>
</div>
All of these are from the CoreUsersController and going in order in which they are processed.
'098f6bcd4621d373cade4e832627b4f6'
object(AuthComponent) {
components => array(
(int) 0 => 'Session',
(int) 1 => 'RequestHandler'
)
authenticate => array(
(int) 0 => 'Form'
)
authorize => false
ajaxLogin => null
flash => array(
'element' => 'default',
'key' => 'auth',
'params' => array()
)
loginAction => array(
'admin' => false,
'controller' => 'CoreUsers',
'action' => 'login'
)
loginRedirect => array(
'controller' => 'pages',
'action' => 'index'
)
logoutRedirect => array(
'controller' => 'pages',
'action' => 'display',
(int) 0 => 'home'
)
authError => 'You are not authorized to access that location.'
allowedActions => array(
(int) 0 => 'login'
)
request => object(CakeRequest) {
params => array(
'plugin' => null,
'controller' => 'CoreUsers',
'action' => 'login',
'named' => array(),
'pass' => array()
)
data => array(
'CoreUser' => array(
'user_name' => 'testy5',
'user_password' => 'test'
)
)
query => array()
url => 'CoreUsers/login'
base => '/cpm_v2_dev'
webroot => '/cpm_v2_dev/'
here => '/cpm_v2_dev/CoreUsers/login'
}
response => object(CakeResponse) {
}
settings => array(
'loginRedirect' => array(
'controller' => 'pages',
'action' => 'index'
),
'logoutRedirect' => array(
'controller' => 'pages',
'action' => 'display',
(int) 0 => 'home'
),
'loginAction' => array(
'admin' => false,
'controller' => 'CoreUsers',
'action' => 'login'
),
'userModel' => 'CoreUser'
)
userModel => 'CoreUser'
}
'2.1.0'
'test'
'testy5'
'test'
Here is a quick list of things that I've read in other stackoverflow post that I've tried. Let me know if you need to me to elaborate.
1) I mapped username and password to the fields in the DB. It's where the comments are for fields. I also tried doing it in the beforeFilter() method. Using:
$this->Auth->fields = array('username' => 'user_name', 'password' => 'user_password');
In the login view the form was created as such:
$this->Form->input('username');
$this->Form->input('password');
2) I tried hashing the password manually before login like so:
$this->Auth->request->data['CoreUser']['password'] = Security::hash($this->Auth->request->data['CoreUser']['password'])
if ($this->Auth->login()) {
$this->redirect($this->Auth->redirect());
}
3) I just tried doing this as recommended by CakePHP 2.0 Auth Login not working
My AuthComponent now looks like this:
public $components = array(
'Session',
'Auth' => array(
'authenticate' => array(
'Form' => array(
'userModel' => 'CoreUser',
'fields' => array(
'username' => 'user_name',
'password' => 'user_password'
)
)
),
'loginRedirect' => array('controller' => 'pages', 'action' => 'index'),
'logoutRedirect' => array('controller' => 'pages', 'action' => 'display', 'home'),
'loginAction' => array('admin' => false, 'controller' => 'CoreUsers', 'action' => 'login')
)
);
I apologize if I didn't elaborate enough, or I made a mistake. I've been working on this for a couple of days and it has really drained me. I appreciate any help I may receive. Thanks!
What I ended up doing to solve this issue was following the tutorial exactly as CakePHP has it. I also upgraded to 2.1.2. I was running 2.1.0.
http://book.cakephp.org/2.0/en/tutorials-and-examples/blog-auth-example/auth.html
Then I slowly added the configurations I needed. For information about the Auth component I referenced:
http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html
Really what my problem was poor troubleshooting. I would make a bunch of changes rather than one at a time. I had my login.ctp view two different ways
$this->Form->input('username');
$this->Form->input('password');
and now it looks like this:
echo $this->Form->input('user_name');
echo $this->Form->Label('Password');
echo $this->Form->password('user_password');
The second version works.
EDIT0: This is very important. Without a call to the AppController parent the login will not work.
class CoreUsersController extends AppController{
public $helpers = array('Html','Form');
public function beforeFilter() {
parent::beforeFilter();
}
The revision for the Auth component works:
public $components = array(
'Session',
'Auth' => array(
'authenticate' => array(
'Form' => array(
'userModel' => 'CoreUser',
'fields' => array(
'username' => 'user_name',
'password' => 'user_password'
)
)
),
'loginRedirect' => array('controller' => 'pages', 'action' => 'index'),
'logoutRedirect' => array('controller' => 'pages', 'action' => 'display', 'home'),
'loginAction' => array('admin' => false, 'controller' => 'CoreUsers', 'action' => 'login')
)
);
My salt is still an empty string:
Configure::write('Security.salt', '');
Setting the md5 hash is only needed in one place. It's not needed in beforeSave() in the model:
public function beforeFilter() {
Security::setHash('md5');
$this->Auth->allow('login','add');
}
beforeSave():
public function beforeSave() {
if (isset($this->data[$this->alias]['user_password'])) {
$this->data[$this->alias]['user_password'] = AuthComponent::password($this->data[$this->alias]['user_password']);
}
return true;
}