How to ensure users verify their email with Laravel

How to make registered users verify their account email before using the Laravel application.

With the baseline Laravel authentication framework Breeze when a user registration or sign-up occurs the user can be free to browse and use the web application without having verified their email.

This can mean that a fake or non-genuine email was used because the user never has to verify that it is their email account.

You can fix this by protecting routes and forcing the user to verify the email they used to register to view or use the routes.

Ensure valid email SMTP

The first step is to ensure you have a valid mail SMTP configuration in your .env file, this is so that the verification emails actually send to the users.

The user model

In App\Models\User implement MustVerifyEmailand use Notifiable, this means that the verify email gets sent to anyone right after they register.

namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable implements MustVerifyEmail
    use Notifiable;

The routes

This first route tells the user they must click the link in their verification email. It also provides a link to re-send this verification email.

Route::get('/email/verify', function () {
    return view('auth.verify-email');

This is also what is shown when a non-verified user attempts to access a route that is protected with verified access only.

Laravel verify email routeThe next route handles the verification process when the link is clicked in the email. Take note that you can change where the now verified user gets redirected to.

use Illuminate\Foundation\Auth\EmailVerificationRequest;
Route::get('/email/verify/{id}/{hash}', function (EmailVerificationRequest $request) {
    return redirect('/home');
})->middleware(['auth', 'signed'])->name('verification.verify');

Now the last route is the handling of the verification link email being re-sent.

use Illuminate\Http\Request;
Route::post('/email/verification-notification', function (Request $request) {
    return back()->with('message', 'Verification link sent!');
})->middleware(['auth', 'throttle:6,1'])->name('verification.send');

Protecting routes with the middleware

This last part ensures to protect the routes you only want available to verified users. Generally, this would be everything that has the auth middleware except maybe the user’s account page (so they can edit their details).

The middleware for verified users only is verified

Route::get('/something/create', [App\Http\Controllers\SomeController::class, 'index'])->middleware(['auth', 'verified'])->name('something.create');

Since you edited a routes file you will need to run:

php artisan route:cache


Read the official Laravel documentation on verification here.