How to implement password reset in Laravel

Updated: January 18, 2024 By: Guest Contributor Post a comment

Introduction

Laravel is a powerful PHP framework that streamlines common tasks in web development like authentication, routing, sessions, and caching, making it easier to build web applications. An essential feature of most web applications is the ability for users to reset their passwords. Laravel provides built-in support to handle password reset mechanisms, but custom implementation can be a bit intricate.

The modern user expects a simple and secure way to reset their password if they forget it. This tutorial will guide you through the steps to set up a password reset in Laravel and how to customize it to match your application’s needs. This guide assumes that you have a basic understanding of Laravel and its components such as models, views, controllers, and middlewares. Before diving into the details, ensure that you have a fresh Laravel project setup and ready to go.

Setting up User Authentication

Before we can implement password resets, we need to set up user authentication in our Laravel application if it’s not already in place. Laravel makes this simple with the built-in Laravel Breeze starter kit or Laravel Jetstream:

composer require laravel/breeze --dev
php artisan breeze:install
npm install
npm run dev
php artisan migrate

Once you have authentication set up, users will be able to register and log in to your application.

Understanding Laravel’s Password Reset Functionality

Laravel uses the ‘Illuminate\Auth\Passwords\PasswordBroker’ class to manage password resets. This class has methods to create, manage and reset password tokens which are part of the password reset process. It also interfaces with the ‘Password Reset’ controller which powers your ‘/password/reset’ endpoint.

Inside the ‘config/auth.php’ file, you will find configurations related to password resets, such as ‘passwords’ array where you can define the table used for storing password reset tokens and the expiration time of the tokens.

Step 1: Configuring Password Reset Settings

If you have used the Artisan command to install your authentication system, Laravel has already created the necessary migration for the password resets table.

Schema::create('password_resets', function (Blueprint $table) {
    $table->string('email')->index();
    $table->string('token');
    $table->timestamp('created_at')->nullable();
});

Next, you need to run the default migration that comes with Laravel to create the table:

php artisan migrate

Step 2: Initiate Password Reset Process

To start the password reset process, you need a form where the user can submit their email address. In your application, create a view called ‘password/email.blade.php’ that contains an email input and a submit button:

<form method="POST" action="{{ route('password.email') }}">
    @csrf
    <!-- Email Address Input -->
    <div>
        <label for="email">Email</label>
        <input id="email" type="email" name="email" required autofocus />
    </div>
    <!-- Submit Button -->
    <button type="submit">Send Password Reset Link</button>
</form>

When the user submits this form, the email will be sent to the PasswordController provided by Laravel:

public function sendResetLinkEmail(Request $request)
{
    $this->validateEmail($request);

    $response = $this->broker()->sendResetLink(
        $request->only('email')
    );

    return $response == Password::RESET_LINK_SENT
                ? back()->with('status', __($response))
                : back()->withErrors(['email' => __($response)]);
}

Step 3: Resetting the Password

When your user receives the password reset email, they will be directed to a view where they can choose a new password. You need to create another view called ‘password/reset.blade.php’ that will contain a form for new password and password confirmation inputs:

<form method="POST" action="{{ route('password.update') }}">
    @csrf
    <!-- Token Field -->
    <input type="hidden" name="token" value="{{ $token }}">
    <!-- Email Address Input -->
    <div>
        <label for="email">Email</label>
        <input id="email" type="email" name="email" value="{{ $email ?? old('email') }}" required autofocus />
    </div>
    <!-- Password Input -->
    <div>
        <label for="password">New Password</label>
        <input id="password" type="password" name="password" required />
    </div>
    <!-- Confirm Password Input -->
    <div>
        <label for="password-confirm">Confirm Password</label>
        <input id="password-confirm" type="password" name="password_confirmation" required />
    </div>
    <!-- Submit Button -->
    <button type="submit">Reset Password</button>
</form>

The associated route will usually be handled by the built-in ResetPasswordController:

public function reset(Request $request)
{
    $request->validate($this->rules(), $this->validationErrorMessages());

    $response = $this->broker()->reset(
        $this->credentials($request), function ($user, $password) {
            $this->resetPassword($user, $password);
        }
    );

    return $response == Password::PASSWORD_RESET
                ? $this->sendResetResponse($request, $response)
                : $this->sendResetFailedResponse($request, $response);
}

Step 4: Notifying the User

Laravel allows customizing the email notifications to suit your application branding by setting up a custom notification:

php artisan make:notification ResetPasswordNotification

After creating the notification, you can modify it to include your branding, by editing the ‘toMail’ method:

public function toMail($notifiable)
{
    return (new MailMessage)
        ->subject('Your Password Reset Link')
        ->line('You are receiving this email because we received a password reset request for your account.')
        ->action('Reset Password', url(config('app.url').route('password.reset', $this->token, false)))
        ->line('If you did not request a password reset, no further action is required.');
}

In your User model, ensure to include the ‘Notifiable’ trait to use the notification system, and don’t forget to update the ‘sendPasswordResetNotification’ method:

use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use Notifiable;

    public function sendPasswordResetNotification($token)
    {
        $this->notify(new ResetPasswordNotification($token));
    }
}

Conclusion

Password resetting function is a critical part of user management in any application. Laravel makes this task relatively straightforward, providing the necessary classes, methods, and views that you can adjust according to your needs. Through the steps outlined above, you now have a basic password reset flow implemented into your Laravel application. However, keep in mind that security practices are continually evolving, and you should update your code as best practices become established.