简体   繁体   中英

laravel reset password not resetting the password

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 -

  1. click forgot password link
  2. get page on which user enters email and click to send reset link
  3. gets the email of resetting link and data like email, token , created_at stores in password_reset table
  4. 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. ? This is not working in my case. users table not changing with new password and entry not gets removed from password_reset` table once the reset done successfully.

where and what changes I have to make to make this work? please guide. thanks in advance.

In my case (Laravel 7.x) i was missing the csrf token and the password reset token so when i put both it work correctly:

<form action="{{ route('password.update') }}" method="post">
  @csrf
    <input type="hidden" name="token" value="{{ $token }}">
    ...

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM