I am trying to create a reset option in my project. If user is doing their first login, it will redirect to reset page.
This is the view part
<div class="form-group{{ ($errors->has('cpassword')) ? 'has error' : '' }}">
<label for="cpassword">Current Password: </label>
<input id="cpassword" name="cpassword" type="text" class="form-control">
#if($errors->has('cpassword'))
{{ $errors->first('cpassword')}}
#endif
</div>
<div class="form-group{{ ($errors->has('password')) ? 'has error' : '' }}">
<label for="password">New Password: </label>
<input id="password" name="password" type="password" class="form-control">
#if($errors->has('password'))
{{ $errors->first('password')}}
#endif
</div>
<div class="form-group{{ ($errors->has('password2')) ? 'has error' : '' }}">
<label for="password2">Confirm Password: </label>
<input id="password2" name="password2" type="password" class="form-control">
#if($errors->has('password2'))
{{ $errors->first('password2')}}
#endif
</div>
{{ Form::token() }}
<div class="form-group">
<input type="submit" value="Submit" class="btn btn-default">
</div>
in reset page we need to enter old password, new password and confirm password..
Controller part is given below
public function postReset(){
$validator =Validator::make(Input::all(), array(
'cpassword' => 'required',
'password' => 'required|min:8',
'password2' => 'required|min:8|same:password'
));
if ($validator->fails())
{
return Redirect::route('resetPassword')->withErrors($validator)->withInput();
}
else
{
if (Auth::attempt(array('username'=>Auth::user()->username, 'password'=>Hash::make(Input::get('cpassword'))))) {
return 'password is resetted';
}
}
}
But if I tried to verify current password and userpasssword, their hash codes doesn't match. Is there any other methods to reset passord. I need the same view part.
Can anyone help??
The Auth::attempt() method needs the plain password you must not generate a hash yourself. Also Laravel's hashes can't be validated just by comparing them because every hash contains a random salt. To compare a password with it's hash you have to use Hash::check(). Also, while Auth::attempt() works Auth::validate() would be the better choice since your user is already logged in:
$credentials = array(
'username' => Auth::user()->username,
'password' => Input::get('cpassword')
);
if(Auth::validate($credentials)){
return 'password is resetted';
}
Laravel has a "forgot" password feature built in which you can use to let people reset passwords if they have forgot them.
You can find that at: http://laravel.com/docs/5.0/authentication
If you want someone to be able to change their password (and they are able to remember the old one), you can do something like this:
if(Input::get('passwordIs')) {
if (!Hash::check(Input::get('passwordIs'), Auth::user()->password))
return Redirect::to('my-account/settings/')->withErrors(Lang::get('account.password-wrong'));
else {
if(Input::get('passwordIsNew') !== Input::get('passwordIs_confirmation'))
return Redirect::to('my-account/settings/')->withErrors(Lang::get('account.passwords-must-match'));
else{
$password = Hash::make(Input::get('passwordIs_confirmation'));
$customer = Auth::user();
$customer->password = $password;
$customer->save();
}
}
}
Related
I am using laravel 6. I am trying to implement forgot password for my laravel project for the first time. I have customize the default design for login, forgot password, reset password pages. I have integrated mailtrap for sending email. I have successfully implemented flow like -
click forgot password link
get page on which user enters email and click to send reset link
gets the email of resetting link and data like email, token , created_at stores in password_reset table
on click of reset link page with token and email url gets open in new tab(open the page of reset password having email, new password, confirm password)
Further when I type new password and confirm password and click on Reset Password, nothing happens.
my reset.blade.php
<form id="sign_in" name="sign_in" method="POST" action="{{ route('password.update') }}" data-parsley-validate >
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<h1>Reset Password</h1>
<div class="col-md-12 col-sm-12 form-group has-feedback">
{{-- <label for="login_id"><span style="color:red;">*</span>Login ID</label> --}}
<input id="email" type="email" class="form-control has-feedback-left #error('email') is-invalid #enderror" placeholder="Email" name="email" value="{{ $email ?? old('email') }}" required autocomplete="email" autofocus/>
<span class="fa fa-envelope form-control-feedback left" aria-hidden="true"></span>
#error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
#enderror
</div>
<div class="col-md-12 col-sm-12 form-group has-feedback">
<input id="password" type="password" class="form-control has-feedback-left #error('password') is-invalid #enderror" placeholder="Password" name="password" required autocomplete="new-password" />
<span class="fa fa-pencil form-control-feedback left" aria-hidden="true"></span>
</div>
<div class="col-md-12 col-sm-12 form-group has-feedback">
<input id="password-confirm" type="password" class="form-control has-feedback-left" placeholder="Confirm Password" name="password_confirmation" required autocomplete="new-password" />
<span class="fa fa-pencil form-control-feedback left" aria-hidden="true"></span>
</div>
<button type="submit" class="btn btn-success">Reset Password</button>
</div>
<div class="clearfix"></div>
</form>
I have default controllers generated for auth like 'ConfirmPasswordController, ForgotPasswordController, ResetPasswordController, VerificationController'
ResetPasswordController
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;
class ResetPasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset requests
| and uses a simple trait to include this behavior. You're free to
| explore this trait and override any methods you wish to tweak.
|
*/
use ResetsPasswords;
/**
* Where to redirect users after resetting their password.
*
* #var string
*/
protected $redirectTo = '/dashboard';
}
I have used default route of auth like Auth::routes();
how the passwords reset in database in users table for email and token generated in password_reset table and how the message gets displayed that 'Password reset successfully? This is not working in my case.userstable not changing with new password and entry not gets removed frompassword_reset` table once the reset done successfully.
where and what changes I have to make to make this work? please guide. thanks in advance.
Password Reset in Laravel
Step 1 — Create a Route and a Controller
Create two routes, a controller, and methods through which the email address that requires a password reset will be submitted via the password reset form. The name of these routes, controllers, and methods is totally up to you.
Route::post('reset_password_without_token', 'AccountsController#validatePasswordRequest');
Route::post('reset_password_with_token', 'AccountsController#resetPassword');
Step 2— Change the action property on the default password reset form
<form method="POST" action="{{ url('/reset_password_without_token') }}">
The default password reset form can be found here:
resources/views/auth/passwords/email.blade.php
Step 3 — Create a token and Send Password Reset Link via email
Then add the validatePasswordRequest method in the AccountsController and use or modify the code below.
//You can add validation login here
$user = DB::table('users')->where('email', '=', $request->email)
->first();
//Check if the user exists
if (count($user) < 1) {
return redirect()->back()->withErrors(['email' => trans('User does not exist')]);
}
//Create Password Reset Token
DB::table('password_resets')->insert([
'email' => $request->email,
'token' => str_random(60),
'created_at' => Carbon::now()
]);
//Get the token just created above
$tokenData = DB::table('password_resets')
->where('email', $request->email)->first();
if ($this->sendResetEmail($request->email, $tokenData->token)) {
return redirect()->back()->with('status', trans('A reset link has been sent to your email address.'));
} else {
return redirect()->back()->withErrors(['error' => trans('A Network Error occurred. Please try again.')]);
}
The sendResetEmail method is a private method that sends an email with the reset link to the user. Here you can use whatever email app you choose to use. Maybe, you have a custom email service for your organization, you can use it here, not relying on the options Laravel has by default.
private function sendResetEmail($email, $token)
{
//Retrieve the user from the database
$user = DB::table('users')->where('email', $email)->select('firstname', 'email')->first();
//Generate, the password reset link. The token generated is embedded in the link
$link = config('base_url') . 'password/reset/' . $token . '?email=' . urlencode($user->email);
try {
//Here send the link with CURL with an external email API
return true;
} catch (\Exception $e) {
return false;
}
}
The link generated and sent to the user when clicked will direct the user to your domain.com/password/reset/token?email=’user#email.com’. You can find the view here: resources/views/auth/passwords/reset.blade.php
Step 4 - Reset the User's password
Add this method to the AccountsController. Go through the comments, they explain each step.
public function resetPassword(Request $request)
{
//Validate input
$validator = Validator::make($request->all(), [
'email' => 'required|email|exists:users,email',
'password' => 'required|confirmed'
'token' => 'required' ]);
//check if payload is valid before moving on
if ($validator->fails()) {
return redirect()->back()->withErrors(['email' => 'Please complete the form']);
}
$password = $request->password;
// Validate the token
$tokenData = DB::table('password_resets')
->where('token', $request->token)->first();
// Redirect the user back to the password reset request form if the token is invalid
if (!$tokenData) return view('auth.passwords.email');
$user = User::where('email', $tokenData->email)->first();
// Redirect the user back if the email is invalid
if (!$user) return redirect()->back()->withErrors(['email' => 'Email not found']);
//Hash and update the new password
$user->password = \Hash::make($password);
$user->update(); //or $user->save();
//login the user immediately they change password successfully
Auth::login($user);
//Delete the token
DB::table('password_resets')->where('email', $user->email)
->delete();
//Send Email Reset Success Email
if ($this->sendSuccessEmail($tokenData->email)) {
return view('index');
} else {
return redirect()->back()->withErrors(['email' => trans('A Network Error occurred. Please try again.')]);
}
}
There you have it. This should be enough to get things working.
I had the same problem, I was able to solve it this way,
first i add a route:
Route::get('password/reset/{token}', [App\Http\Controllers\Auth\ResetPasswordController::class, 'showResetForm'])->name('password.reset');
next i add in reset.blade.php
<input type="hidden" name="token" value="{{$token}}">
that's it, it works for me. Maybe someone will also need it
I am trying to make a edit function for my user's where they can edit their own data, but i want it to depends on what the user will change and if the other field is not changed will be at is. you will see the code below and its not working if only one is changed but if i changed all of them the data will be changed.
Myprofile // my users view
<form class="form-group" method="POST" action="{{ route('updateprofilemany', ['id' => auth()->user()->id]) }}" >
#csrf
//username
<input class="col-md-3 container justify-content-center form-control {{$errors->has('username') ? 'has-error' : ''}}" type="text" name="username" id="username" placeholder="{{ Auth::user()->username }}" Value="{{ Request::old('username') }}" />
//bio
<textarea class="border-info form-control {{$errors->has('bio') ? 'has-error' : ''}}" type="text" name="bio" id="bio" placeholder="{{ Auth::user()->bio }}" Value="{{ Request::old('bio') }}"></textarea> <br />
<button id="btn-login" class="btn btn-md r btn-primary" type="submit" > <i class="fa fa-cog"> </i> Save Changes </button>
</form>
StudentController.php // my users controller
public function updateprofilemany(Request $request, $id)
{
// Validation
$this->validate($request, [
'username' => 'max:15|unique:Students',
'bio' => 'max:50',
]);
if ($request->has('username'))
{
// if there is a new username value
$username = $request->input('username');
} else {
$username = Auth::user()->username;
}
if ($request->has('bio'))
{
// if there is a new username value
$bio = $request->input('bio');
} else {
$bio = Auth::user()->bio;
}
// Find the user and inject the new data if there is then go back to
myprofile
$students = User::find($id);
$students->username = $username;
$students->bio = $bio;
$students->save();
//redirect
return redirect()->route('myprofile');
}
it can read the data but if I add it inside the if else statements it requires the both fields.
I tried passing default data like this
myprofile // users view
<form class="form-group" method="POST" action="{{ route('updateprofilemany', ['id' => auth()->user()->id, 'username' => auth()->user()->username, 'bio' => auth()->user()->bio]) }}" >
#csrf
//username
<input class="col-md-3 container justify-content-center form-control {{$errors->has('username') ? 'has-error' : ''}}" type="text" name="username" id="username" placeholder="{{ Auth::user()->username }}" Value="{{ Request::old('username') }}" />
//bio
<textarea class="border-info form-control {{$errors->has('bio') ? 'has-error' : ''}}" type="text" name="bio" id="bio" placeholder="{{ Auth::user()->bio }}" Value="{{ Request::old('bio') }}"></textarea> <br />
<button id="btn-login" class="btn btn-md r btn-primary" type="submit" > <i class="fa fa-cog"> </i> Save Changes </button>
</form>
Web.php // routes
// calls user update profile many function
Route::post('/updateprofilemany/{id}', [
'uses' => 'StudentController#updateprofilemany',
'as' => 'updateprofilemany',
'name' => 'updateprofilemany'
]);
Student Controller
public function updateprofilemany(Request $request, $id, $username ,$bio)
{
//functions like above
}
and add it the specific function like
public function Functionname(Request $request, $id, $username, $bio)
can you guys help me with this thank you!
When you use Value="{{ Request::old('username') }}" in your username field, it may be empty because it doesn't have any value in the first time you open that page.
And in the controller when you use if ($request->has('username')) , it returns true because the username field is sent but with empty value.
You should check the username field for empty value and then continue ...
for example :
if ($request->filled('username')) {
// do something
}
If you only want to change the data when it is in the request you can just pass a default value to the input function. This will use the value if the key is not present in the request. If the key exists but it is an empty string then you can check with a ternary statement to see if there is a value.
This is probably the most simple way to write it:
public function updateprofilemany(Request $request, $id)
{
$this->validate($request, [
'username' => 'max:15|unique:Students',
'bio' => 'max:50'
]);
// get the user
$student = User::find($id);
// just pass the default value as the old username if the key is not supplied
// and if it is an empty string it will also use the old username
$student->username = $request->input('username', $student->username)
?: $student->username;
// also pass the default here as the old bio
$student->bio = $request->input('bio', $student->bio)
?: $student->bio;
$student->save();
}
I am working on laravel 5 eCommerce web portal.
I am having an issue when the user updates the password using the ready made scripts.
The issue is that I can send the link to the customer perfectly without any issue and the customer can change his password also. But when logged out and re-logging in, I get the error as Invalid credentials.
In my routes.php, I have this:
Route::controllers([
'auth' => 'Auth\AuthController',
'password' => 'Auth\PasswordController',
]);
This is the login page:
<form class="form-horizontal" role="form" method="POST" action="{{ url('/login') }}">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<div class="form-group">
<label class="col-md-4 control-label">E-Mail Address</label>
<div class="col-md-6">
<input type="email" class="form-control" name="email" value="{{ old('email') }}">
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label">Password</label>
<div class="col-md-6">
<input type="password" class="form-control" name="password">
</div>
</div>
<div class="form-group">
<div class="col-md-4"></div>
<div class="col-md-4">
Forgot Password
</div>
</div>
<div class="form-group">
<div class="col-md-6 col-md-offset-4">
<button type="submit" class="btn btn-primary btn-block">Login</button>
</div>
</div>
</form>
I cannot login again after I am logged out once the password has been reset.
EDIT 1:
When the login button is clicked on the login form page, the postLogin method is called. Here's the code
public function postLogin( Request $request ) {
$this->validate( $request, [
'email' => ['required', 'exists:users,email,role,customer'],
'password' => 'required'
]);
$credentials = $request->only('email', 'password');
if ( \Auth::attempt($credentials) ) {
\Session::flash('logged_in', 'You have successfully logged in.');
return redirect('/');
}
return redirect('/login')->withInput($request->all())->withErrors(['email' => 'Invalid Email Address Or Password']);
}
EDIT 2:
I just realize that login is not checking for the hash and hence returning false, on doing dd(\Hash::check($request->password, $user->password)), after updating the password and re-logging in. What could be the issue with this ?
Where have I made mistake ? Kindly guide me.
Thanks in advance.
P.S.: I am using the defaults only to update the password, rest all, I have made the controllers and models which are all working fine without any issue.
I stumbled upon this as well and found the answer here, just adding this for future reference..
The reason is that as soon as you add the setPasswordAttribute method on your User model, the password is hashed twice when using the built-in password reset functionality of Laravel. As explained on the Laracast page, all it needs is a check for an already hashed password, eg:
// Add Hash facade
use Illuminate\Support\Facades\Hash;
class User extends Authenticatable
{
// ...
/**
* Automatically hash password
*
* #param String $value The password, maybe hashed already
*
* #return string|null
*/
public function setPasswordAttribute($value)
{
if ($value) {
$this->attributes['password'] = Hash::needsRehash($value) ? Hash::make($value) : $value;
}
}
}
If the new password does not work after changing then something goes wrong when changing the password.
Most likely suspect is the encryption. It can be possible that you are not using the Hash::make($password) and saving it in plaintext format.
You can doublecheck if the hash is saved correctly to DB with function Hash::check($password, $hash);
During the login you can check the password as
public function postLogin( Request $request ) {
$user=User::where('email', $request->email);
Log::debug("Testing $request->password $user->password ". Hash::check($request->password, $user->password));
}
If the Hash::check is false then something went wrong when saving new password. $user->password must be in hashed form.
I'm doing PHP Laravel authentication. Registration and email activation seem works well. But when comes to login, it always return false. I have no idea about this. My email, password and active columns seems correct in my database.
User Modal
class User extends Eloquent implements UserInterface, RemindableInterface {
protected $fillable = array('email', 'username', 'password', 'password_temp', 'code', 'active');
use UserTrait, RemindableTrait;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('password', 'remember_token');
}
Login.php
<form action="{{ URL::route('login-post')}}" method="post">
<!--/ sign in title-->
<!--text field-->
<div class="form-group">
<input type="email" name="email" placeholder="Email" class="form-control rounded input-lg text-center no-border" {{ (Input::old('email') ? ' value="'.Input::old('email') . '"' : '') }}>
#if($errors->has('email'))
{{ $errors->first('email') }}
#endif
</div>
<div class="form-group">
<input type="password" name="password" placeholder="Password" class="form-control rounded input-lg text-center no-border" {{ (Input::old('password') ? ' value="'.Input::old('password') . '"' : '') }}>
#if($errors->has('password'))
{{ $errors->first('password') }}
#endif
</div>
<!--/ text field-->
<div class="text-center m-t m-b">
<input type="checkbox" name="remember" id="remember">
<label for="remember">
Remember Me
</label>
</div>
<input type="submit" value="Sign in" class="btn btn-lg btn-warning lt b-white b-2x btn-block btn-rounded"></input>
{{ Form::token() }}
</form>
Controller
public function postSignIn() {
$validator = Validator::make(Input::all(),
array(
'email' => 'required|email',
'password' => 'required'
)
);
if ($validator->fails()) {
return Redirect::route('login')
->withErrors($validator)
->withInput();
}else {
$remember = (Input::has('remember')) ? true : false;
//Attempt user sign-in
$auth = Auth::attempt(array(
'email' => Input::get('email'),
'password' => Input::get('password'),
'active' => 1
), $remember);
if ($auth) {
//Redirect to the intended page
return Redirect::intended('home');
}else {
return Redirect::route('login')
->with('global','Email/Password is wrong or account is not activated.'.Hash::make(Input::get('password')));
}
}
return Redirect::route('login')
->with('global','There was a problem signing you in.');
}
Problem
It returns incorrect password always.
Solution
Password length must be at least 60 in database for Laravel.
I think there are two reasons (one or maybe two in the same time could couse this)
ONE : when you store your passwords you didn't hash them Hash::make()
TWO : you modified your config/app.php [key] value after setting your pass
I have 3 user types :
Admin
Distributor
Internal
I have a problem sign in as user type. ( Internal )
I can sign in when my user type is Admin.
I can sign in when my user type is Distributor.
BUT I can’t sign in when my user type is internal. Wired ????
I look through every single line of my code in my sign-in functions in my AccountController.php.
I didn’t notice any bug there. If you guys notice any bugs there -- please kindly let me know.
That will be a huge help for me.
Here is my Sign-In Functions
GET
public function getSignIn(){
return View::make('account.signin');
}
POST
public function postSignIn() {
$validator = Validator::make( Input::only('username','password'),
array(
'username' =>'required',
'password' =>'required'
)
);
if ($validator->fails()) {
return Redirect::route('account-sign-in-post')
->with('error','Username/Password Wrong or account has not been activated !')
->withErrors($validator);
}
// Remember Me
$remember = (Input::has('remember')) ? true : false ;
$auth = Auth::attempt(array(
'username' => strtolower(Input::get('username')),
'password' => Input::get('password'),
'active' => 1),
$remember);
// Keep track on log-in information of the user.
if(Auth::check()){
$user = Auth::user();
$user->last_logged_in = Input::get('created_at');
$user->logged_in_count = $user->logged_in_count + 1 ;
$user->is_online = '1';
$user->save();
}
if($auth) {
return Redirect::to('/')
->with('success','You have been successfully logged in.')
;
}
else {
return Redirect::route('account-sign-in')
->with('error','Username/Password Wrong or account has not been activated !')
->withInput(Input::except('password'))
->withErrors($validator);
}
}
VIEW
#extends ('layouts.form')
#section('content')
<style type="text/css">
.signin{
text-align: center;
}
#forgetpassword{
/*color:#5cb85c;*/
color:silver;
}
</style>
<form class="form-horizontal" role="form" action=" {{ URL::route('account-sign-in-post')}}" method="post" >
#if ($errors->has('username')){{ $errors->first('username')}} #endif
<div class="form-group">
<label for=""> Email </label>
<input placeholder="Email" type="text" class="form-control" required name="username" {{ ( Input::old('username')) ? 'value="'.e(Input::old('username')).'"' : '' }}>
</div><br>
#if ($errors->has('password')){{ $errors->first('password')}} #endif
<div class="form-group">
<label for=""> Password </label>
<input placeholder="Password" type="password" class="form-control" required name="password">
</div><br>
<br>
<button type="submit" class="btn btn-success btn-sm btn-block ">Sign In </button>
{{ Form::token() }}
</form><br>
<div class="col-lg-12 text-center">
<a id="forgetpassword" href="{{ URL::route('account-forgot-password') }}"> Forget Password </a> <br>
</div>
#stop
I am sure that I typed in the right username and password because I double check with my database.
It keep redirecting me back to my sign-in page.
with('error','Username/Password Wrong or account has not been activated !')
Can someone please tell me, if I did anything that I’m not suppose to ?
In your situation, you should check your auth variable in your Sign_In Function.
According to your code,
$auth = Auth::attempt(array(
'username' => strtolower(Input::get('username')),
'password' => Input::get('password'),
'active' => 1),
$remember);
Keep in mind that, these are things need to make sure
username must match the database
password must match the database
user active must be 1
If any of these fail, therefore, it STOP you from signing in.
Since, you're so sure about username and password, what about user active ?
Did you check to if it's 1 ?
If Not
on your set-password function or anywhere, where you normally set your user active.
just do this :
$user->active = '1';
$user->save();
Let me know if this work!!