cakephp3- hashed password doesnt match when compared - php

CakePHP version: 3.3.5
I'm building a simple system using which users can login (using a email and password) and after login they can change their password.
For this, I'm using DefaultPasswordHasher
I had a few users already in my db. Their record were already present. So when I did the login function, it worked. I compared the password the user enters with the hased password already present in the db. The check was successful and user was able to login.
Now after login, I wrote change password function, which updated the user password. New hash string replaced the old password string but when I try to login again, login fails.
I will share my controller here. It's pretty basic.
namespace Api\Controller;
use Cake\Utility\Security;
use Cake\Utility\Hash;
use Cake\Auth\DefaultPasswordHasher;
use Api\Controller\AppController;
class LoginController extends AppController
{
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
}
//Function to reset the password
public function resetPassword()
{
$pass = $this->request->data['pass'];
$hasher = new DefaultPasswordHasher();
$hashedPass = $hasher->hash($pass);
$this->loadModel('Login');
//save it to db
$responseArray = $this->Login->resetPassword($hashedPass);
$this->set(compact('responseArray'));
$this->set('_serialize', ['responseArray']);
}
//Function to login
public function login()
{
if ($this->request->is('post'))
{
//Password submitted via form
$pass = $this->request->data['pass'];
//Hashed password fetched from db via a function call
$actualPassword = 'hashedPasswordString'
//Compare password submitted and hash from db
if($this->checkPassword($pass,$actualPassword))
{
$result = 'password matched';
}
else
{
$result = 'password doesnot match';
}
}
$this->set(compact('result'));
$this->set('_serialize', ['result']);
}
//Function to compare password and hash
public function checkPassword($passedPassword , $actualPassword)
{
if ((new DefaultPasswordHasher)->check($passedPassword, $actualPassword)) {
return true;
} else {
return false;
}
}
}
Can anyone tell me why the passwords don't match. I'm new to CakePHP framework. Thanks in advance!

This is what my reset password workflow looks like. I cannot tell from your post what your entity and table look like.
Anytime posted data is converted into a user entity it will now be hashed
Admin/UsersController.php
public function password($id = null)
{
$user = $this->Users->get($id, [
'fields' => ['id', 'first_name', 'last_name', 'username']
]);
if ($this->request->is('put')) {
if ($this->request->data['password'] == $this->request->data['password2']) {
$this->Users->patchEntity($user, ['password' => $this->request->data['password']]);
$this->Users->save($user);
$this->Flash->success('Password has been updated');
return $this->redirect('/admin/users/password/' . $id);
} else {
$this->Flash->error('Passwords do not match');
}
}
$this->set(compact('user'));
}
Model/Entity/User.php
protected function _setPassword($password)
{
if (strlen($password) > 0) {
return (new DefaultPasswordHasher)->hash($password);
}
}

public function changePassword(){
if ($this->request->is('post')) {
$data = $this->request->data();
$res['success'] = FALSE;
$user = $this->Users->get($this->Auth->user('id'))->toArray();
if ((new DefaultPasswordHasher)->check($data['oldPassword'], $user['password'])) {
if($data['newPassword'] == $data['confPassword']){
$userEntity = $this->Users->get($this->Auth->user('id'));
$userEntity->password = $data['newPassword'];
if($this->Users->save($userEntity)){
$res['success'] = TRUE;
$res['message'] = 'Password Changed Successfully.';
}
}else{
$res['success'] = FALSE;
$res['message'] = 'Confirm password is not same as new password. please enter both password again!!';
}
}else{
$res['success'] = FALSE;
$res['message'] = 'Your old password is wrong!';
}
echo json_encode($res);
exit();
}
}

Related

password_verify() logging in all the time

Using codeigniter hashed my password with BCRYPT, seems that everytime I login I redirect to the success page. So I am figuring password verify is not working, even if I enter the incorrect login it still redirects, does not throw the form_validation errors either.
I used the documentation to set it up along with the guides on SO. Will eventually go to Ion Auth but want to know how to fix this. As I am still learning code igniter mvc.
Model
class user_model extends CI_Model{
public function register($encrypt_pass){
$data = array(
'name'=> $this->input->post('name'),
'email'=> $this->input->post('email'),
'username'=> $this->input->post('username'),
'password'=>password_hash($encrypt_pass,PASSWORD_BCRYPT)
);
return $this->db->insert('customers',$data);
}
public function login($username,$password){
//validate the inputs from form
$this->db->where('username',$username);
$query = $this->db->get('customers'); //customers is the table
$result = $query->row_array();
if(!empty($result) && password_verify($password, $result['password'])){
return $result;
}
else{
return "false";
}
}
}
Controller
public function login()
{
$this->form_validation->set_rules('username','Username','required');
$this->form_validation->set_rules('password','Password','required');
if($this->form_validation->run()=== FALSE){
$this->load->view('templates/header');
$this->load->view('users/login',$data);
$this->load->view('templates/footer');
}
else {
//Getting username
$username = $this->input->post('Username');
//Getting and ecrypting password
$password = $this->input->post('Password');//password hashed
$user_id = $this->user_model->login($result);
//checking for user/pass correct will set session if so
if($user_id){
$this->session->set_flashdata('user_loggedin','You are now logged in');
redirect('posts');
}
// If combo is incorrect will redirect
else{
$this->session->set_flashdata('user_loggedin','Login Failed, Please Try
Again');
redirect('users/login');
}
}
}
}
Here is a simple working login code, there are many ways how to do it, it's just an example.
ON YOUR MODEL
Create a function that will check/get the username's password.
public function _getUserPassword($user_name){
$data = array();
$this->db->select('PASSWORD');
$this->db->from('tbl_user');
$this->db->where('USER_NAME', $user_name);
$query = $this->db->get();
if($query->num_rows() > 0){
foreach($query->result_array() as $field_name => $field_value){
$data = $field_value;
}
return $data;
}
else{
return false;
}
}
I've seen your's just selecting it.
We need to use that _getUserPassword function on we call it verify function
function verify($username, $password){
$data = array();
$userNameExists = $this->_getUserPassword($username);
if(password_verify($password, $userNameExists['PASSWORD'])){
$this->db->select('*');
$this->db->from('tbl_user AS user');
$this->db->where('USER_NAME', $username);
$query = $this->db->get();
if($query->num_rows() > 0){
foreach($query->result_array() as $field_name => $field_value){
$data = $field_value;
}
return $data;
}
else{
return false;
}
}
else{
return false;
}
}
So if the verification is success it will return the data to your controller, Let's use your controller.
Let's assume that you changed the models
ON YOUR CONTROLLER
public function login()
{
$this->form_validation->set_rules('username','Username','required');
$this->form_validation->set_rules('password','Password','required');
if($this->form_validation->run()=== FALSE){
$this->load->view('templates/header');
$this->load->view('users/login',$data);
$this->load->view('templates/footer');
}else {
//Getting username
$username = $this->input->post('Username');
//Getting and ecrypting password
$password = $this->input->post('Password');
$user_id = $this->user_model->verify($username,$password);
//checking for user/pass correct will set session if so
if($user_id){
$this->session->set_userdata('user_loggedin','You are now logged in');
redirect('posts');
}else{
//DO NOT SET USER DATA SESSION HERE UNLESS IT WILL AUTOMATICALLY LOGGED IN.
redirect('users/login');
}
}
}
Hope this helps!
where you are checking that password is matching or not.
try this in your controller.after user check.
if($user>0){
if (password_verify($this->input->post('Password'), $user_id['password'])) {
//success message
}
else{
//error message.password is invalid
}

Login in CodeIgniter with password_verify

I'm trying to achieve to login implementation in CodeIgniter, I'm hashing password while registration like password_hash($this->input->post('password'),PASSWORD_DEFAULT) in my Controller and in the same Controller I'm trying to write a login method which is as followed :
public function loginValidation() {
$this->form_validation->set_rules('email', 'Email', 'trim|required');
$this->form_validation->set_rules('password', 'Password', 'trim|required');
if ($this->form_validation->run()) {
// true
$email = $this->input->post('email');
$password = $this->input->post('password');
// User Model Loaded in constructor
if ($this->user->canLogin($email, $password)) {
$session_data = array('email' => $email );
$this->session->set_userdata($session_data);
redirect('profile/personal','Refresh');
} else {
$this->session->set_flashdata('error', 'Invalid Username or Password');
//redirect('login','Refresh');
}
} else {
// try again to login
//redirect('login','Refresh');
}
}
My user Model function is
public function canLogin($email, $password) {
$this->db->where('email',$email);
$this->db->where('password',$password);
$query = $this->db->get($this->tableName);
if ($query->num_rows() > 0) {
return true;
} else {
return false;
}
}
I know I have to password_verify($string,$hash) at some point but I'm unable to figure out.
How do I validate the password against email and redirect to the desired view i.e. personal/profile and I'm making request via AJAX call.
What you need to do is fetch the record from the DB where only the email matches (assuming it is the Unique key). Then you compare the returned value using password_verify().
This is very rough and untested, but should give you an idea:
public function canLogin($email, $password) {
$this->db->where('email',$email);
// $this->db->where('password',$password);
$query = $this->db->get($this->tableName);
$row = $query->row();
return $row ? password_verify($password, $row->password) : false;
}

How to login in laravel using hash techniques

I stored email & password like this:
public function addNewUser(Request $request)/****Add new User****/
{
$user_email = $request->input('email');
$user_hashed_pass = $request->input('password');
$user_pass = Hash::make($user_hashed_pass);
$addAdmin = new SaveNewUser(['useremail'=> $user_email, 'userpassword'=> $user_pass]);
$addAdmin->save();
echo "User added.";
}
And trying to login like this:
public function userLogin(Request $request)/****Login User****/
{
$user_email_log = $request->input('email');
$user_hashed_pass = $request->input('password');
$user_pass_log = Hash::make($user_hashed_pass);
$user = DB::table('userinfo')->where(['useremail'=>$user_email_log, 'userpassword'=>$user_pass_log ])->get();
if(count($user)>0)
{
echo "Welcome User";
}
else
{
echo "Wrong email/password.";
}
}
But cannot login by correct email and password. I think for login hashing password technique is generating new characters for the password and so its not matching. Can anyone help me out here to how to login. Thank you in advance.
Your right, each time Hash:make() runs it will return a different result as some randomness is added. Use the Hash::check() function to check your plain text password against the hash stored in the database. for example, after recovering your user model using the email only, use the following to test the password.
if(Hash::check($request->input('password'), $user->password))
{
echo "Welcome User";
}
From https://laravel.com/docs/5.6/hashing you can see that they have Hash::check() in "Verifying A Password Against A Hash"
if (Hash::check('plain-text', $hashedPassword)) {
// The passwords match...
}
Or as in your case, it would look like this
$user = DB::table('userinfo')->where('useremail', $request->input('email'))->first();
if ($user === null) {
return 'Wrong email';
}
if (Hash::check($request->input('password'), $user->password)) {
return 'Welcome User';
} else {
return 'Wrong password';
}

Phalcon checkHash returns false (Always)

I'm struggling with a problem. I use the Phalcon framework.
The problem is, the $this->security->checkHash() function always returns false.
What I've checked so far:
Checked the length of the varchar password field (is 255) so the hash should fit perfectly inside the field.
Currently, the code looks like this:
The register function:
public function registerAction()
{
$postData = $this->request->getPost();
/*
* Validation
*/
$validation = new RegistrationValidation();
$validationMessages = $validation->validate($postData);
if (count($validationMessages)) {
// Validation Failed!
foreach ($validationMessages as $message)
$this->flashSession->error( $message);
$this->response->redirect( $_SERVER['HTTP_REFERER'] );
$this->response->send();
} else {
// Check Passwords Match
if($postData['password'] !== $postData['password-repeat']) {
$this->flashSession->error( "Passwords don't match");
$this->response->redirect( $_SERVER['HTTP_REFERER'] );
$this->response->send();
}
}
/**
* Begin registration Process
*/
$user = new Users();
$password = $this->request->getPost('pawword');
$password = $this->security->hash($password);
$user->username = $this->request->getPost('username');
$user->email = $this->request->getPost('email');
$user->register_ip = $_SERVER['REMOTE_ADDR'];
$user->password = $password;
$user->active = 0;
// Store user
$user->save();
$this->view->emailmsg = $this->sendVerificationMail($user->id, $user->email, $user->username);
}
the login function:
public function loginAction()
{
if ($this->request->isPost()) {
$email = $this->request->getPost("email");
$password = $this->request->getPost("password");
var_dump($password);
$user = Users::findFirstByEmail($email);
var_dump($this->security->checkHash( 'edrsvc', '$2y$12$ZERPY2Q3N0hUdG1XSkw5V.DqhYek97IZyrRQwq/UP/X7xO3PiPIpG' ));
var_dump($this->security->checkHash($password, $user->password));
var_dump(password_verify('edrsvc', '$2y$12$ZERPY2Q3N0hUdG1XSkw5V.DqhYek97IZyrRQwq/UP/X7xO3PiPIpG'));
die();
if ($user) {
if ($this->security->checkHash($password, $user->password)) {
var_dump($user);
die();
$this->_registerSession($user);
$this->flash->success(
"Welcome " . $user->name
);
// Forward to the 'invoices' controller if the user is valid
$this->dispatcher->forward(
[
"controller" => "index",
"action" => "index",
]
);
}
} else {
$this->security->hash(rand());
$this->flashSession->error(
'Wrong Email or password Back'
);
}
}
}
You can see those 3 var_dumps, which are actually functioning and not throwing exceptions, but always return false. The password is of course
correct and checked twice.
The workFactor is set to Phalcon's default workFactor.

Codeigniter : Change password for logged in user and for password that uses md5

I want to ask how to change password for logged in user,
I can change the password when I enter password that matches anyone in database.
For just example, user have "admin" password, I just enter the current password,
new password and confirm password.
Current password: admin
New Password: newadmin
Current Password: new admin
And also I don't know how to change the password if the password
uses md5(). I hope you can help me, I am a newbie on Codeigniter.
I search answers but I really don't understand it so I want to comment but
it's required 50 reputation so I post new question.
Here's my code :
Controller
public function update(){
$this->form_validation->set_rules('password', 'Current Password', 'required|alpha_numeric|min_length[6]|max_length[20]');
$this->form_validation->set_rules('newpass', 'New Password', 'required|alpha_numeric|min_length[6]|max_length[20]');
$this->form_validation->set_rules('confpassword', 'Confirm Password', 'required|alpha_numeric|min_length[6]|max_length[20]');
if($this->form_validation->run()){
$cur_password = $this->input->post('password');
$new_password = $this->input->post('newpass');
$conf_password = $this->input->post('confpassword');
$this->load->model('queries');
$userid = '1';
$passwd = $this->queries->getCurrPassword($userid);
if($passwd->password == $cur_password){
if($new_password == $conf_password){
if($this->queries->updatePassword($new_password, $userid)){
echo 'Password updated successfully';
}
else{
echo 'Failed to update password';
}
}
else{
echo 'New password & Confirm password is not matching';
}
}
else{
echo'Sorry! Current password is not matching';
}
}
else{
echo validation_errors();
}
model
public function getCurrPassword($userid){
$query = $this->db->where(['id'=>$userid])
->get('users');
if($query->num_rows() > 0){
return $query->row();
} }
public function updatePassword($new_password, $userid){
$data = array(
'password'=> $new_password
);
return $this->db->where('id', $userid)
->update('users', $data); }
I got a solution for my problem.
For logged in user I just changed the $userid = '1'; into
$userid = $this->session->userdata('account_id');
And for the md5 password
I just add md5 on passwords.Like what #sintakonte did and #zaph is right.
"Only use strong password hashing algorithms like BCrypt, which is used in PHP’s own Password Hashing functions."
Reference : https://www.codeigniter.com/userguide3/general/security.html
Thanks for the help guys!
If it is about an application whose Admin password you don't remember, then please try this solution
Not yet marked but I don't see any other way, been at this for weeks
I'm not going to discuss the md5 subject here, but you should avoid those weak algorithms because they aren't safe. Use password_verify and password_hash for this purpose. (but as i said i'm not a missionary)
you need to organize your code a bit better - because this is a mess ;)
try the following - your controller
public function update()
{
$this->form_validation->set_rules('password', 'Current Password', 'required|alpha_numeric|min_length[6]|max_length[20]');
$this->form_validation->set_rules('newpass', 'New Password', 'required|alpha_numeric|min_length[6]|max_length[20]');
$this->form_validation->set_rules('confpassword', 'Confirm Password', 'required|alpha_numeric|min_length[6]|max_length[20]');
if($this->form_validation->run())
{
$cur_password = $this->input->post('password');
$new_password = $this->input->post('newpass');
$conf_password = $this->input->post('confpassword');
$this->load->model('queries');
$userid = '1';
try
{
$objUser = $this->queries->getUser($userid);
if ($objUser->password != md5($cur_password)) throw new Exception('Sorry! Current password is not matching');
if ($new_password != $conf_password) throw new Exception('New password & Confirm password is not matching');
$this->queries->updatePassword($new_password, $userid);
echo 'Password updated successfully';
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
else
{
echo validation_errors();
}
}
and your model
public function getUser($userid)
{
$query = $this->db->where(id,$userid])->get('users');
if($query->num_rows() == 1)
{
return $query->row();
}
throw new Exception("no user data found");
}
public function updatePassword($new_password, $userid)
{
$data = array
(
'password'=> md5($new_password)
);
if (!$this->db->where('id', $userid)->update('users', $data))
{
throw new Exception('Failed to update password');
}
}
there is no need to name your model function getCurrPassword if it is in fact returning an user object - so i renamed that.

Categories