support@codebucket.net

How to make Custom Forget Password Process in Laravel

How to make Custom Forget Password Process in Laravel

K. M. Shawkat Zamil | February 09, 2023

Hello Developers,

 

Sometimes we want to implement the Custom Forget Password Process using email in Laravel. When we register a user, the email is sent through the system, and when we click the link, the reset password page comes up.

 

 

 

When you press the forget your password then the next page comes.

 

 

 

 

The verification page:

 

 

 

 

After clicking the link, the password reset page occurs:

 

 

 

Let's configure the process.

 

 

Install Laravel Project In Your Environment

 

 

First, you need to go to your development workspace. My workspace is situated in D:/ drive. Open a command prompt and write the below code to install Laravel.

 

 

laravel new example-app

 

 

Database Configuration

 

 

After installing the project, open the project in your code editor. Now we have to configure the database credentials. As I am using the wamp server, I have to start the server and open the localhost/phpmyadmin. In there I will create a database named example-app.

 

 

 

 

After that, add the credentials to the project .env file

 

 

/.env

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=example-app
DB_USERNAME=[USERNAME]
DB_PASSWORD=[PASSWORD]

 

 

In this tutorial, we will use MailTrap. This service is used to test sending emails. Let's configure the mail credentials. Open the .env file and replace the below lines. This enables our application to deliver emails to the MailTrap inbox. 

 

 

MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=[YOUR_USERNAME]
MAIL_PASSWORD=[YOUR_PASSWORD]
MAIL_ENCRYPTION=tls

 

 

Install Bootstrap Scaffolding

 

 

Any Laravel project will include Bootstrap and auth scaffolding. To initiate let's run the below command:

 

 

composer require laravel/ui

 

 

To make the laravel default bootstrap login design run the below command:

 

 

php artisan ui bootstrap --auth

 

 

Lastly, install the npm in the project. To do so, run the two commands one by one.

 

 

npm install 


npm run dev

 

 

Also, run the mix command to get the design:

 

 

npm run watch

 

 

Finally, you can run the php artisan migrate In the command prompt run the below command:

 

 

php artisan migrate

 

 

Sometimes you might get the below error:

 

 

SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 1000 bytes

 

 

 If you  get the error, add the following line in the [project_directory]/app/Providers/AppServiceProvider.php

 

 

/app/Providers/AppServiceProvider.php

use Illuminate\Support\Facades\Schema;

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Schema::defaultStringLength(191);
}

 

 

As your table has already been generated. Now run the php artisan migrate:fresh.

 

Create Controller

 

 

For the authentication part, let's create an Authentication controller, some models,s and views. First, we create the Authentication Controller. Run the below command:

 

 

php artisan make:controller AuthenticateController

 

 

Then we will create the login, registration function, and post methods. Paste the below functions in AuthenticateController.php. In this tutorial, we will use the laravel-toastr. Install it from the link.

 

 

/app/Http/Controllers/AuthenticateController.php

public function login()
{
    return view('auth.login');
}

public function make_login(Request $request)
{
    $request->validate([
        'email' => 'required',
        'password' => 'required',
    ]);

    $credentials = array(
        'email' => $request->input('email'),
        'password' => $request->input('password')
    );

    if (Auth::attempt($credentials)) {
        Toastr::success('Login successful', 'GoodJob!', ["positionClass" => "toast-top-right"]);
        return redirect()->route('dashboard');
    } else {
        Toastr::error('Login Failed', 'Opps!', ["positionClass" => "toast-top-right"]);
        return redirect()->route('authenticate.login');
    }
}

public function register()
{
    return view('auth.register');
}

public function make_register(Request $request)
{
    $request->validate([
        'email' => 'required|unique:users,email',
        'password' => 'required|min:6',
    ]);

    $data = $request->all();
    $check = $this->create($data);

    if ($check == true) {
        Toastr::success('Registration successful! Please check your email for further process', 'GoodJob!', ["positionClass" => "toast-top-right"]);
    } else {
        Toastr::error('Registration Failed', 'Opps!', ["positionClass" => "toast-top-right"]);
    }

    return redirect()->route('authenticate.login');
}


public function create(array $data)
{
    DB::beginTransaction();

    try {
        $temp = User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password'])
        ]);

        DB::commit();
    } catch (\Exception $e) {
        DB::rollback();
        Log::info($e->getMessage());
    }

    return $temp;
}


public function dashboard()
{
    if (Auth::check()) {
        return view('home');
    }
    return redirect()->route('authenticate.login');
}



public function logout(Request $request)
{
    Session::flush();
    Auth::logout();

    return Redirect()->route('authenticate.login');
}


/**
 * Write code on Method
 *
 * @return response()
 */
    
    public function showForgetPasswordForm()
{
    return view('auth.forget_password');
}

/**
 * Write code on Method
 *
 * @return response()
 */
public function submitForgetPasswordForm(Request $request)
{
    $request->validate([
        'email' => 'required|email|exists:users',
    ]);

    $token = Str::random(150);
    //dd($token);

    DB::table('password_resets')->insert([
        'email' => $request->email,
        'token' => $token,
        'created_at' => Carbon::now()
    ]);

    Mail::send('email.forget_password', ['token' => $token], function ($message) use ($request) {
        $message->to($request->email);
        $message->subject('Reset Password');
    });

    Toastr::success('We have e-mailed your password reset link!', 'GoodJob!', ["positionClass" => "toast-top-right"]);
    return back()->with('message', 'We have e-mailed your password reset link!');
}
/**
 * Write code on Method
 *
 * @return response()
 */
public function showResetPasswordForm($token)
{
    return view('auth.forget_password_link', ['token' => $token]);
}

/**
 * Write code on Method
 *
 * @return response()
 */
public function submitResetPasswordForm(Request $request)
{
    //dd($request->all());
    $request->validate([
        'email' => 'required|email|exists:users',
        'password' => 'required|string|min:6|confirmed',
        'password_confirmation' => 'required'
    ]);

    $updatePassword = DB::table('password_resets')
        ->where([
            'email' => $request->email,
            'token' => $request->token
        ])
        ->first();
    //dd($updatePassword);
    if (!$updatePassword) {
        Toastr::error('Token is wrong or Token expired', 'Invalid token!', ["positionClass" => "toast-top-right"]);
        return redirect()->route('authenticate.login');
        return back()->withInput()->with('error', 'Invalid token!');
    }

    $user = User::where('email', $request->email)
        ->update(['password' => Hash::make($request->password)]);

    DB::table('password_resets')->where(['email' => $request->email])->delete();

    Toastr::success('Your password has been changed!', 'GoodJob!', ["positionClass" => "toast-top-right"]);
    return redirect()->route('authenticate.login');
    // return redirect('/login')->with('message', 'Your password has been changed!');
}

 

 

Create Views

 

 

We need a forget_password_link page to get the email. The view code is:

 

 

resources/views/auth/forget_password_link.blade.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Login') }}</div>

                <div class="card-body">
                    <form action="{{ route('reset.password.post') }}" method="POST" class="was-validated">
                        @csrf
                        <input type="hidden" name="token" value="{{ $token }}">
                        <div class="form-group mb-4">
                            <label for="email" class="fs-6 text text-black-50">Email Adress</label>
                            <input type="email" name="email" id="email"
                                class="form-control rounded-1 @error('email') is-invalid @enderror"
                                value="{{ old('email') }}" autofocus required>
                            @error('email')
                                <span class="invalid-feedback" role="alert">
                                    <strong>{{ $message }}</strong>
                                </span>
                            @enderror
                        </div> 
                        <div class="form-group mb-3">
                            <label for="password" class="fs-6 text text-black-50">Password</label>
                            <input type="password" name="password" id="password"
                                class="form-control rounded-1  @error('password') is-invalid @enderror"
                                value="{{ old('password') }}" required aria-autocomplete="list" min="6" autofocus required>
                            @error('password')
                                <span class="invalid-feedback" role="alert">
                                    <strong>{{ $message }}</strong>
                                </span>
                            @enderror
                        </div>
                        <div class="form-group mb-3">
                            <label for="password_confirmation" class="fs-6 text text-black-50">Confirm Password</label>
                            <input type="password" name="password_confirmation" id="password_confirmation"
                                class="form-control rounded-1  @error('password_confirmation') is-invalid @enderror"
                                value="{{ old('password_confirmation') }}" required min="6" autofocus required>
                            @if ($errors->has('password_confirmation'))
                                <span class="invalid-feedback" role="alert">
                                    <strong>{{ $errors->first('password_confirmation') }}</strong>
                                </span>
                            @endif
                        </div>                       
                        <div class="d-grid mb-4">
                            <button type="submit"
                                class="btn btn-primary border-0 rounded-5 p-3 px-3 text-uppercase fs-5 text"> Reset Password</button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

 

 

 

resources/views/auth/forget_password.blade.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Login') }}</div>

                <div class="card-body">
                    <form action="{{ route('forget.password.post') }}" method="POST">
                        @csrf
                        <div class="form-group mb-4">
                            <label for="email" class="fs-6 text text-black-50">Email Adress</label>
                            <input type="email" name="email" id="email"
                                class="form-control rounded-1 @error('email') is-invalid @enderror"
                                value="{{ old('email') }}" autofocus required>
                            @error('email')
                                <span class="invalid-feedback" role="alert">
                                    <strong>{{ $message }}</strong>
                                </span>
                            @enderror
                        </div>                        
                        <div class="d-grid mb-4">
                            <button type="submit"
                                class="btn btn-primary border-0 rounded-5 p-3 px-3 text-uppercase fs-5 text">Send Password Reset Link</button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

 

 

We need to create an email view file. Let's create a folder in the views folder named email. The codes are given below:

 

 

resources/views/email/forget_password.blade.php

<h4>Forget Password Email</h4>
   
You can reset password from bellow link:
<a href="{{ route('reset.password.get', $token) }}">Reset Password</a>

 

 

Also, add the below two lines on the forget_password page to see the Toast message:

 

 

<script src="https://code.jquery.com/jquery-3.6.3.min.js" integrity="sha256-pvPw+upLPUjgMXY0G+8O0xUf+/Im1MZjXxxgOcBQBXU=" crossorigin="anonymous"></script>
<script src="{{ asset('https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js') }}"></script>
{!! Toastr::message() !!}

 

 

Create Routes

 

 

To work with these functions, we need the routes, the routes are given below:

 

/routes/web.php

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\AuthenticateController;
use Illuminate\Foundation\Auth\EmailVerificationRequest;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/


Auth::routes();

Route::get('/', [AuthenticateController::class, 'login'])->name('login');
Route::get('authenticate/login', [AuthenticateController::class, 'login'])->name('authenticate.login');
Route::post('authenticate/make_login', [AuthenticateController::class, 'make_login'])->name('authenticate.make_login');
Route::get('authenticate/register', [AuthenticateController::class, 'register'])->name('authenticate.register');
Route::post('authenticate/make_register', [AuthenticateController::class, 'make_register'])->name('authenticate.make_register');
Route::post('authenticate/logout', [AuthenticateController::class, 'logout'])->name('authenticate.logout');

Route::group(['middleware' => ['auth']], function () {
    Route::get('/dashboard', [AuthenticateController::class, 'dashboard'])->name('dashboard')
});

Route::get('account/verify/{token}', [AuthenticateController::class, 'verifyAccount'])->name('user.verify'); 

Route::get('forget-password', [AuthenticateController::class, 'showForgetPasswordForm'])->name('forget.password.get');
Route::post('forget-password', [AuthenticateController::class, 'submitForgetPasswordForm'])->name('forget.password.post');
Route::get('reset-password/{token}', [AuthenticateController::class, 'showResetPasswordForm'])->name('reset.password.get');
Route::post('reset-password', [AuthenticateController::class, 'submitResetPasswordForm'])->name('reset.password.post');




 

 

Let's run the project by the following command:

 

 

php artisan serve

 

 

When you register, you will get the email, and after clicking the email, you can get access to the dashboard.

 

 

Read More: How to Configure Laravel Custom Email Verification System

 

 

K. M. Shawkat Zamil

K. M. Shawkat Zamil

Senior Software Engineer

I am a Senior Software Engineer in a reputed company in Bangladesh. I am a big fan of Laravel, PHP Programming, MSSQL Server, MySql, JavaScript, and lots more. I love to help people who are especially eager to learn. I believe in patience and motivation.