DefaultPasswordHasher generating different hash for the same value - php

I have a password stored at database hashed with DefaultPasswordHasher at add action.
I have another action for change the password for the loggedin user, on this form I have a field called current_password that I need compare with the current password value from database.
The issue is that DefaultPasswordHasher is generating a different hash for each time that I'm hashing the value of the form so this will never match with the hash from database.
Follow the validation code of the 'current_password' field:
->add('current_password', 'custom', [
'rule' => function($value, $context){
$user = $this->get($context['data']['id']);
if ($user) {
echo $user->password; // Current password value hashed from database
echo '<br>';
echo $value; //foo
echo '<br>';
echo (new DefaultPasswordHasher)->hash($value); // Here is displaying a different hash each time that I post the form
// Here will never match =[
if ($user->password == (new DefaultPasswordHasher)->hash($value)) {
return true;
}
}
return false;
},
'message' => 'Você não confirmou a sua senha atual corretamente'
])

That is the way bcrypt works. Bcrypt is a stronger password hashing algorithm that will generate different hashes for the same value depending on the current system entropy, but that is able to compare if the original string can be hashed to an already hashed password.
To solve your problem use the check() function instead of the hash() function:
->add('current_password', 'custom', [
'rule' => function($value, $context){
$user = $this->get($context['data']['id']);
if ($user) {
if ((new DefaultPasswordHasher)->check($value, $user->password)) {
return true;
}
}
return false;
},
'message' => 'Você não confirmou a sua senha atual corretamente'

Related

How to match input password and database hash password in laravel 8

How to authenticate a user password from a given request in Laravel? How is the password checked against the password hash stored in the database?
**
This is my Controller
**
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class MainController extends Controller
{
function login1(Request $request){
$username = $request->input('username');
$password = $request->input('password');
$data = DB::table('users')->where(['username'=>$username, 'password'=>$password])->first();
if($data == null){
echo "error";
$notification = array(
'message' => 'User Does not Exists!',
'alert-type' => 'error'
);
return back()->with($notification);
}
else{
$request->session()->put('user',$data);
return redirect('dashboard');
}
}}
In basic terms, what you want to do is:
Query the users table for a user, with the given username.
Check whether their hashed password compares the hash of the provided password.
So, you want to first query the table for a user with the given username. Then after retrieving the user, and verifying that they exist, you can then check if the provided password matches the hashed password on the retrieved model.
public function login(Request $request): Response
{
$user = User::where('username', $request->get('username'));
if (!$user || !Hash::check($request->get('password'), $user->password)) {
return back()->with([
'message' => 'Incorrect username and/or password.',
'alert-type' => 'error'
]);
}
$request->session()->put('user', $user);
return redirect('dashboard');
}
However, there is baked in functionality in Laravel for this, and it's probably simpler to do something like this, depending on your needs:
public function login(Request $request): Response
{
if (!Auth::attempt(['username' => $request->get('username'), 'password' => $request->get('password')]) {
return back()->with([
'message' => 'Incorrect username and/or password.',
'alert-type' => 'error'
]);
}
return redirect('dashboard');
}
https://laravel.com/api/8.x/Illuminate/Support/Facades/Auth.html#method_attempt
like this
$encrypted = Crypt::encrypt('password_name_variable');

How to change password in laravel laravel 5.2

I have three fields
1- password
2- new password
3- password_confirmation this is change password functionality.
I have allow the condition on password that must be 8 characters one upper one lower and one special character
but i cannot change my password its going on my validator fails:
My Controller code:
public function changepassword(Request $request){
$user = Auth::guard()->user();
$request_data = $request->All();
$validator = $this->admin_credential_rules($request_data);
if($validator->fails()) {
return \Illuminate\Support\Facades\Redirect::to('mujucet')
->with("modal_message_danger", "password must be at least 8 characters, one upper and lower case, and a number");
} else {
$current_password = $user->password;
if(md5($request_data['password']) == $current_password) {
$user_id = $user->id;
$obj_user = User::find($user_id);
$obj_user->password = md5($request_data['new_password']);
$obj_user->save();
return \Illuminate\Support\Facades\Redirect::to('mujucet')
->with("modal_message_success", "Password has been changed successfully");
} else {
return \Illuminate\Support\Facades\Redirect::to('mujucet')
->with("modal_message_danger", "wong old password");
}
}
}
public function admin_credential_rules(array $data){
$messages = [
'new_password.required' => "Zdejte nové heslo.",
'password.required' => "Zadejte souÄasné heslo.",
];
$validator = Validator::make($data, [
'password' => 'required|min:8|regex:/^.*(?=.{3,})(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[\d\X])(?=.*[!$#%]).*$/|confirmed',
'new_password' => 'required|min:8|regex:/^.*(?=.{3,})(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[\d\X])(?=.*[!$#%]).*$/|confirmed',
], $messages);
return $validator;
}
i am stuck into this problem i need your help.
Any help will be highly appreciated!
What errors does the validator give you? You can retrieve them with $validator->errors().
Looking at the code I think you'll need to remove the confirmed rule from the password field validator (since you don't need to confirm the old password). Then you'll need to change the new password confirmation field to have the name new_password_confirmation.
Your three fields should be: password, new_password and new_password_confirmation.
The validator should be:
$validator = Validator::make($data, [
'password' => 'required|min:8|regex:/^.*(?=.{3,})(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[\d\X])(?=.*[!$#%]).*$/',
'new_password' => 'required|min:8|regex:/^.*(?=.{3,})(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[\d\X])(?=.*[!$#%]).*$/|confirmed',
], $messages);
Have you overridden the default hasher to use MD5 for passwords? By default Laravel uses bcrypt which is a lot more secure for hashing sensitive data.

Changing yii2 password by checking the current password with the entered password

Am trying to change password in yii2 advanced app but it always fails
I have a model which finds the entered password and checks it against the stored password and if it is true it returns true but if false it should fail.
This is model part
This is what sets a user password
public function setPassword($password)
{
$this->password = Yii::$app->security->generatePasswordHash($password);
}
This is what is used to compare the two passwords
public function findPasswords($attribute, $params){
$user = UserIdentity::find()->where([
'username'=>Yii::$app->user->identity->username
])->one();
$password = $user->password_hash; //returns current password as stored in the dbase
$hash2 = Yii::$app->security->generatePasswordHash($this->oldpass); //generates an encrypted password
if($password!= $hash2)
{
$this->addError($attribute, 'Old password is incorrect');
}
}
This always returns old password is incorrect.
I have also tried
var_dump(Yii::$app->security->generatePasswordHash(5378));
var_dump(Yii::$app->security->generatePasswordHash(5378));
The two above returns two different values why is it that?
What could be wrong??
THIS IS THE FULL USER MODEL AFTER UPDATE
Am now getting an error of Getting unknown property: app\models\UserPass::password_hash
class UserPass extends Model{
public $oldpass;
public $newpass;
public $repeatnewpass;
public function rules(){
return [
[['oldpass','newpass','repeatnewpass'],'required'],
['oldpass','findPasswords'],
['repeatnewpass','compare','compareAttribute'=>'newpass'],
];
}
public function findPasswords($attribute, $params){
$user = UserIdentity::find()->where([
'username'=>Yii::$app->user->identity->username
])->one();
$valid = $this->validatePassword("53785378");
var_dump(validatePassword("53785378"));
die();
$password = $user->password_hash; //returns current password as stored in the dbase
$hash2 = Yii::$app->security->generatePasswordHash($this->oldpass); //generates an encrypted password
if($password!= $hash2)
{
$this->addError($attribute, 'Old password is incorrect');
}
}
public function attributeLabels(){
return [
'oldpass'=>'Old Password',
'newpass'=>'New Password',
'repeatnewpass'=>'Confirm Password',
];
}
public function validatePassword($password) {
return Yii::$app->security->validatePassword($password, $this->password_hash);
}
}
Use the validatePassword method instead of generating password hash from input value and compare hashes. This is a method from User model which extends ActiveRecord:
/**
* Validates password
*
* #param string $password password to validate
* #return boolean if password provided is valid for current user
*/
public function validatePassword($password) {
return Yii::$app->security->validatePassword($password, $this->password_hash);
}
You should use the validatePassword instead of comparing hashes, exactly as #simialbi said, but to answer your question about why does this return different result.
Yii::$app->security->generatePasswordHash(5738);
The process of generating the hash requires generating a random salt which will result in different output everytime, references for documentation
change
$hash2 = Yii::$app->security->generatePasswordHash($this->oldpass);
if($password!= $hash2)
{
$this->addError($attribute, 'Old password is incorrect');
}
to
$validateOldPass = Yii::$app->security->validatePassword($this->oldpass,$password);
if(!$validateOldPass)
{
$this->addError($attribute, 'Old password is incorrect');
}
You need to use validatePassword method instead of generating new hash(as per #simialbi said).
Generated hash cahnge everytime its being generated thus make your comparison between newly hashed oldpass and hashed oldpass fail. (as per #mhyassin said)

CakePHP 3 - Compare passwords

I have two field "password" (This field is in the database) and confirm_password (This field is not in the database)
Well, I need to compare if password == confirm_password.. but I'm not knowing create a custom validation to "confirm_password"... Would need to have this field in the database?
How do I do?
Generally you can access all data in a custom validation rule via the $context argument, where it's stored in the data key, ie $context['data']['confirm_password'], which you could then compare to the current fields value.
$validator->add('password', 'passwordsEqual', [
'rule' => function ($value, $context) {
return
isset($context['data']['confirm_password']) &&
$context['data']['confirm_password'] === $value;
}
]);
That being said, recently a compareWith validation rule was introduced which does exactly that.
https://github.com/cakephp/cakephp/pull/5813
$validator->add('password', [
'compare' => [
'rule' => ['compareWith', 'confirm_password']
]
]);
Now there has a method call sameAs in validator class, for version 3.2 or grater.
$validator -> sameAs('password_match','password','Passwords not equal.');
see API
I know it's late answer but will help to other.
// Your password hash value (get from database )
$hash = '$2y$10$MC84b2abTpj3TgHbpcTh2OYW5sb2j7YHg.Rj/DWiUBKYRJ5./NaRi';
$plain_text = '123456'; // get from form and do not make hash. just use what user entred.
if (password_verify($plain_text, $hash)) {
echo 'Password is valid!';
} else {
echo 'Invalid password.';
}
OR
$hasher = new DefaultPasswordHasher();
$check = $hasher->check($plain_text,$hash); // it will return true/false

How to compare Laravel's hash password using a custom login form?

Can you help me with this? I am building my own login form using Laravel. But I have a problem because I stored my password using Hash method and in my login form I used hash method again to compare. But I found out that the hash value is always changing.
Here's my code in routes:
Route::post('/admin_handle_login', function()
{
$rules = array(
'admin_username' => 'required',
'admin_password' => 'required'
);
$validate_admin_login = Validator::make(Input::all(), $rules);
if($validate_admin_login->fails()) {
$messages = $validate_admin_login->messages();
Session::flash('warning_notification','Error: Incomplete details!');
return Redirect::to('/flaxadmin')
->withErrors($messages)
->withInput(Input::except('admin_password'));
} else {
$d = array(
Input::get('admin_username'), Hash::make(Input::get('admin_password'))
);
$validate_admin = DB::table('administrators')
->select('username')
->where('username', Input::get('admin_username'))
->where('password', Hash::check('password', Input::get('admin_password')))
->count();
fp($d);
fp($validate_admin);
}
});
The result is
Array
(
[0] => admin002
[1] => $2y$10$RTwKHN9W1/unu1ZhYlNjauApJjjoNTBnE6td/AZ5jWgZEdqVav0um
)
0
In my database the password of admin002 is
$2y$10$47sSXLzh/YXN6Rf2fmljYO7lZaxfhXVSUTp5bssR2gYQ6Nw9luUH2
Is my code wrong? Or are there any proper way to do this? I am a begiiner in Laravel..
First, you cannot do it this way. Assuming username is unique, you should do:
$validate_admin = DB::table('administrators')
->select('username')
->where('username', Input::get('admin_username'))
->first();
if ($validate_admin && Hash::check(Input::get('admin_password'), $validate_admin->password)) {
// here you know data is valid
}
However you should think about rather using built-in methods than coding it yourself. You have Auth::attempt or Auth::validate if you want to login/check only user with password so there's really no need to code it yourself.
Here you're checking the string 'password' with the hashed version of the input password.
So try fetching the user by their username and if you've a result you can compare the hashed version of the password, stored in the database, with the input password. Like so:
$user = DB::table('administrators')
->select('username', 'password')
->where('username', Input::get('admin_username');
if($user->count()) {
$user = $user->first();
if(Hash::check(Input::get('admin_password'), $user->password)) {
//User has provided valid credentials :)
}
}
A slight improvement to marcin-nabiałek's answer, you can now use PHP's password_verify to achieve the same
$user = App\User::where('email', $request->email)->first();
if($user && password_verify($request->password, $user->password)) {
// authenticated user,
// do something...
}
This is useful code 100% laravel 6/7/8.
if ($data = AddEmployee::where('name', $request->name)-first()) {
$pass = Hash::check($request->password, $data->password);
if ($pass) {
echo "sucess";
} else {
echo "Password Not Valid";
}
} else {
echo "Username Not Valid" . "<br>";
}

Categories