So, I'm trying to make an authentication in CakePHP that is using email instead of username, which field I don't even have in my users table in database. first i was trying to google that, and i already have tried these:
Cakephp 2.0 Authentication using email instead of username
Using email instead of username in CakePHP Auth Component
and few others, but nothing seems to work - still i get the "incorrect data" error. below is my code
AppController.php
class AppController extends Controller {
public $components = array(
'Session',
'Auth' => array(
'userModel' => 'User',
'loginRedirect' => array(
'controller' => 'pages',
'action' => 'display'
),
'logoutRedirect' => array(
'controller' => 'pages',
'action' => 'display',
'home'
),
'authenticate' => array(
'Form' => array(
'fields' => array(
'username' => 'email',
'password' => 'password'
),
'passwordHasher' => 'Blowfish'
)
)
)
);
public function beforeFilter(){
$this->Auth->allow('index', 'view');
}
UsersController.php
public function add() {
if ($this->request->is('post')) {
$this->User->create();
$this->request->data['User']['role'] = "user";
if(strcmp($this->request->data['User']['password'], $this->request->data['User']['repeat']) == 0){
if ($this->User->save($this->request->data)) {
$this->Session->setFlash(__('Użytkownik zarejestrowany.'));
return $this->redirect(array('controller' => 'Pages', 'action' => 'display'));
}
else $this->Session->setFlash(__('Wystąpił błąd, spróbuj ponownie.'));
}
else $this->Session->setFlash(__('Wpisane hasła się nie zgadzają'));
}
}
public function login(){
if($this->request->is('post')){
if($this->Auth->login()){
return $this->redirect($this->Auth->redirectUrl());
}
$this->Session->setFlash(__('Nieprawidłowe dane, spróbuj ponownie'.$this->Auth->login()));
}
}
login.ctp
<div class="users form">
<?php echo $this->Session->flash('auth'); ?>
<?php echo $this->Form->create('User'); ?>
<fieldset>
<legend>
<?php echo __('Zaloguj się'); ?>
</legend>
<?php
echo $this->Form->input('email' /*I also tried with username instead of email here*/, array('label' => 'Email'));
echo $this->Form->input('password', array('label' => 'Hasło'));
?>
</fieldset>
<?php echo $this->Form->end(__('Zaloguj')); ?>
</div>
EDIT: Here is User.php
App::uses('AppModel', 'Model');
App::uses('BlowfishPasswordHasher', 'Controller/Component/Auth');
class User extends AppModel {
public $validate = array(
'email' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'Email jest wymagany'
)
),
'password' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'Hasło jest wymagane'
)
),
'repeat' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'Powtórz hasło'
)
),
'identicalFieldValues' => array(
'rule' => 'identicalFieldValues',
'message' => 'Wpisane hasła się nie zgadzają'
)
);
public function identicalFieldValues(){
return $this->data['User']['password'] === $this->data['User']['repeat'];
}
public function beforeSave($options = array()){
if(isset($this->data[$this->alias]['password'])){
$passwordHasher = new BlowfishPasswordHasher();
$this->data[$this->alias]['password'] = $passwordHasher->hash(
$this->data[$this->alias]['password']
);
}
return true;
}
}
2nd EDIT: I read that the problem can be in size of the varchar in sql, so I changed it from 50 to 130, deleted users, made a new one, but still I cannot log in.
3rd EDIT: I made a completly new, clean cake project, without password hashing, but still with login via email and still im getting "incorrect data" -.-
Related
I don't know why am still getting invalid username or password while I have all the codes and my database. Also the user is already registered but cannot login.
AppController.php
class AppController extends Controller{
public $components = array(
/*'DebugKit.Toolbar',*/
'Session',
'Auth' => array(
'loginRedirect' => array('controller' => 'jobs', 'action' => 'index'),
'logoutRedirect' => array(
'controller' => 'users',
'action' => 'login'
)
)
);
}
Model: User.php
App::uses('AppModel', 'Model');
App::uses('SimplePasswordHasher', 'Controller/Component/Auth');
class User extends AppModel {
public $validate = array(
'Username' => array(
'notEmpty' => array(
'rule' => array('notEmpty'),
),
'The username already exists'=>array(
'rule'=>array('isUnique'),
'message'=>'The username already exists!'
),
),
'Password' => array(
'notEmpty' => array(
'rule' => array('notEmpty'),
),
'Match passwords'=>array(
'rule'=>'matchPasswords',
'message'=>'The password does not match'
),
),
'Confirm_Password' => array(
'notEmpty' => array(
'rule' => array('notEmpty'),
),
),
);
function matchPasswords($data){
if ($data['Password'] == $this->data['User']['Confirm_Password']) {
return TRUE;
}
$this->invalidate('Confirm_Password', 'The password does not match');
return FALSE;
}
public function beforeSave($options = array()) {
if (!parent::beforeSave($options)) {
return false;
}
if (isset($this->data[$this->alias]['Password'])) {
$hasher = new SimplePasswordHasher();
$this->data[$this->alias]['Password'] = $hasher->hash($this->data[$this->alias]['Password']);
}
return true;
}
}
Controller: UsersController.php
class UsersController extends AppController {
public $components = array('Session');
var $name = 'Users';
var $helpers = array('Form');
// Placeholder for login_form, required by CakePHP to see the login_form view
function login_form() { }
public function beforeFilter () {
parent::beforeFilter();
$this->Auth->allow('user', 'login');
}
public function login(){
if ($this->request->is('post')) {
if ($this->Auth->login()) {
return $this->redirect($this->Auth->redirectUrl());
}
$this->Session->setFlash(__('Incorrect username or password'));
}
}
public function logout() {
return $this->redirect($this->Auth->logout());
}
public function done() {
$this->set('framework', 'CakePHP');
}
public function user(){
if($this->request->is('post')) {
$this->User->create();
if($this->User->save($this->request->data)) {
$this->Session->setFlash('The information has been sent successfully!');
return $this->redirect(array('action' => 'login'));
$this->redirect('done');
}
}
}
}
View: login.ctp
<h4>LOGIN HERE</h4>
<?php
echo $this->Session->flash('auth');
echo $this->Form->create('User');
echo $this->Form->input('Username');
echo $this->Form->input('Password',array('type' => 'password'));
echo $this->Form->end('Login');
?>
You are not using the default field names CakePHP is expecting. Therefore, you have to include them in your AuthComponent configuration.
Try the following:
class AppController extends Controller
{
public $components = array(
/*'DebugKit.Toolbar',*/
'Session',
'Auth' => array(
'loginRedirect' => array('controller' => 'jobs', 'action' => 'index'),
'logoutRedirect' => array(
'controller' => 'users',
'action' => 'login'
),
'authenticate' => array(
'Form' => array(
'fields' => array(
'username' => 'Username',
'password'=>'Password'
),
),
)
)
);
}
These should match the field names in your users table and in your views.
EDIT
Also, make sure your password field in the database is long enough to store the hashed password. The default algorithm used by CakePHP is SHA1, which produces a 160 bit (40 character) hash. A VARCHAR 255 should be more than enough to store this string.
See:
Configuring Authentication handlers in Cookbook 2.x | Authentication
I'm new to CakePHP I tried to follow the sample authentication and login in CakePHP documentation and I still cannot login.
I saw same issues in others but I tried to work on it like they did but didn't work out for me. I can't login even if I am providing the correct credentials but $this->Auth->login() is returning false.
Here's my code
<?php
//UsersController
public function add() {
if ($this->request->is('post')) {
$this->User->create();
if ($this->User->save($this->request->data)) {
$this->Session->setFlash(__('The user has been saved'));
return $this->redirect(array('action' => 'index'));
}
$this->Session->setFlash(
__('The user could not be saved. Please, try again.')
);
}
}
public function beforeFilter() {
parent::beforeFilter();
// Allow users to register and logout.
$this->Auth->allow('add', 'logout');
parent::beforeFilter();
}
public function login() {
if ($this->request->is('post')) {
debug($this->Auth->login());
if ($this->Auth->login()) {
return $this->redirect($this->Auth->redirect());
}
$this->Session->setFlash(__('Invalid username or password, try again'));
}
}
//User Model
public $validate = array(
'username' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'A username is required'
)
),
'password' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'A password is required'
)
),
'role' => array(
'valid' => array(
'rule' => array('inList', array('admin', 'author')),
'message' => 'Please enter a valid role',
'allowEmpty' => false
)
)
);
public function beforeSave($options = array()) {
if (isset($this->data[$this->alias]['password'])) {
$passwordHasher = new BlowfishPasswordHasher();
$this->data[$this->alias]['password'] = $passwordHasher->hash(
$this->data[$this->alias]['password']
);
}
return true;
}
// Login View
<div class="users form">
<?php echo $this->Session->flash('auth'); ?>
<?php echo $this->Form->create('User'); ?>
<fieldset>
<legend>
<?php echo __('Please enter your username and password'); ?>
</legend>
<?php echo $this->Form->input('username');
echo $this->Form->input('password');
?>
</fieldset>
<?php echo $this->Form->end(__('Login')); ?>
</div>
?>
it seems that you did not declared Auth Component. You can do that by simply refering to my sample code.
public $components = array('Auth' => array('authenticate' => array(
'Form' => array(
'userModel' => **YOUR MODEL**
)
),
'loginAction' => array(
'controller' => **YOUR CONTROLLER**,
'action' => 'login'
),
'loginRedirect' => array(
'controller' => **YOUR CONTROLLER**,
'action' => 'index'
),
'logoutRedirect' => array(
'controller' => **YOUR CONTROLLER**,
'action' => 'login'
)
)
);
You may want to read first the documentation or follow their blog tutorials because that helped me alot when I first started. :)
Cakephp's Documentation
Change this function:
public function beforeFilter() {
parent::beforeFilter();
// Allow users to register and logout.
$this->Auth->allow('add', 'logout', 'login'); //Add login
}
Update your AppController like that
public $components = array(
'Auth' => array(
'authenticate' => array(
'Form' => array(
'passwordHasher' => 'Blowfish'
)
)
)
);
Been trying to figure this out for plenty of hours, but without success.
$this->request->data['Login'] array contains the right username and hash which matches the entry in the database. $this->Auth->login(); is always returning false for some reason.
The Login table has a column called UserID and Password, Password is hashed using MD5 and a salt which is stored in the table Login as well.
I tried adding a beforeSave function in the Login model which hashed the password, but this didn't seem to work either?
/app/Controller/AppController.php
<?php
App::uses('Controller', 'Controller');
class AppController extends Controller {
public $helpers = array('App', 'Html', 'Form', 'Session');
public $components = array(
'Session',
'Auth' => array(
'loginAction' => array('controller' => 'login', 'action' => 'authenticate'),
'loginRedirect' => array('controller' => 'account', 'action' => 'index'),
'logoutRedirect' => array('controller' => 'home', 'action' => 'index'),
'authenticate' => array('Form' => array('userModel' => 'Login', 'fields' => array('username' => 'UserID', 'password' => 'Password'))))
);
// Execute on every page load.
public function beforeFilter(){
$this->Auth->allow('index', 'view');
}
}
/app/Controller/LoginController.php
<?php
class loginController extends AppController{
public $uses = array('Login');
public function index(){
$this->render('/login');
}
public function authenticate(){
if($this->request->is('post')){
$this->request->data['Login']['password'] = $this->hashPassword($this->data['Login']);
if($this->Auth->login()){
return $this->redirect($this->Auth->redirect());
}
$this->Session->setFlash('Invalid username or password.');
return $this->redirect('/login');
}
}
private function hashPassword($login){
// Get the salt of the user.
$salt = $this->Login->find('first', array(
'fields' => array(
'Salt'),
'conditions' => array(
'Login.UserID' => $login['username'])));
return md5(md5($login['password']) . $salt['Login']['Salt']);
}
}
/app/Model/Login.php
<?php
class Login extends AppModel{
public $useTable = 'Login';
public $validate = array(
'username' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'Please fill in all of the fields.'
)
),
'password' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'Please fill in all of the fields.'
)
));
}
/app/View/login.ctp
<?php
echo $this->Session->flash('flash', array('element' => 'fail'));
echo $this->Form->create('Login', array('url' => '/login/authenticate'));
echo $this->Form->input('username', array('label' => false, 'div' => false, 'autocomplete' => 'off'));
echo $this->Form->input('password', array('label' => false, 'div' => false));
echo $this->Form->end('Login');
?>
Per the incredibly detailed example in the CakePHP book:
http://book.cakephp.org/2.0/en/tutorials-and-examples/blog-auth-example/auth.html
You shouldn't be manually hashing your password prior to submitting.
Alright I solved it:
Changed the field names in the login view file to match the column names in the database.
Added a custom PasswordHasher
While making login feature in my application, i found a problem i cannot solve..
I created login() action inside IndexController, and i am trying verify given data. Main problem is that i cannot to connect them with User Model which holds all data needed to login , such a nickname (username) and password. The code is below:
IndexController.php
App::uses('AppController', 'Controller');
App::import('Controller', 'Users');
class IndexController extends AppController{
public $helpers = array('Html','Form', 'Session');
public $uses = array('User', 'Registration');
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow();
}
public function index(){
$menu = $this->menu();
$this->set('menu', $menu);
}
public function login(){
if ($this->request->is('post')) {
$this->Auth->authenticate = array('Form' => array('userModel' => 'User' ));
var_dump($this->Auth->login());
exit();
if ($this->Auth->login($this->request->data)) {
return $this->redirect($this->Auth->redirectUrl());
}else{
$this->Session->setFlash(__('Invalid username or password, try again'));
$this->redirect(array('controller' => 'index', 'action' => 'login'));
}
if ($this->Session->read('Auth.User')) {
$this->Session->setFlash('You are logged in!');
return $this->redirect(array('controller' => 'index', 'action' => 'index'));
}
}
}
User.php
App::uses('AppModel', 'Model');
App::uses('SimplePasswordHasher', 'Controller/Component/Auth');
class User extends AppModel {
public $displayField = 'name';
//public $belongsTo = array('Role');
//public $actsAs = array('Acl' => array('type' => 'requester'));
public $validate = array(
'name' => array(
'maxLength' => array(
'rule' => array('maxLength', 20),
'message' => 'Name field is too long'
)
),
'nickname' => array(
'notEmpty' => array(
'rule' => array('notEmpty'),
'message' => 'Field cannot be empty'
),
'maxLength' => array(
'rule' => array('maxLength', 20),
'message' => 'Nickname field is too long'
),
),
'password' => array(
'notEmpty' => array(
'rule' => array('notEmpty'),
'message' => 'Field cannot be empty',
),
),
'role_id' => array(
'numeric' => array(
'rule' => array('numeric')
),
),
'email' => array(
'email' => array(
'rule' => array('email'),
'message' => 'Wrong email address format'
),
'notEmpty' => array(
'rule' => array('notEmpty'),
'message' => 'Field cannot be empty',
),
'maxLength' => array(
'rule' => array('maxLength', 30),
'message' => 'Your custom message here'
),
),
'avatar' => array(
'maxLength' => array(
'rule' => array('maxLength', 50),
),
),
'points' => array(
'numeric' => array(
'rule' => array('numeric'),
),
),
);
public function beforeSave($options = array()) {
if (isset($this->data[$this->alias]['password'])) {
$passwordHasher = new SimplePasswordHasher();
$this->data[$this->alias]['password'] = $passwordHasher->hash(
$this->data[$this->alias]['password']
);
}
return true;
}
}
And UserController.php
App::uses('AppController', 'Controller');
class UsersController extends AppController {
public $helpers = array('Html', 'Form', 'Session', 'Paginator');
public $components = array('Auth', 'Session');
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('');
}
public function index(){
$this->User->recursive = 0;
$this->set('users', $this->paginate());
}
public function view($id = null){
$this->User->id = $id;
if (!$this->User->exists()) {
throw new NotFoundException(__('Invalid user'));
}
$this->set('user', $this->User->read(null, $id));
}
public function edit($id = null){
$this->User->id = $id;
if (!$this->User->exists()) {
throw new NotFoundException(__('Invalid user'));
}
if ($this->request->is('post','put')) {
if ($this->User->save($this->request->data)) {
$this->Session->setFlash(__('The user has been saved'));
return $this->redirect(array('action' => 'index'));
}
$this->Session->setFlash(
__('The user could not be saved. Please, try again.')
);
} else {
$this->request->data = $this->User->read(null, $id);
unset($this->request->data['User']['password']);
}
$roles = $this->User->Role->find('list');
$this->set(compact('roles'));
}
public function add(){
if($this->request->is('post')){
$this->User->create();
if($this->User->save($this->request->data)){
$this->Session->setFlash('User has been registered');
return $this->redirect(array('controller' => 'index', 'action' => 'index'));
}
$this->Session->setFlash('Unable to register now, try again');
}
$roles = $this->User->Role->find('list');
$this->set(compact('roles'));
}
public function delete($id = null) {
$this->request->onlyAllow('post');
$this->User->id = $id;
if (!$this->User->exists()) {
throw new NotFoundException(__('Invalid user'));
}
if ($this->User->delete()) {
$this->Session->setFlash(__('User deleted'));
return $this->redirect(array('action' => 'index'));
}
$this->Session->setFlash(__('User was not deleted'));
return $this->redirect(array('action' => 'index'));
}
public function login() {
}
}
Login.ctp
<div class="users form">
<?php echo $this->Session->flash('auth'); ?>
<?php echo $this->Form->create('User'); ?>
<fieldset>
<legend>
<?php echo __('Please enter your username and password'); ?>
</legend>
<?php echo $this->Form->input('User.nickname');
echo $this->Form->input('User.password');
?>
</fieldset>
<?php echo $this->Form->end(__('Login')); ?>
</div>
And here is a question: is it even possible to make it like that?
EDIT
Forgive me, but i forgot to add that all Auth rules i set in AppController:
AppController.php
App::uses('Controller', 'Controller');
class AppController extends Controller {
public $components = array(
'Session',
'Acl',
'Auth' => array(
'authorize' => array(
'Actions' => array('actionPath' => 'controllers')
),
'authenticate' => array(
'Form' => array('username' => 'nickname'),
'Basic'
),
'loginAction' => array(
'controller' => 'index',
'action' => 'login'
),
'loginRedirect' => array(
'controller' => 'users',
'action' => 'index'
),
'logoutRedirect' => array(
'controller' => 'index',
'action' => 'index',
)
)
);
}
First of all this line is definitly wrong:
echo $this->Form->input('Userpassword');
change it to
echo $this->Form->input('password');
also Cakes Auth by default is looking for field called "username" so you have 2 options
instead of User.nickname use
echo $this->Form->input('username');
(and remember about changing validiation from nickname to username)
Or
To configure different field then username for user auth in $components array:
Pass settings in $components array
public $components = array(
'Auth' => array(
'authenticate' => array(
'Form' => array(
'fields' => array('username' => 'nickname')
)
)
)
);
I highly recommend you to read about Cake's Auth Component so you will avoid mistakes like this.
I have tried just about everything now and I'm still having problems with my Auth Setup. I using Employee as my model with the fields employee_id and password. Blowfish is my passwordhasher and Employees/index in my Controller/action.
I'am trying to echo $this->Auth->login() but its not responding.
Output from $this->request->data
Array ( [Employee] => Array ( [employee_id] => bob [password] => temp ) )
Employee Model
<?php
class Employee extends AppModel {
public function beforeSave($options = array()) {
if (isset($this->data[$this->alias]['password'])) {
$this->data[$this->alias]['password'] = AuthComponent::password($this->data[$this->alias]['password']);
}
return true;
}
public $primaryKey = 'employee_id';
public $hasMany = array(
'CustomerInteraction' => array(
'foreignKey' => 'created_by'
),
'Appointment' => array(
'foreignKey' => 'assigned_to'
),
'Customer' => array(
'className' => 'Customer',
'foreignKey' => false
)
);
public $hasOne = array(
'SalesTarget' => array(
'foreignKey' => 'subject'
)
);
public $virtualFields = array(
'full_name' => 'CONCAT(Employee.first_name, " ", Employee.last_name)'
);
}
?>
AppController
public $components = array(
'Session',
'Auth' => array(
'flashElement' => 'login_error',
'authError' => 'You must be logged in to view this page.',
'loginError' => 'Invalid Username or Password entered, please try again.',
'loginAction' => array(
'controller' => 'Employees',
'action' => 'index',
),
'authenticate' => array(
'all' => array(
'userModel' => 'Employee',
'passwordHasher' => 'Blowfish'
),
'Form' => array(
'userModel' => 'Employee',
'passwordHasher' => 'Blowfish',
'fields' => array(
'username' => 'employee_id',
'password' => 'password',
)
)
)
),
);
public $uses = array(
'ProgramApplication',
'Employee'
);
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->fields = array(
'username' => 'employee_id',
'password' => 'password'
);
EmployeesController
<?php
class EmployeesController extends AppController {
public $uses = array(
'TimeEntry',
'Employee',
'CakeEmail',
'Network/Email' ,
'CraigslistTemplate',
'Inventory'
);
public $helpers = array(
'DateConversion'
);
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('index','checkUsername','passwordStatus','passwordCheck','convertPassword');
}
public function index() {
//Set layout to loginr
$this->layout = 'login';
//if already logged-in, redirect
if($this->Session->check('Auth.User')){
return $this->redirect(
array('controller' => 'Search', 'action' => 'index'));
}
echo "1";
if($this->request->is('post')) {
echo $this->Auth->login();
if($this->passwordCheck($this->request->data['Employee']['employee_id'],$this->request->data['Employee']['password'])) {
}else{
echo "Invalid username/password";
}
}
Index.ctp
<div class="Employees form">
<?php //echo $this->Session->flash('auth'); ?>
<?php echo $this->Form->create('Employee',array('controller' => 'Employees','type' => 'POST')); ?>
<fieldset>
<legend>
<?php echo __('Please enter your username and password'); ?>
</legend>
<?php echo $this->Form->input('employee_id',array('type' => 'Username'));
echo $this->Form->input('password');
?>
</fieldset>
<?php echo $this->Form->end(__('Login')); ?>
</div>
I made the same setup you have and got an error related to blowfish.
Removing blowfish works ('passwordHasher' => 'Blowfish'). I am able to login.
I also used a dummy edit function that updates an user:
public function edit() {
$data = array(
'employee_id' => '111',
'password' => 'test',
);
$res = $this->Employee->save($data);
}
After running this function, I was able to login with 111/test, without blowfish.
Is blowfish a requirement for the project? Can you use normal passwords?