In this article, we will see how to two-factor authentication using email in laravel 10. Here, we will learn about laravel 10 two-factor authentication using email. Here, we will send the OTP code to the email in laravel 10. You can two-factor verification using email in laravel 10. Also, we will use google SMTP for sending emails.
So, let's see laravel 10 two-factor authentications using email, laravel 10 two-factor authentication with email, email OTP verification in laravel 10, how to send verification code to email in laravel 10, and how to send OTP email using laravel 10.
In this step, we will install the laravel 10 application using the following command.
composer create-project laravel/laravel laravel_10_two_factor_auth_example
Also, we will configure the .env file.
MAIL_DRIVER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
[email protected]
MAIL_PASSWORD=your_password
MAIL_ENCRYPTION=tls
[email protected]
MAIL_FROM_NAME="${APP_NAME}"
In this step, we will create a migration using the following command.
php artisan make:migration create_user_email_codes
Migrations:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUserEmailCodes extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('user_email_codes', function (Blueprint $table) {
$table->id();
$table->integer('user_id');
$table->string('code');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('user_email_codes');
}
}
After that, we will migrate the table into the database using the following command.
php artisan migrate
Now, we will update the User model and create a new UserEmailCode model.
app/Models/User.php
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Exception;
use Mail;
use App\Mail\SendEmailCode;
use App\Models\UserEmailCode;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var string[]
*/
protected $fillable = [
'name',
'email',
'password'
];
/**
* The attributes that should be hidden for serialization.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
/**
* Write code on Method
*
* @return response()
*/
public function generateCode()
{
$code = rand(1000, 9999);
UserEmailCode::updateOrCreate(
[ 'user_id' => auth()->user()->id ],
[ 'code' => $code ]
);
try {
$details = [
'title' => 'Mail Sent from Websolutionstuff',
'code' => $code
];
Mail::to(auth()->user()->email)->send(new SendEmailCode($details));
} catch (Exception $e) {
info("Error: ". $e->getMessage());
}
}
}
app/Models/UserEmailCode.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class UserEmailCode extends Model
{
use HasFactory;
public $table = "user_email_codes";
protected $fillable = [
'user_id',
'code',
];
}
Then we will create a laravel auth scaffold using the laravel composer command.
composer require laravel/ui
After that, we will install bootstrap auth using the following command.
php artisan ui bootstrap --auth
Now, we will create middleware for verifying. So, run the following command and create middleware.
php artisan make:middleware Check2FA
app/Http/Middleware/Check2FA.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Session;
class Check2FA
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
if (!Session::has('user_2fa')) {
return redirect()->route('2fa.index');
}
return $next($request);
}
}
app/Http/Kernel.php
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
...
...
...
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'2fa' => \App\Http\Middleware\Check2FA::class,
];
}
Now, we will add routes in the web.php file. So, add the following code to that file.
routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\HomeController;
use App\Http\Controllers\TwoFAController;
/*
|--------------------------------------------------------------------------
| 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!
|
*/
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/home', [HomeController::class, 'index'])->name('home')->middleware('2fa');
Route::controller(TwoFAController::class)->group(function(){
Route::get('two-factor-authentication', 'index')->name('2fa.index');
Route::post('two-factor-authentication/store', 'store')->name('2fa.store');
Route::get('two-factor-authentication/resend', 'resend')->name('2fa.resend');
});
Then we will update LoginController and create a new TwoFAController using the following command.
php artisan make:controller TwoFAController
app/Http/Controllers/Auth/LoginController.php
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Auth;
use App\Models\UserEmailCode;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* @var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest')->except('logout');
}
/**
* Write code on Method
*
* @return response()
*/
public function login(Request $request)
{
$request->validate([
'email' => 'required',
'password' => 'required',
]);
$credentials = $request->only('email', 'password');
if (Auth::attempt($credentials)) {
auth()->user()->generateCode();
return redirect()->route('2fa.index');
}
return redirect("login")->withSuccess('Oppes! You have entered invalid credentials);
}
}
app/Http/Controllers/TwoFAController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Session;
use App\Models\UserEmailCode;
class TwoFAController extends Controller
{
/**
* Write code on Method
*
* @return response()
*/
public function index()
{
return view('2fa');
}
/**
* Write code on Method
*
* @return response()
*/
public function store(Request $request)
{
$request->validate([
'code'=>'required',
]);
$find = UserEmailCode::where('user_id', auth()->user()->id)
->where('code', $request->code)
->where('updated_at', '>=', now()->subMinutes(1))
->first();
if (!is_null($find)) {
Session::put('user_2fa', auth()->user()->id);
return redirect()->route('home');
}
return back()->with('error', 'You entered wrong code.');
}
/**
* Write code on Method
*
* @return response()
*/
public function resend()
{
auth()->user()->generateCode();
return back()->with('success', 'We re-sent code to on your email.');
}
}
Now, we will create a mail class for sending mail to users. So, run the following command and create a mailable class.
php artisan make:mail SendEmailCode
app/Mail/SendEmailCode.php
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class SendEmailCode extends Mailable
{
use Queueable, SerializesModels;
public $details;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($details)
{
$this->details = $details;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->subject('Mail from Websolutionstuff')
->view('emails.code');
}
}
Now, we will create a 2fa.blade.php file. So, add the following HTML code to that file.
resources/views/2fa.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">Laravel 9 Two Factor Authentication Using Email - Websolutionstuff</div>
<div class="card-body">
<form method="POST" action="{{ route('2fa.store') }}">
@csrf
<p class="text-center">We sent code to email : {{ substr(auth()->user()->email, 0, 5) . '******' . substr(auth()->user()->email, -2) }}</p>
@if ($message = Session::get('success'))
<div class="row">
<div class="col-md-12">
<div class="alert alert-success alert-block">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong>{{ $message }}</strong>
</div>
</div>
</div>
@endif
@if ($message = Session::get('error'))
<div class="row">
<div class="col-md-12">
<div class="alert alert-danger alert-block">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong>{{ $message }}</strong>
</div>
</div>
</div>
@endif
<div class="form-group row">
<label for="code" class="col-md-4 col-form-label text-md-right">Code</label>
<div class="col-md-6">
<input id="code" type="number" class="form-control @error('code') is-invalid @enderror" name="code" value="{{ old('code') }}" required autocomplete="code" autofocus>
@error('code')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="form-group row mb-0">
<div class="col-md-8 offset-md-4">
<a class="btn btn-link" href="{{ route('2fa.resend') }}">Resend Code?</a>
</div>
</div>
<div class="form-group row mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">
Submit
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
resources/views/emails/code.blade.php
<!DOCTYPE html>
<html>
<head>
<title>Websolutionstuff</title>
</head>
<body>
<h1>{{ $details['title'] }}</h1>
<p>Your code is: {{ $details['code'] }}</p>
<p>Thank you</p>
</body>
</html>
Now, we will run laravel 10 two-factor authentication using email.
php artisan serve
You might also like:
In this article, we will see how two-way data binding in angular 12. When you create a variable or property to data...
May-12-2022
Hello, laravel web developers! This article will show how to add pagination in laravel 11 Livewire. Here, we'll...
Jun-14-2024
In this article, we will see how to auto select a country using IP lookup in jquery. Here, we will learn about auto...
May-15-2023
Today we will see how to download file on the ftp server using php. Many time we have requirment to retrieve file from t...
May-21-2021