comparing confirmation password against a hashed password | Laravel 4 - php

I am trying to get the confirmation password to work against the password field in my form. I went through the Validator methods and they all seem to work perfectly. However, when trying to confirm the password I get an error message everytime that they must match..scratching my head I can only determine it's because they are being hashed before going through validation. I am not sure how to get past this as they need to be hash before being entered into the database. Any ideas?
getSignUp Controller
public function getSignUp() {
$userdata = array(
'email' => Input::get('email'),
'password' => Hash::make(Input::get('password')),
'confirm_password' => Hash::make(Input::get('confirm_password')),
'user_zip_code' => Input::get('user_zip_code')
);
$rules = array(
'email' => 'required|email|unique:users,email',
'password' => 'required|min:5',
'confirm_password' => 'required|same:password',
'user_zip_code' => 'required'
);
$validation = Validator::make($userdata, $rules);
if($validation->fails()){
return Redirect::to('signup')->withErrors($validation)->withInput();
}
$user = new User($userdata);
$user->save();
return Redirect::to('login');
}
If anymore code is needed let me know. I just simply have the withErrors going to the blade template for the signup page

Don't pass the hashed password to the validator. Hash it before you save it:
public function getSignUp() {
$userdata = array(
'email' => Input::get('email'),
'password' => Input::get('password'),
'confirm_password' => Input::get('confirm_password'),
'user_zip_code' => Input::get('user_zip_code')
);
$rules = ...
$validation = Validator::make($userdata, $rules);
if($validation->fails()){
return Redirect::to('signup')->withErrors($validation)->withInput();
}
$userdata['password'] = Hash::make($userdata['password']);
$user = new User($userdata);
$user->save();
return Redirect::to('login');
}

Related

How to validate current, new, and new password confirmation in Laravel 5?

I have created the password route, view and method in UserController#getProfilePassword and UserController#postProfilePassword
At the moment, if I fill out the new_password field, it gets hashed and submitted to the database correctly, then I can login with the new password.
But I need to be able to validate the new_password and new_password_confirm to make sure they're the same and validate the user's current password as well.
How can I do that?
EDIT: I added $this->validate to the method, but now I keep getting the error The password confirmation confirmation does not match. even though they do match as I am using a simple password. Also I think I need to check against the current password manually as validator won't do it for me.
public function getProfilePassword(Request $request) {
return view('profile/password', ['user' => Auth::user()]);
}
public function postProfilePassword(Request $request) {
$user = Auth::user();
$this->validate($request, [
'old_password' => 'required',
'password' => 'required|min:4',
'password_confirmation' => 'required|confirmed'
]);
$user->password = Hash::make(Input::get('new_password'));
$user->save();
}
And this is the view
<form action="{{ route('profile/updatepassword') }}" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="name">Current Password</label>
<input type="password" name="old_password" class="form-control" id="old_password">
</div>
<div class="form-group">
<label for="name">Password</label>
<input type="password" name="password" class="form-control" id="password">
</div>
<div class="form-group">
<label for="name">New Password</label>
<input type="password" name="password_confirmation" class="form-control" id="password_confirmation">
</div>
<button type="submit" class="btn btn-primary">Change Password</button>
<input type="hidden" value="{{ Session::token() }}" name="_token">
</form>
There's a Hash::check() function which allows you to check whether the old password entered by user is correct or not.
usage
if (Hash::check("param1", "param2")) {
//add logic here
}
param1 - user password that has been entered on the form
param2 - old password hash stored in database
it will return true if old password has been entered correctly and you can add your logic accordingly
for new_password and new_confirm_password to be same, you can add your validation in form request like
'new_password' => 'required',
'new_confirm_password' => 'required|same:new_password'
If you only need the functionality of a custom rule once throughout your application, you may use a Closure instead of a rule object. The Closure receives the attribute's name, the attribute's value, and a $fail callback that should be called if validation fails
$request->validate([
'new_password' => 'required|confirmed|min:4',
'current_password' => ['required', function ($attribute, $value, $fail) use ($user) {
if (!\Hash::check($value, $user->password)) {
return $fail(__('The current password is incorrect.'));
}
}],
]);
https://laravel.com/docs/5.6/validation#using-closures
In Laravel 6 there is a new rule called password ,according to docs
The field under validation must match the authenticated user's password. You may specify an authentication guard using the rule's first parameter:
'password' => 'password:api'
so the validation rules can be as simple as :
'current_password' => 'required|password',
'password' => 'required|string|min:8|confirmed',
You can do this by creating a custom validation rule (for this example I'm using current_password and new_password as the input names).
Put this in AppServiceProvider::boot():
Validator::extend('current_password', function ($attribute, $value, $parameters, $validator) {
$user = User::find($parameters[0]);
return $user && Hash::check($value, $user->password);
});
Now you can use the following in your controller:
$user = auth()->user(); // or pass an actual user here
$this->validate($request, [
'current_password' => 'required_with:new_password|current_password,'.$user->id,
]);
Using laravel 5.8/6.0, here is what i do(without much additional code)
Step 1: Validate
$data = request()->validate([
'firstname' => ['required', 'string', 'max:255'],
'lastname' => ['required', 'string', 'max:255'],
'username' => ['bail', 'nullable', 'string', 'max:255', 'unique:users'],
'email' => ['bail', 'nullable', 'string', 'email:rfc,strict,dns,spoof,filter', 'max:255', 'unique:users'],
'new_password' => ['nullable', 'string', 'min:8'],
'confirm_new_password' => ['nullable', 'required_with:new_password', 'same:new_password'],
'current_password' => ['required', function ($attribute, $value, $fail) {
if (!\Hash::check($value, Auth::user()->password)) {
return $fail(__('The current password is incorrect.'));
}
}]
]);
Step 2: If validation is passed
Create array , checking each input value (but not the ones with the required tag in validation) for presence or null OR do something that you want.
For example:
if(request(input)){
$data += ['input' => request(input)];
}
Update database using the created array
For example:
Auth::user()->account->update($data);
A complete function which will check everything. You just need to send old_password, new_password and confirm_password.
public function changePassword(Request $request) {
try {
$valid = validator($request->only('old_password', 'new_password', 'confirm_password'), [
'old_password' => 'required|string|min:6',
'new_password' => 'required|string|min:6|different:old_password',
'confirm_password' => 'required_with:new_password|same:new_password|string|min:6',
], [
'confirm_password.required_with' => 'Confirm password is required.'
]);
if ($valid->fails()) {
return response()->json([
'errors' => $valid->errors(),
'message' => 'Faild to update password.',
'status' => false
], 200);
}
// Hash::check("param1", "param2")
// param1 - user password that has been entered on the form
// param2 - old password hash stored in database
if (Hash::check($request->get('old_password'), Auth::user()->password)) {
$user = User::find(Auth::user()->id);
$user->password = (new BcryptHasher)->make($request->get('new_password'));
if ($user->save()) {
return response()->json([
'data' => [],
'message' => 'Your password has been updated',
'status' => true
], 200);
}
} else {
return response()->json([
'errors' => [],
'message' => 'Wrong password entered.',
'status' => false
], 200);
}
} catch (Exception $e) {
return response()->json([
'errors' => $e->getMessage(),
'message' => 'Please try again',
'status' => false
], 200);
}
}
Laravel Check Old Password and Updating a New Password | More
public function updatePassword(Request $request)
{
$this->validate($request, [
'old_password' => 'required',
'new_password' => 'required|min:6',
'confirm_password' => 'required|same:new_password',
]);
$data = $request->all();
if(!\Hash::check($data['old_password'], auth()->user()->password)){
return back()->with('error','You have entered wrong password');
}else{
here you will write password update code
}
}
Validation rules for laravel 8.*
Default
'current_password' => 'required|current_password',
'password' => 'required|min:8|confirmed',
Custom
php artisan make:rule MatchOldPassword
//inside MatchOldPassword
public function passes($attribute, $value)
{
return Hash::check($value, auth()->user()->password);
}
'current_password' => ['required', new MatchOldPassword()],
'password' => 'required|min:8|confirmed',
Validation rules for Laravel 8.*
use default available validation rules:
[
'current_password' => ['required', 'string', 'current_password'],
'password' => ['required', 'string', 'min:4', 'confirmed']
]
current_password based on Laravel Document check parameter to be equaled to authenticated user password
confirmed based on Laravel
Document check parameter to equaled with new parameter named:
{parameter}_confirmation
You can add confirmed as it's to confirm old password.
And 'required|confirmed' you change to 'required|same:password' to compare password and password confirmation
'old_password' => 'required|confirmed',
'password' => 'required|min:4',
'password_confirmation' => 'required|same:password'
Good luck!
In Laravel 8.x you can use this method in UserController.php:
public function ChangePasswordStore(Request $request, $user_id)
{
$user = User::findOrFail($user_id);
$request->validate([
'password' => 'required|confirmed|string|min:8',
'current_password' => ['required', function ($attr, $password, $validation) use ($user) {
if (!\Hash::check($password, $user->password)) {
return $validation(__('The current password is incorrect.'));
}
}],
]);
User::where('id', $user_id)->update([
'password' => Hash::make($request->input('password')),
]);
return redirect()->back();
}
In web.php:
Route::post('/user/{user_id}/changepassword', [
App\Http\Controllers\Admin\UserController::class,
'changepasswordStore'
])->name('users.changepassword.store');

Laravel MethodNotAllowedHttpException, but my methods match

I have a registration form that I'm creating using the blade templating like so:
{{ Form::open(array('url'=>'registerUser', 'method'=>'POST', 'class'=>'loginForm SignUp')) }}
In routes.php, I have the following route:
Route::post('registerUser', 'UsersController#doRegister');
But when I submit the form, I get a MethodNotAllowedHttpException. Pretty much every other question I've found online about this was a case of the form having the GET method while the route had POST, but mine match, so I'm pretty confused.
Edit: Here's my full routes file:
Route::get('', 'UsersController#showLogin');
Route::get('login', 'UsersController#showLogin');
Route::post('doLogin', 'UsersController#doLogin');
Route::get('signUp', 'UsersController#showSignUp');
Route::post('authenticateCode', 'UsersController#authenticateCode');
Route::post('requestCode', 'UsersController#requestCode');
Route::get('showRegister', 'UsersController#showRegister');
Route::post('registerUser', 'UsersController#doRegister');
Route::get('dashboard', 'DashboardController#showDashboard');
Here's the controller function:
public function doRegister() {
$rules = array(
'fname' => 'required|alpha|min:2',
'lname' => 'required|alpha|min:2',
'email' => 'required|email|unique:users',
'phone' => 'required|alpha_num|min:7',
'company' => 'required|alpha_spaces|min:2',
'password' => 'required|alpha_num|between:6,12|confirmed', // these password rules need to be improved
'password_confirmation' => 'required|alpha_num|between:6,12'
);
$validator = Validator::make(Input::all(), $rules);
if($validator->passes()) {
$user = User::create(array(
'fname' => Input::get('fname'),
'lname' => Input::get('lname'),
'email' => Input::get('email'),
'password' => Hash::make(Input::get('password')),
'phone' => Input::get('phone'),
'company' => Input::get('company')
));
// Update the invite key that was passed to the register page
// with this new user's ID.
$key = InviteKey::find(Input::get('key'));
$key->user_id = $user->id;
$key->save();
return Redirect::to('login')->with('message', 'Thank you for registering!');
} else {
return Redirect::to('register')
->with('message', 'The following errors occurred')
->withErrors($validator)
->withInput(Input::except('password'));
}
}

Laravel update password passes validation but doesn't update record

Hi I am using Laravel and I am using a couple of packages for user auth and roles which are Zizaco Confide and I want to update the users password firstly they should input there current password a new password and confirm the password and they should match. Now the validation works but the users password isn't updated in the database. My code is below:
public function updatePassword($id) {
$rules = array(
'now_password' => 'required',
'password' => 'min:5|confirmed|different:now_password',
'password_confirmation' => 'required_with:password|min:5'
);
//password update.
$now_password = Input::get('now_password');
$password = Input::get('password');
$passwordconf = Input::get('password_confirmation');
$validator = Validator::make(Input::only('now_password', 'password', 'password_confirmation'), $rules);
if ($validator->fails()) {
return Redirect::back()->withErrors($validator);
}
elseif (Hash::check($now_password, Auth::user()->password)) {
$user = User::find($id);
$user->password = Hash::make($password);
$user->save();
return Redirect::back()->with('success', true)->with('message','User updated.');
} else {
return Redirect::back()->withErrors('Password incorrect');
}
}
Any ideas why the users password is not isn't updated using this block of code
$user = User::find($id);
$user->password = Hash::make($password);
$user->save();
User Model
<?php
use Zizaco\Confide\ConfideUser;
use Zizaco\Confide\ConfideUserInterface;
use Zizaco\Entrust\HasRole;
class User extends Eloquent implements ConfideUserInterface
{
use SoftDeletingTrait;
use ConfideUser;
use HasRole;
protected $softDelete = true;
public function favourites()
{
return $this->hasMany('Favourite');
}
}
To check inputted password:
1.
$now_password = Input::get('now_password');
$user = DB::table('users')->where('name', Auth::user()->name)->first();
if(Hash::check($now_password, $user->password)){
//Your update here
}
2.
$now_password = Input::get('now_password');
if(Hash::check($now_password, Auth::user()->password)){
//Your update here
}
To check if they match and if the new password is different than old.
$rules = array(
'now_password' => 'required|min:8',
'password' => 'required|min:8|confirmed|different:now_password',
'password_confirmation' => 'required|min:8',
);
And edit your form to (or enter your names):
{{ Form::label('now_password', 'Old Password') }}
{{ Form::password('now_password')}}
{{ Form::label('password', 'New Password') }}
{{ Form::password('password')}}
{{ Form::label('password_confirmation', 'Confrim New Password') }}
{{ Form::password('password_confirmation')}}
Update
Ok, so you don't want to edit only passwords.
Edit your rules:
$rules = array(
'now_password' => 'required|min:5',
'password' => 'min:5|confirmed|different:now_password',
'password_confirmation' => 'required_with:password|min:5'
);
I think that current password should be required in every type of change. Other inputs imo shouldn't be required, because you don't know which data user want to edit.
You should also add to your rules something like:
'username' => alpha_num|unique:users,username
etc.. (for more see http://laravel.com/docs/4.2/validation#available-validation-rules)
If Validator pass, you should check which data user want to change (which inputs are not empty).
Something like:
if(!empty(Input::get('firstname'))){
$user->firstname = Input::get('firstname');
}
etc...with every input.
Try it like this:
public function updatePassword($id)
{
$user = User::findOrFail($id);
User::$rules['now_password'] = 'required';
// other rules here
$validator = Validator::make($data = Input::all(), User::rules('update', $id));
if ($validator->fails())
{
return Redirect::back()->withErrors($validator)->withInput();
}
array_forget($data, 'password_confirmation');
array_forget($data, 'now_password');
$data['password'] = Hash::make($data['password']);
$user->update($data);
return Redirect::back()->with('success', true)->with('message','User updated.');
}
remember your password confirmation field name must be "password_confirmation" if you used first way...
if you used another name for password confirm field you can use second way.
$this->validate($request, [
'email' => 'required|unique:user|email|max:255',
'username' => 'required|max:20',
'password' => 'required|min:3|confirmed',
'password_confirmation' => 'required',
'gender' => 'required|in:m,f',
]);
$this->validate($request, [
'email' => 'required|unique:user|email|max:255',
'username' => 'required|max:20',
'password' => 'required|min:3',
'confirm_password' => 'same:password',
'gender' => 'required|in:m,f',
]);
public function change_password_post($id)
{
$rules = array(
'current' => 'required|string|min:8',
'new' => 'required|string|min:8',
'confirm' => 'required|same:new'
);
$validator = Validator::make(Input::only('current', 'new', 'confirm'), $rules);
if($validator->fails())
{
return Redirect::back()
->withErrors($validator);
}
else
{
$users = User::where('id', '=', $id)->first();
if (Hash::check(Input::get('current'), $users->password))
{
if(Input::get('new') == Input::get('confirm'))
{
$users->password =Hash::make(Input::get('new'));
$users->save();
$msg = array('msg' => 'Password changed Successfully');
return Redirect::back()
->withErrors($msg);
}
else
{
$msg = array('msg' => 'New password and Confirm password did not match');
return Redirect::back()
->withErrors($msg);
}
}
else
{
$msg = array('msg' => 'Current password is incorrect');
return Redirect::back()
->withErrors($msg);
}
}
}

Laravel sign in (Auth::attempt) not working

Hi there I have problem with Laravel. I can't sign in. I tried everything what I found online. Maybe somebody have any idea where I made mistake. Create new user and send email work fine. Sign in I don't know work like loop come back to view no errors or any messages. I work with debug mode in laravel but it wasn't show any errors.
<?php
class AccountController extends BaseController {
//Sign in function start
public function getSignIn(){
return View::make('account.signin');
}
public function postSignIn(){
$validator = Validator::make(Input::all(),
array(
'email' => 'required|email',
'username' => 'required'
)
);
if($validator->fails()){
return Redirect::route('account-sign-in')
->withErrors($validator)
->withInput();
}else{
if($auth = Auth::attempt(array(
'email' => Input::get('email'),
'password' => Input::get('password'),
'active' => 1
), true)){
return Redirect::to('/');
}else{
return Redirect::route('account-sign-in')
->with('global', 'Email/password wrong or account not activated');
}
}
return Redirect::route('account-sign-in')
->with('global', 'There was a problem signing you in');
}
//Sign in function end
//Create new account function start
public function getCreate(){
return View::make('account.create');
}
public function postCreate(){
$validator = Validator::make(Input::all(),
array(
'email' => 'required|max:50|email|unique:users',
'username' => 'required|max:20|min:3|unique:users',
'password' => 'required|min:6',
'password_again' => 'required|same:password'
)
);
if($validator->fails()){
return Redirect::route('account-create')
->withErrors($validator)
->withInput();
}else{
$email = Input::get('email');
$username = Input::get('username');
$password = Input::get('password');
//Activation code
$code = str_random(60);
$user = User::create(array(
'email' => $email,
'username' => $username,
'password' => Hash::make($password),
'code' => $code,
'active' => 0
));
if($user){
//Send link function start
Mail::send('emails.auth.active', array(
'link' => URL::route('account-active', $code),
'username' => $username),function($message) use ($user){$message->to($user->email, $user->username)->subject('Activation your account');});
//Send link function end
return Redirect::route('home')
->with('global', 'Your account has been created! We have sent you an email with activation link');
}
}
}
public function getActivate($code){
$user = User::where('code', '=', $code)->where('active', '=', 0);
if($user->count()){
$user = $user->first();
//Update user to active state
$user->active = 1;
$user->code ='';
if($user->save()){
return Redirect::route('home')
->with('global', 'Activated! You can now sign in!');
}
}
return Redirect::route('home')
->with('global', 'We could not activate your account. Please try again later.');
}
//Create new account function end
}
?>
In postSignIn() validator you specify that username is required when from what i can see from your logic and error messages, you need the user to specify an email and a password to login. Instead try:
$validator = Validator::make(Input::all(),
array(
'email' => 'required|email',
'password' => 'required'
)
);
When submitting the login form with email and password, the validator always fails since there is no username input

Laravel 4 Auth::attempt() issue

I'm trying the Laravel's Auth class but the method returns false always. Here's my code:
Controller :
public function postLogin()
{
// Declare the rules for the form validation.
//
$rules = array(
'email' => 'Required|Email',
'password' => 'Required'
);
// Get all the inputs.
//
$email = Input::get('email');
$password = Input::get('password');
// Validate the inputs.
//
$validator = Validator::make(Input::all(), $rules);
// Check if the form validates with success.
//
if ($validator->passes())
{
//echo $password; displays test
// Try to log the user in.
//
if (Auth::attempt(array('email' => $email, 'password' => $password)))
{
// Redirect to the users page.
//
return Redirect::to('account')->with('success', 'You have logged in successfully');
}
else
{
// Redirect to the login page.
//
return Redirect::to('account/login')->with('error', 'Email/password invalid.');
}
}
// Something went wrong.
//
return Redirect::to('account/login')->withErrors($validator->getMessageBag());
}
Seeder.php
public function run()
{
DB::table('users')->delete();
$users = array(
array(
'email' => 'test#test.com',
'password' => Hash::make('test'),
'first_name' => 'John',
'last_name' => 'Doe',
'created_at' => new DateTime,
'updated_at' => new DateTime,
)
);
DB::table('users')->insert( $users );
}
It will be because of framework bug. So try to update it.
composer update
Or
php composer.phar update
In your config/auth.php file
try changing from 'driver' => 'eloquent' to 'driver' => 'database'.

Categories