Hello Developers,
Sometimes we want to implement the Custom Laravel Email verification process. For that when we register a user the email sends through the system and when we click the link then the login page comes up. The register page looks like this:
The verification page comes when a user register:
After clicking the link, the login 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 and Mail 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:
If you get the error, add the following line in the /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');
}
Create Migration
Now we need a table name users_verify
table and a new column named is_email_verified
in users table. To create a table we need migration.
Paste the below line in the command:
php artisan make:migration create_users_verify_table
The file looks like the below:
/database/migrations/2023_02_07_113210_create_users_verify_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersVerifyTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users_verify', function (Blueprint $table) {
$table->integer('user_id');
$table->string('token');
$table->timestamps();
});
Schema::table('users', function (Blueprint $table) {
$table->boolean('is_email_verified')->default(0);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('users_verify');
}
}
Run the command to execute the migration.
php artisan migrate
Create Model
Also, we need the UserVerify
Model. To create we need to run the below command:
php artisan make:model UserVerify
The model looks like this:
/app/Models/UserVerify.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class UserVerify extends Model
{
use HasFactory;
public $table = "users_verify";
/**
* Write code on Method
*
* @return response()
*/
protected $fillable = [
'user_id',
'token',
];
/**
* Write code on Method
*
* @return response()
*/
public function user()
{
return $this->belongsTo(User::class);
}
}
Now we will create a function in the AuthenticateController
to verify the token. The function is given below:
public function verifyAccount($token)
{
$verifyUser = UserVerify::where('token', $token)->first();
$message = 'Sorry your email cannot be identified.';
$success = 0;
if (!is_null($verifyUser)) {
$user = $verifyUser->user;
$success = 1;
if (!$user->is_email_verified) {
$verifyUser->user->is_email_verified = 1;
$verifyUser->user->save();
$message = "Your e-mail is verified. You can now login.";
} else {
$message = "Your e-mail is already verified. You can now login.";
}
}
if ($success != 0) {
Toastr::success($message, 'GoodJob!', ["positionClass" => "toast-top-right"]);
}else{
Toastr::error($message, 'Sorry!', ["positionClass" => "toast-top-right"]);
}
return redirect()->route('authenticate.login');
}
After that, we need to change the make_register()
function to send emails after registration.
/app/Http/Controllers/AuthenticateController
public function make_register(Request $request)
{
$request->validate([
'email' => 'required|unique:users,email',
'password' => 'required|min:6',
]);
$data = $request->all();
$check = $this->create($data);
$token = Str::random(85);
UserVerify::create([
'user_id' => $check->id,
'token' => $token
]);
Mail::send('email.verification_email', ['token' => $token], function ($message) use ($request) {
$message->to($request->email);
$message->subject('Email Verification Mail');
});
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');
}
Create Views
We need to create a view file. Let's create a folder in the views folder named email. The codes are given below:
resources/views/email/verification_email.blade.php
<h4>Email Verification Mail</h4>
Please verify your email with bellow link:
<a href="{{ route('user.verify', $token) }}">Verify Email</a>
Also, add the below two lines on the login 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 MIddleware
We need to create middleware to check whether the email is verified or not. Run the below command:
php artisan make:middleware IsVerifyEmail
Paste the code in the middleware.
/app/Http/Middleware/IsVerifyEmail.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Brian2694\Toastr\Facades\Toastr;
use Illuminate\Support\Facades\Auth;
class IsVerifyEmail
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
if (!Auth::user()->is_email_verified) {
auth()->logout();
$error_message = 'You need to confirm your account. We have sent you an activation code, please check your email.';
Toastr::warning($error_message, 'Please Check!', ["positionClass" => "toast-top-right"]);
return redirect()->route('login')
->with('message', $error_message );
}
return $next($request);
}
}
Register it in the kernel.
/app/Http/Kernel.php
protected $routeMiddleware = [
...
'is_verify_email' => \App\Http\Middleware\IsVerifyEmail::class,
];
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')->middleware(['is_verify_email']);
});
Route::get('account/verify/{token}', [AuthenticateController::class, 'verifyAccount'])->name('user.verify');
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 Default Email Verification