344 lines
11 KiB
Markdown
344 lines
11 KiB
Markdown
# Email Verification
|
||
|
||
* Introduction
|
||
* Model Preparation
|
||
* Database Preparation
|
||
* Routing
|
||
* The Email Verification Notice
|
||
* The Email Verification Handler
|
||
* Resending the Verification Email
|
||
* Protecting Routes
|
||
* Customization
|
||
* Events
|
||
|
||
## Introduction
|
||
|
||
Many web applications require users to verify their email addresses before
|
||
using the application. Rather than forcing you to re-implement this feature by
|
||
hand for each application you create, Laravel provides convenient built-in
|
||
services for sending and verifying email verification requests.
|
||
|
||
Want to get started fast? Install one of the [Laravel application starter
|
||
kits](/docs/12.x/starter-kits) in a fresh Laravel application. The starter
|
||
kits will take care of scaffolding your entire authentication system,
|
||
including email verification support.
|
||
|
||
### Model Preparation
|
||
|
||
Before getting started, verify that your `App\Models\User` model implements
|
||
the `Illuminate\Contracts\Auth\MustVerifyEmail` contract:
|
||
|
||
|
||
|
||
1<?php
|
||
|
||
2
|
||
|
||
3namespace App\Models;
|
||
|
||
4
|
||
|
||
5use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||
|
||
6use Illuminate\Foundation\Auth\User as Authenticatable;
|
||
|
||
7use Illuminate\Notifications\Notifiable;
|
||
|
||
8
|
||
|
||
9class User extends Authenticatable implements MustVerifyEmail
|
||
|
||
10{
|
||
|
||
11 use Notifiable;
|
||
|
||
12
|
||
|
||
13 // ...
|
||
|
||
14}
|
||
|
||
|
||
<?php
|
||
|
||
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;
|
||
|
||
// ...
|
||
}
|
||
|
||
Once this interface has been added to your model, newly registered users will
|
||
automatically be sent an email containing an email verification link. This
|
||
happens seamlessly because Laravel automatically registers the
|
||
`Illuminate\Auth\Listeners\SendEmailVerificationNotification`
|
||
[listener](/docs/12.x/events) for the `Illuminate\Auth\Events\Registered`
|
||
event.
|
||
|
||
If you are manually implementing registration within your application instead
|
||
of using [a starter kit](/docs/12.x/starter-kits), you should ensure that you
|
||
are dispatching the `Illuminate\Auth\Events\Registered` event after a user's
|
||
registration is successful:
|
||
|
||
|
||
|
||
1use Illuminate\Auth\Events\Registered;
|
||
|
||
2
|
||
|
||
3event(new Registered($user));
|
||
|
||
|
||
use Illuminate\Auth\Events\Registered;
|
||
|
||
event(new Registered($user));
|
||
|
||
### Database Preparation
|
||
|
||
Next, your `users` table must contain an `email_verified_at` column to store
|
||
the date and time that the user's email address was verified. Typically, this
|
||
is included in Laravel's default `0001_01_01_000000_create_users_table.php`
|
||
database migration.
|
||
|
||
## Routing
|
||
|
||
To properly implement email verification, three routes will need to be
|
||
defined. First, a route will be needed to display a notice to the user that
|
||
they should click the email verification link in the verification email that
|
||
Laravel sent them after registration.
|
||
|
||
Second, a route will be needed to handle requests generated when the user
|
||
clicks the email verification link in the email.
|
||
|
||
Third, a route will be needed to resend a verification link if the user
|
||
accidentally loses the first verification link.
|
||
|
||
### The Email Verification Notice
|
||
|
||
As mentioned previously, a route should be defined that will return a view
|
||
instructing the user to click the email verification link that was emailed to
|
||
them by Laravel after registration. This view will be displayed to users when
|
||
they try to access other parts of the application without verifying their
|
||
email address first. Remember, the link is automatically emailed to the user
|
||
as long as your `App\Models\User` model implements the `MustVerifyEmail`
|
||
interface:
|
||
|
||
|
||
|
||
1Route::get('/email/verify', function () {
|
||
|
||
2 return view('auth.verify-email');
|
||
|
||
3})->middleware('auth')->name('verification.notice');
|
||
|
||
|
||
Route::get('/email/verify', function () {
|
||
return view('auth.verify-email');
|
||
})->middleware('auth')->name('verification.notice');
|
||
|
||
The route that returns the email verification notice should be named
|
||
`verification.notice`. It is important that the route is assigned this exact
|
||
name since the `verified` middleware included with Laravel will automatically
|
||
redirect to this route name if a user has not verified their email address.
|
||
|
||
When manually implementing email verification, you are required to define the
|
||
contents of the verification notice view yourself. If you would like
|
||
scaffolding that includes all necessary authentication and verification views,
|
||
check out the [Laravel application starter kits](/docs/12.x/starter-kits).
|
||
|
||
### The Email Verification Handler
|
||
|
||
Next, we need to define a route that will handle requests generated when the
|
||
user clicks the email verification link that was emailed to them. This route
|
||
should be named `verification.verify` and be assigned the `auth` and `signed`
|
||
middlewares:
|
||
|
||
|
||
|
||
1use Illuminate\Foundation\Auth\EmailVerificationRequest;
|
||
|
||
2
|
||
|
||
3Route::get('/email/verify/{id}/{hash}', function (EmailVerificationRequest $request) {
|
||
|
||
4 $request->fulfill();
|
||
|
||
5
|
||
|
||
6 return redirect('/home');
|
||
|
||
7})->middleware(['auth', 'signed'])->name('verification.verify');
|
||
|
||
|
||
use Illuminate\Foundation\Auth\EmailVerificationRequest;
|
||
|
||
Route::get('/email/verify/{id}/{hash}', function (EmailVerificationRequest $request) {
|
||
$request->fulfill();
|
||
|
||
return redirect('/home');
|
||
})->middleware(['auth', 'signed'])->name('verification.verify');
|
||
|
||
Before moving on, let's take a closer look at this route. First, you'll notice
|
||
we are using an `EmailVerificationRequest` request type instead of the typical
|
||
`Illuminate\Http\Request` instance. The `EmailVerificationRequest` is a [form
|
||
request](/docs/12.x/validation#form-request-validation) that is included with
|
||
Laravel. This request will automatically take care of validating the request's
|
||
`id` and `hash` parameters.
|
||
|
||
Next, we can proceed directly to calling the `fulfill` method on the request.
|
||
This method will call the `markEmailAsVerified` method on the authenticated
|
||
user and dispatch the `Illuminate\Auth\Events\Verified` event. The
|
||
`markEmailAsVerified` method is available to the default `App\Models\User`
|
||
model via the `Illuminate\Foundation\Auth\User` base class. Once the user's
|
||
email address has been verified, you may redirect them wherever you wish.
|
||
|
||
### Resending the Verification Email
|
||
|
||
Sometimes a user may misplace or accidentally delete the email address
|
||
verification email. To accommodate this, you may wish to define a route to
|
||
allow the user to request that the verification email be resent. You may then
|
||
make a request to this route by placing a simple form submission button within
|
||
your verification notice view:
|
||
|
||
|
||
|
||
1use Illuminate\Http\Request;
|
||
|
||
2
|
||
|
||
3Route::post('/email/verification-notification', function (Request $request) {
|
||
|
||
4 $request->user()->sendEmailVerificationNotification();
|
||
|
||
5
|
||
|
||
6 return back()->with('message', 'Verification link sent!');
|
||
|
||
7})->middleware(['auth', 'throttle:6,1'])->name('verification.send');
|
||
|
||
|
||
use Illuminate\Http\Request;
|
||
|
||
Route::post('/email/verification-notification', function (Request $request) {
|
||
$request->user()->sendEmailVerificationNotification();
|
||
|
||
return back()->with('message', 'Verification link sent!');
|
||
})->middleware(['auth', 'throttle:6,1'])->name('verification.send');
|
||
|
||
### Protecting Routes
|
||
|
||
[Route middleware](/docs/12.x/middleware) may be used to only allow verified
|
||
users to access a given route. Laravel includes a `verified` [middleware
|
||
alias](/docs/12.x/middleware#middleware-aliases), which is an alias for the
|
||
`Illuminate\Auth\Middleware\EnsureEmailIsVerified` middleware class. Since
|
||
this alias is already automatically registered by Laravel, all you need to do
|
||
is attach the `verified` middleware to a route definition. Typically, this
|
||
middleware is paired with the `auth` middleware:
|
||
|
||
|
||
|
||
1Route::get('/profile', function () {
|
||
|
||
2 // Only verified users may access this route...
|
||
|
||
3})->middleware(['auth', 'verified']);
|
||
|
||
|
||
Route::get('/profile', function () {
|
||
// Only verified users may access this route...
|
||
})->middleware(['auth', 'verified']);
|
||
|
||
If an unverified user attempts to access a route that has been assigned this
|
||
middleware, they will automatically be redirected to the `verification.notice`
|
||
[named route](/docs/12.x/routing#named-routes).
|
||
|
||
## Customization
|
||
|
||
#### Verification Email Customization
|
||
|
||
Although the default email verification notification should satisfy the
|
||
requirements of most applications, Laravel allows you to customize how the
|
||
email verification mail message is constructed.
|
||
|
||
To get started, pass a closure to the `toMailUsing` method provided by the
|
||
`Illuminate\Auth\Notifications\VerifyEmail` notification. The closure will
|
||
receive the notifiable model instance that is receiving the notification as
|
||
well as the signed email verification URL that the user must visit to verify
|
||
their email address. The closure should return an instance of
|
||
`Illuminate\Notifications\Messages\MailMessage`. Typically, you should call
|
||
the `toMailUsing` method from the `boot` method of your application's
|
||
`AppServiceProvider` class:
|
||
|
||
|
||
|
||
1use Illuminate\Auth\Notifications\VerifyEmail;
|
||
|
||
2use Illuminate\Notifications\Messages\MailMessage;
|
||
|
||
3
|
||
|
||
4/**
|
||
|
||
5 * Bootstrap any application services.
|
||
|
||
6 */
|
||
|
||
7public function boot(): void
|
||
|
||
8{
|
||
|
||
9 // ...
|
||
|
||
10
|
||
|
||
11 VerifyEmail::toMailUsing(function (object $notifiable, string $url) {
|
||
|
||
12 return (new MailMessage)
|
||
|
||
13 ->subject('Verify Email Address')
|
||
|
||
14 ->line('Click the button below to verify your email address.')
|
||
|
||
15 ->action('Verify Email Address', $url);
|
||
|
||
16 });
|
||
|
||
17}
|
||
|
||
|
||
use Illuminate\Auth\Notifications\VerifyEmail;
|
||
use Illuminate\Notifications\Messages\MailMessage;
|
||
|
||
/**
|
||
* Bootstrap any application services.
|
||
*/
|
||
public function boot(): void
|
||
{
|
||
// ...
|
||
|
||
VerifyEmail::toMailUsing(function (object $notifiable, string $url) {
|
||
return (new MailMessage)
|
||
->subject('Verify Email Address')
|
||
->line('Click the button below to verify your email address.')
|
||
->action('Verify Email Address', $url);
|
||
});
|
||
}
|
||
|
||
To learn more about mail notifications, please consult the [mail notification
|
||
documentation](/docs/12.x/notifications#mail-notifications).
|
||
|
||
## Events
|
||
|
||
When using the [Laravel application starter kits](/docs/12.x/starter-kits),
|
||
Laravel dispatches an `Illuminate\Auth\Events\Verified`
|
||
[event](/docs/12.x/events) during the email verification process. If you are
|
||
manually handling email verification for your application, you may wish to
|
||
manually dispatch these events after verification is completed.
|
||
|