1271 lines
41 KiB
Markdown
1271 lines
41 KiB
Markdown
# Laravel Fortify
|
||
|
||
* Introduction
|
||
* What is Fortify?
|
||
* When Should I Use Fortify?
|
||
* Installation
|
||
* Fortify Features
|
||
* Disabling Views
|
||
* Authentication
|
||
* Customizing User Authentication
|
||
* Customizing the Authentication Pipeline
|
||
* Customizing Redirects
|
||
* Two Factor Authentication
|
||
* Enabling Two Factor Authentication
|
||
* Authenticating With Two Factor Authentication
|
||
* Disabling Two Factor Authentication
|
||
* Registration
|
||
* Customizing Registration
|
||
* Password Reset
|
||
* Requesting a Password Reset Link
|
||
* Resetting the Password
|
||
* Customizing Password Resets
|
||
* Email Verification
|
||
* Protecting Routes
|
||
* Password Confirmation
|
||
|
||
## Introduction
|
||
|
||
[Laravel Fortify](https://github.com/laravel/fortify) is a frontend agnostic
|
||
authentication backend implementation for Laravel. Fortify registers the
|
||
routes and controllers needed to implement all of Laravel's authentication
|
||
features, including login, registration, password reset, email verification,
|
||
and more. After installing Fortify, you may run the `route:list` Artisan
|
||
command to see the routes that Fortify has registered.
|
||
|
||
Since Fortify does not provide its own user interface, it is meant to be
|
||
paired with your own user interface which makes requests to the routes it
|
||
registers. We will discuss exactly how to make requests to these routes in the
|
||
remainder of this documentation.
|
||
|
||
Remember, Fortify is a package that is meant to give you a head start
|
||
implementing Laravel's authentication features. **You are not required to use
|
||
it.** You are always free to manually interact with Laravel's authentication
|
||
services by following the documentation available in the
|
||
[authentication](/docs/12.x/authentication), [password
|
||
reset](/docs/12.x/passwords), and [email
|
||
verification](/docs/12.x/verification) documentation.
|
||
|
||
### What is Fortify?
|
||
|
||
As mentioned previously, Laravel Fortify is a frontend agnostic authentication
|
||
backend implementation for Laravel. Fortify registers the routes and
|
||
controllers needed to implement all of Laravel's authentication features,
|
||
including login, registration, password reset, email verification, and more.
|
||
|
||
**You are not required to use Fortify in order to use Laravel's authentication
|
||
features.** You are always free to manually interact with Laravel's
|
||
authentication services by following the documentation available in the
|
||
[authentication](/docs/12.x/authentication), [password
|
||
reset](/docs/12.x/passwords), and [email
|
||
verification](/docs/12.x/verification) documentation.
|
||
|
||
If you are new to Laravel, you may wish to explore [our application starter
|
||
kits](/docs/12.x/starter-kits) before attempting to use Laravel Fortify. Our
|
||
starter kits provide an authentication scaffolding for your application that
|
||
includes a user interface built with [Tailwind CSS](https://tailwindcss.com).
|
||
This allows you to study and get comfortable with Laravel's authentication
|
||
features before allowing Laravel Fortify to implement these features for you.
|
||
|
||
Laravel Fortify essentially takes the routes and controllers of our
|
||
application starter kits and offers them as a package that does not include a
|
||
user interface. This allows you to still quickly scaffold the backend
|
||
implementation of your application's authentication layer without being tied
|
||
to any particular frontend opinions.
|
||
|
||
### When Should I Use Fortify?
|
||
|
||
You may be wondering when it is appropriate to use Laravel Fortify. First, if
|
||
you are using one of Laravel's [application starter kits](/docs/12.x/starter-
|
||
kits), you do not need to install Laravel Fortify since all of Laravel's
|
||
application starter kits already provide a full authentication implementation.
|
||
|
||
If you are not using an application starter kit and your application needs
|
||
authentication features, you have two options: manually implement your
|
||
application's authentication features or use Laravel Fortify to provide the
|
||
backend implementation of these features.
|
||
|
||
If you choose to install Fortify, your user interface will make requests to
|
||
Fortify's authentication routes that are detailed in this documentation in
|
||
order to authenticate and register users.
|
||
|
||
If you choose to manually interact with Laravel's authentication services
|
||
instead of using Fortify, you may do so by following the documentation
|
||
available in the [authentication](/docs/12.x/authentication), [password
|
||
reset](/docs/12.x/passwords), and [email
|
||
verification](/docs/12.x/verification) documentation.
|
||
|
||
#### Laravel Fortify and Laravel Sanctum
|
||
|
||
Some developers become confused regarding the difference between [Laravel
|
||
Sanctum](/docs/12.x/sanctum) and Laravel Fortify. Because the two packages
|
||
solve two different but related problems, Laravel Fortify and Laravel Sanctum
|
||
are not mutually exclusive or competing packages.
|
||
|
||
Laravel Sanctum is only concerned with managing API tokens and authenticating
|
||
existing users using session cookies or tokens. Sanctum does not provide any
|
||
routes that handle user registration, password reset, etc.
|
||
|
||
If you are attempting to manually build the authentication layer for an
|
||
application that offers an API or serves as the backend for a single-page
|
||
application, it is entirely possible that you will utilize both Laravel
|
||
Fortify (for user registration, password reset, etc.) and Laravel Sanctum (API
|
||
token management, session authentication).
|
||
|
||
## Installation
|
||
|
||
To get started, install Fortify using the Composer package manager:
|
||
|
||
|
||
|
||
1composer require laravel/fortify
|
||
|
||
|
||
composer require laravel/fortify
|
||
|
||
Next, publish Fortify's resources using the `fortify:install` Artisan command:
|
||
|
||
|
||
|
||
1php artisan fortify:install
|
||
|
||
|
||
php artisan fortify:install
|
||
|
||
This command will publish Fortify's actions to your `app/Actions` directory,
|
||
which will be created if it does not exist. In addition, the
|
||
`FortifyServiceProvider`, configuration file, and all necessary database
|
||
migrations will be published.
|
||
|
||
Next, you should migrate your database:
|
||
|
||
|
||
|
||
1php artisan migrate
|
||
|
||
|
||
php artisan migrate
|
||
|
||
### Fortify Features
|
||
|
||
The `fortify` configuration file contains a `features` configuration array.
|
||
This array defines which backend routes / features Fortify will expose by
|
||
default. We recommend that you only enable the following features, which are
|
||
the basic authentication features provided by most Laravel applications:
|
||
|
||
|
||
|
||
1'features' => [
|
||
|
||
2 Features::registration(),
|
||
|
||
3 Features::resetPasswords(),
|
||
|
||
4 Features::emailVerification(),
|
||
|
||
5],
|
||
|
||
|
||
'features' => [
|
||
Features::registration(),
|
||
Features::resetPasswords(),
|
||
Features::emailVerification(),
|
||
],
|
||
|
||
### Disabling Views
|
||
|
||
By default, Fortify defines routes that are intended to return views, such as
|
||
a login screen or registration screen. However, if you are building a
|
||
JavaScript driven single-page application, you may not need these routes. For
|
||
that reason, you may disable these routes entirely by setting the `views`
|
||
configuration value within your application's `config/fortify.php`
|
||
configuration file to `false`:
|
||
|
||
|
||
|
||
1'views' => false,
|
||
|
||
|
||
'views' => false,
|
||
|
||
#### Disabling Views and Password Reset
|
||
|
||
If you choose to disable Fortify's views and you will be implementing password
|
||
reset features for your application, you should still define a route named
|
||
`password.reset` that is responsible for displaying your application's "reset
|
||
password" view. This is necessary because Laravel's
|
||
`Illuminate\Auth\Notifications\ResetPassword` notification will generate the
|
||
password reset URL via the `password.reset` named route.
|
||
|
||
## Authentication
|
||
|
||
To get started, we need to instruct Fortify how to return our "login" view.
|
||
Remember, Fortify is a headless authentication library. If you would like a
|
||
frontend implementation of Laravel's authentication features that are already
|
||
completed for you, you should use an [application starter
|
||
kit](/docs/12.x/starter-kits).
|
||
|
||
All of the authentication view's rendering logic may be customized using the
|
||
appropriate methods available via the `Laravel\Fortify\Fortify` class.
|
||
Typically, you should call this method from the `boot` method of your
|
||
application's `App\Providers\FortifyServiceProvider` class. Fortify will take
|
||
care of defining the `/login` route that returns this view:
|
||
|
||
|
||
|
||
1use Laravel\Fortify\Fortify;
|
||
|
||
2
|
||
|
||
3/**
|
||
|
||
4 * Bootstrap any application services.
|
||
|
||
5 */
|
||
|
||
6public function boot(): void
|
||
|
||
7{
|
||
|
||
8 Fortify::loginView(function () {
|
||
|
||
9 return view('auth.login');
|
||
|
||
10 });
|
||
|
||
11
|
||
|
||
12 // ...
|
||
|
||
13}
|
||
|
||
|
||
use Laravel\Fortify\Fortify;
|
||
|
||
/**
|
||
* Bootstrap any application services.
|
||
*/
|
||
public function boot(): void
|
||
{
|
||
Fortify::loginView(function () {
|
||
return view('auth.login');
|
||
});
|
||
|
||
// ...
|
||
}
|
||
|
||
Your login template should include a form that makes a POST request to
|
||
`/login`. The `/login` endpoint expects a string `email` / `username` and a
|
||
`password`. The name of the email / username field should match the `username`
|
||
value within the `config/fortify.php` configuration file. In addition, a
|
||
boolean `remember` field may be provided to indicate that the user would like
|
||
to use the "remember me" functionality provided by Laravel.
|
||
|
||
If the login attempt is successful, Fortify will redirect you to the URI
|
||
configured via the `home` configuration option within your application's
|
||
`fortify` configuration file. If the login request was an XHR request, a 200
|
||
HTTP response will be returned.
|
||
|
||
If the request was not successful, the user will be redirected back to the
|
||
login screen and the validation errors will be available to you via the shared
|
||
`$errors` [Blade template variable](/docs/12.x/validation#quick-displaying-
|
||
the-validation-errors). Or, in the case of an XHR request, the validation
|
||
errors will be returned with the 422 HTTP response.
|
||
|
||
### Customizing User Authentication
|
||
|
||
Fortify will automatically retrieve and authenticate the user based on the
|
||
provided credentials and the authentication guard that is configured for your
|
||
application. However, you may sometimes wish to have full customization over
|
||
how login credentials are authenticated and users are retrieved. Thankfully,
|
||
Fortify allows you to easily accomplish this using the
|
||
`Fortify::authenticateUsing` method.
|
||
|
||
This method accepts a closure which receives the incoming HTTP request. The
|
||
closure is responsible for validating the login credentials attached to the
|
||
request and returning the associated user instance. If the credentials are
|
||
invalid or no user can be found, `null` or `false` should be returned by the
|
||
closure. Typically, this method should be called from the `boot` method of
|
||
your `FortifyServiceProvider`:
|
||
|
||
|
||
|
||
1use App\Models\User;
|
||
|
||
2use Illuminate\Http\Request;
|
||
|
||
3use Illuminate\Support\Facades\Hash;
|
||
|
||
4use Laravel\Fortify\Fortify;
|
||
|
||
5
|
||
|
||
6/**
|
||
|
||
7 * Bootstrap any application services.
|
||
|
||
8 */
|
||
|
||
9public function boot(): void
|
||
|
||
10{
|
||
|
||
11 Fortify::authenticateUsing(function (Request $request) {
|
||
|
||
12 $user = User::where('email', $request->email)->first();
|
||
|
||
13
|
||
|
||
14 if ($user &&
|
||
|
||
15 Hash::check($request->password, $user->password)) {
|
||
|
||
16 return $user;
|
||
|
||
17 }
|
||
|
||
18 });
|
||
|
||
19
|
||
|
||
20 // ...
|
||
|
||
21}
|
||
|
||
|
||
use App\Models\User;
|
||
use Illuminate\Http\Request;
|
||
use Illuminate\Support\Facades\Hash;
|
||
use Laravel\Fortify\Fortify;
|
||
|
||
/**
|
||
* Bootstrap any application services.
|
||
*/
|
||
public function boot(): void
|
||
{
|
||
Fortify::authenticateUsing(function (Request $request) {
|
||
$user = User::where('email', $request->email)->first();
|
||
|
||
if ($user &&
|
||
Hash::check($request->password, $user->password)) {
|
||
return $user;
|
||
}
|
||
});
|
||
|
||
// ...
|
||
}
|
||
|
||
#### Authentication Guard
|
||
|
||
You may customize the authentication guard used by Fortify within your
|
||
application's `fortify` configuration file. However, you should ensure that
|
||
the configured guard is an implementation of
|
||
`Illuminate\Contracts\Auth\StatefulGuard`. If you are attempting to use
|
||
Laravel Fortify to authenticate an SPA, you should use Laravel's default `web`
|
||
guard in combination with [Laravel Sanctum](https://laravel.com/docs/sanctum).
|
||
|
||
### Customizing the Authentication Pipeline
|
||
|
||
Laravel Fortify authenticates login requests through a pipeline of invokable
|
||
classes. If you would like, you may define a custom pipeline of classes that
|
||
login requests should be piped through. Each class should have an `__invoke`
|
||
method which receives the incoming `Illuminate\Http\Request` instance and,
|
||
like [middleware](/docs/12.x/middleware), a `$next` variable that is invoked
|
||
in order to pass the request to the next class in the pipeline.
|
||
|
||
To define your custom pipeline, you may use the `Fortify::authenticateThrough`
|
||
method. This method accepts a closure which should return the array of classes
|
||
to pipe the login request through. Typically, this method should be called
|
||
from the `boot` method of your `App\Providers\FortifyServiceProvider` class.
|
||
|
||
The example below contains the default pipeline definition that you may use as
|
||
a starting point when making your own modifications:
|
||
|
||
|
||
|
||
1use Laravel\Fortify\Actions\AttemptToAuthenticate;
|
||
|
||
2use Laravel\Fortify\Actions\CanonicalizeUsername;
|
||
|
||
3use Laravel\Fortify\Actions\EnsureLoginIsNotThrottled;
|
||
|
||
4use Laravel\Fortify\Actions\PrepareAuthenticatedSession;
|
||
|
||
5use Laravel\Fortify\Actions\RedirectIfTwoFactorAuthenticatable;
|
||
|
||
6use Laravel\Fortify\Features;
|
||
|
||
7use Laravel\Fortify\Fortify;
|
||
|
||
8use Illuminate\Http\Request;
|
||
|
||
9
|
||
|
||
10Fortify::authenticateThrough(function (Request $request) {
|
||
|
||
11 return array_filter([
|
||
|
||
12 config('fortify.limiters.login') ? null : EnsureLoginIsNotThrottled::class,
|
||
|
||
13 config('fortify.lowercase_usernames') ? CanonicalizeUsername::class : null,
|
||
|
||
14 Features::enabled(Features::twoFactorAuthentication()) ? RedirectIfTwoFactorAuthenticatable::class : null,
|
||
|
||
15 AttemptToAuthenticate::class,
|
||
|
||
16 PrepareAuthenticatedSession::class,
|
||
|
||
17 ]);
|
||
|
||
18});
|
||
|
||
|
||
use Laravel\Fortify\Actions\AttemptToAuthenticate;
|
||
use Laravel\Fortify\Actions\CanonicalizeUsername;
|
||
use Laravel\Fortify\Actions\EnsureLoginIsNotThrottled;
|
||
use Laravel\Fortify\Actions\PrepareAuthenticatedSession;
|
||
use Laravel\Fortify\Actions\RedirectIfTwoFactorAuthenticatable;
|
||
use Laravel\Fortify\Features;
|
||
use Laravel\Fortify\Fortify;
|
||
use Illuminate\Http\Request;
|
||
|
||
Fortify::authenticateThrough(function (Request $request) {
|
||
return array_filter([
|
||
config('fortify.limiters.login') ? null : EnsureLoginIsNotThrottled::class,
|
||
config('fortify.lowercase_usernames') ? CanonicalizeUsername::class : null,
|
||
Features::enabled(Features::twoFactorAuthentication()) ? RedirectIfTwoFactorAuthenticatable::class : null,
|
||
AttemptToAuthenticate::class,
|
||
PrepareAuthenticatedSession::class,
|
||
]);
|
||
});
|
||
|
||
#### Authentication Throttling
|
||
|
||
By default, Fortify will throttle authentication attempts using the
|
||
`EnsureLoginIsNotThrottled` middleware. This middleware throttles attempts
|
||
that are unique to a username and IP address combination.
|
||
|
||
Some applications may require a different approach to throttling
|
||
authentication attempts, such as throttling by IP address alone. Therefore,
|
||
Fortify allows you to specify your own [rate limiter](/docs/12.x/routing#rate-
|
||
limiting) via the `fortify.limiters.login` configuration option. Of course,
|
||
this configuration option is located in your application's
|
||
`config/fortify.php` configuration file.
|
||
|
||
Utilizing a mixture of throttling, [two factor
|
||
authentication](/docs/12.x/fortify#two-factor-authentication), and an external
|
||
web application firewall (WAF) will provide the most robust defense for your
|
||
legitimate application users.
|
||
|
||
### Customizing Redirects
|
||
|
||
If the login attempt is successful, Fortify will redirect you to the URI
|
||
configured via the `home` configuration option within your application's
|
||
`fortify` configuration file. If the login request was an XHR request, a 200
|
||
HTTP response will be returned. After a user logs out of the application, the
|
||
user will be redirected to the `/` URI.
|
||
|
||
If you need advanced customization of this behavior, you may bind
|
||
implementations of the `LoginResponse` and `LogoutResponse` contracts into the
|
||
Laravel [service container](/docs/12.x/container). Typically, this should be
|
||
done within the `register` method of your application's
|
||
`App\Providers\FortifyServiceProvider` class:
|
||
|
||
|
||
|
||
1use Laravel\Fortify\Contracts\LogoutResponse;
|
||
|
||
2
|
||
|
||
3/**
|
||
|
||
4 * Register any application services.
|
||
|
||
5 */
|
||
|
||
6public function register(): void
|
||
|
||
7{
|
||
|
||
8 $this->app->instance(LogoutResponse::class, new class implements LogoutResponse {
|
||
|
||
9 public function toResponse($request)
|
||
|
||
10 {
|
||
|
||
11 return redirect('/');
|
||
|
||
12 }
|
||
|
||
13 });
|
||
|
||
14}
|
||
|
||
|
||
use Laravel\Fortify\Contracts\LogoutResponse;
|
||
|
||
/**
|
||
* Register any application services.
|
||
*/
|
||
public function register(): void
|
||
{
|
||
$this->app->instance(LogoutResponse::class, new class implements LogoutResponse {
|
||
public function toResponse($request)
|
||
{
|
||
return redirect('/');
|
||
}
|
||
});
|
||
}
|
||
|
||
## Two Factor Authentication
|
||
|
||
When Fortify's two factor authentication feature is enabled, the user is
|
||
required to input a six digit numeric token during the authentication process.
|
||
This token is generated using a time-based one-time password (TOTP) that can
|
||
be retrieved from any TOTP compatible mobile authentication application such
|
||
as Google Authenticator.
|
||
|
||
Before getting started, you should first ensure that your application's
|
||
`App\Models\User` model uses the `Laravel\Fortify\TwoFactorAuthenticatable`
|
||
trait:
|
||
|
||
|
||
|
||
1<?php
|
||
|
||
2
|
||
|
||
3namespace App\Models;
|
||
|
||
4
|
||
|
||
5use Illuminate\Foundation\Auth\User as Authenticatable;
|
||
|
||
6use Illuminate\Notifications\Notifiable;
|
||
|
||
7use Laravel\Fortify\TwoFactorAuthenticatable;
|
||
|
||
8
|
||
|
||
9class User extends Authenticatable
|
||
|
||
10{
|
||
|
||
11 use Notifiable, TwoFactorAuthenticatable;
|
||
|
||
12}
|
||
|
||
|
||
<?php
|
||
|
||
namespace App\Models;
|
||
|
||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||
use Illuminate\Notifications\Notifiable;
|
||
use Laravel\Fortify\TwoFactorAuthenticatable;
|
||
|
||
class User extends Authenticatable
|
||
{
|
||
use Notifiable, TwoFactorAuthenticatable;
|
||
}
|
||
|
||
Next, you should build a screen within your application where users can manage
|
||
their two factor authentication settings. This screen should allow the user to
|
||
enable and disable two factor authentication, as well as regenerate their two
|
||
factor authentication recovery codes.
|
||
|
||
> By default, the `features` array of the `fortify` configuration file
|
||
> instructs Fortify's two factor authentication settings to require password
|
||
> confirmation before modification. Therefore, your application should
|
||
> implement Fortify's password confirmation feature before continuing.
|
||
|
||
### Enabling Two Factor Authentication
|
||
|
||
To begin enabling two factor authentication, your application should make a
|
||
POST request to the `/user/two-factor-authentication` endpoint defined by
|
||
Fortify. If the request is successful, the user will be redirected back to the
|
||
previous URL and the `status` session variable will be set to `two-factor-
|
||
authentication-enabled`. You may detect this `status` session variable within
|
||
your templates to display the appropriate success message. If the request was
|
||
an XHR request, `200` HTTP response will be returned.
|
||
|
||
After choosing to enable two factor authentication, the user must still
|
||
"confirm" their two factor authentication configuration by providing a valid
|
||
two factor authentication code. So, your "success" message should instruct the
|
||
user that two factor authentication confirmation is still required:
|
||
|
||
|
||
|
||
1@if (session('status') == 'two-factor-authentication-enabled')
|
||
|
||
2 <div class="mb-4 font-medium text-sm">
|
||
|
||
3 Please finish configuring two factor authentication below.
|
||
|
||
4 </div>
|
||
|
||
5@endif
|
||
|
||
|
||
@if (session('status') == 'two-factor-authentication-enabled')
|
||
<div class="mb-4 font-medium text-sm">
|
||
Please finish configuring two factor authentication below.
|
||
</div>
|
||
@endif
|
||
|
||
Next, you should display the two factor authentication QR code for the user to
|
||
scan into their authenticator application. If you are using Blade to render
|
||
your application's frontend, you may retrieve the QR code SVG using the
|
||
`twoFactorQrCodeSvg` method available on the user instance:
|
||
|
||
|
||
|
||
1$request->user()->twoFactorQrCodeSvg();
|
||
|
||
|
||
$request->user()->twoFactorQrCodeSvg();
|
||
|
||
If you are building a JavaScript powered frontend, you may make an XHR GET
|
||
request to the `/user/two-factor-qr-code` endpoint to retrieve the user's two
|
||
factor authentication QR code. This endpoint will return a JSON object
|
||
containing an `svg` key.
|
||
|
||
#### Confirming Two Factor Authentication
|
||
|
||
In addition to displaying the user's two factor authentication QR code, you
|
||
should provide a text input where the user can supply a valid authentication
|
||
code to "confirm" their two factor authentication configuration. This code
|
||
should be provided to the Laravel application via a POST request to the
|
||
`/user/confirmed-two-factor-authentication` endpoint defined by Fortify.
|
||
|
||
If the request is successful, the user will be redirected back to the previous
|
||
URL and the `status` session variable will be set to `two-factor-
|
||
authentication-confirmed`:
|
||
|
||
|
||
|
||
1@if (session('status') == 'two-factor-authentication-confirmed')
|
||
|
||
2 <div class="mb-4 font-medium text-sm">
|
||
|
||
3 Two factor authentication confirmed and enabled successfully.
|
||
|
||
4 </div>
|
||
|
||
5@endif
|
||
|
||
|
||
@if (session('status') == 'two-factor-authentication-confirmed')
|
||
<div class="mb-4 font-medium text-sm">
|
||
Two factor authentication confirmed and enabled successfully.
|
||
</div>
|
||
@endif
|
||
|
||
If the request to the two factor authentication confirmation endpoint was made
|
||
via an XHR request, a `200` HTTP response will be returned.
|
||
|
||
#### Displaying the Recovery Codes
|
||
|
||
You should also display the user's two factor recovery codes. These recovery
|
||
codes allow the user to authenticate if they lose access to their mobile
|
||
device. If you are using Blade to render your application's frontend, you may
|
||
access the recovery codes via the authenticated user instance:
|
||
|
||
|
||
|
||
1(array) $request->user()->recoveryCodes()
|
||
|
||
|
||
(array) $request->user()->recoveryCodes()
|
||
|
||
If you are building a JavaScript powered frontend, you may make an XHR GET
|
||
request to the `/user/two-factor-recovery-codes` endpoint. This endpoint will
|
||
return a JSON array containing the user's recovery codes.
|
||
|
||
To regenerate the user's recovery codes, your application should make a POST
|
||
request to the `/user/two-factor-recovery-codes` endpoint.
|
||
|
||
### Authenticating With Two Factor Authentication
|
||
|
||
During the authentication process, Fortify will automatically redirect the
|
||
user to your application's two factor authentication challenge screen.
|
||
However, if your application is making an XHR login request, the JSON response
|
||
returned after a successful authentication attempt will contain a JSON object
|
||
that has a `two_factor` boolean property. You should inspect this value to
|
||
know whether you should redirect to your application's two factor
|
||
authentication challenge screen.
|
||
|
||
To begin implementing two factor authentication functionality, we need to
|
||
instruct Fortify how to return our two factor authentication challenge view.
|
||
All of Fortify's authentication view rendering logic may be customized using
|
||
the appropriate methods available via the `Laravel\Fortify\Fortify` class.
|
||
Typically, you should call this method from the `boot` method of your
|
||
application's `App\Providers\FortifyServiceProvider` class:
|
||
|
||
|
||
|
||
1use Laravel\Fortify\Fortify;
|
||
|
||
2
|
||
|
||
3/**
|
||
|
||
4 * Bootstrap any application services.
|
||
|
||
5 */
|
||
|
||
6public function boot(): void
|
||
|
||
7{
|
||
|
||
8 Fortify::twoFactorChallengeView(function () {
|
||
|
||
9 return view('auth.two-factor-challenge');
|
||
|
||
10 });
|
||
|
||
11
|
||
|
||
12 // ...
|
||
|
||
13}
|
||
|
||
|
||
use Laravel\Fortify\Fortify;
|
||
|
||
/**
|
||
* Bootstrap any application services.
|
||
*/
|
||
public function boot(): void
|
||
{
|
||
Fortify::twoFactorChallengeView(function () {
|
||
return view('auth.two-factor-challenge');
|
||
});
|
||
|
||
// ...
|
||
}
|
||
|
||
Fortify will take care of defining the `/two-factor-challenge` route that
|
||
returns this view. Your `two-factor-challenge` template should include a form
|
||
that makes a POST request to the `/two-factor-challenge` endpoint. The `/two-
|
||
factor-challenge` action expects a `code` field that contains a valid TOTP
|
||
token or a `recovery_code` field that contains one of the user's recovery
|
||
codes.
|
||
|
||
If the login attempt is successful, Fortify will redirect the user to the URI
|
||
configured via the `home` configuration option within your application's
|
||
`fortify` configuration file. If the login request was an XHR request, a 204
|
||
HTTP response will be returned.
|
||
|
||
If the request was not successful, the user will be redirected back to the two
|
||
factor challenge screen and the validation errors will be available to you via
|
||
the shared `$errors` [Blade template variable](/docs/12.x/validation#quick-
|
||
displaying-the-validation-errors). Or, in the case of an XHR request, the
|
||
validation errors will be returned with a 422 HTTP response.
|
||
|
||
### Disabling Two Factor Authentication
|
||
|
||
To disable two factor authentication, your application should make a DELETE
|
||
request to the `/user/two-factor-authentication` endpoint. Remember, Fortify's
|
||
two factor authentication endpoints require password confirmation prior to
|
||
being called.
|
||
|
||
## Registration
|
||
|
||
To begin implementing our application's registration functionality, we need to
|
||
instruct Fortify how to return our "register" view. Remember, Fortify is a
|
||
headless authentication library. If you would like a frontend implementation
|
||
of Laravel's authentication features that are already completed for you, you
|
||
should use an [application starter kit](/docs/12.x/starter-kits).
|
||
|
||
All of Fortify's view rendering logic may be customized using the appropriate
|
||
methods available via the `Laravel\Fortify\Fortify` class. Typically, you
|
||
should call this method from the `boot` method of your
|
||
`App\Providers\FortifyServiceProvider` class:
|
||
|
||
|
||
|
||
1use Laravel\Fortify\Fortify;
|
||
|
||
2
|
||
|
||
3/**
|
||
|
||
4 * Bootstrap any application services.
|
||
|
||
5 */
|
||
|
||
6public function boot(): void
|
||
|
||
7{
|
||
|
||
8 Fortify::registerView(function () {
|
||
|
||
9 return view('auth.register');
|
||
|
||
10 });
|
||
|
||
11
|
||
|
||
12 // ...
|
||
|
||
13}
|
||
|
||
|
||
use Laravel\Fortify\Fortify;
|
||
|
||
/**
|
||
* Bootstrap any application services.
|
||
*/
|
||
public function boot(): void
|
||
{
|
||
Fortify::registerView(function () {
|
||
return view('auth.register');
|
||
});
|
||
|
||
// ...
|
||
}
|
||
|
||
Fortify will take care of defining the `/register` route that returns this
|
||
view. Your `register` template should include a form that makes a POST request
|
||
to the `/register` endpoint defined by Fortify.
|
||
|
||
The `/register` endpoint expects a string `name`, string email address /
|
||
username, `password`, and `password_confirmation` fields. The name of the
|
||
email / username field should match the `username` configuration value defined
|
||
within your application's `fortify` configuration file.
|
||
|
||
If the registration attempt is successful, Fortify will redirect the user to
|
||
the URI configured via the `home` configuration option within your
|
||
application's `fortify` configuration file. If the request was an XHR request,
|
||
a 201 HTTP response will be returned.
|
||
|
||
If the request was not successful, the user will be redirected back to the
|
||
registration screen and the validation errors will be available to you via the
|
||
shared `$errors` [Blade template variable](/docs/12.x/validation#quick-
|
||
displaying-the-validation-errors). Or, in the case of an XHR request, the
|
||
validation errors will be returned with a 422 HTTP response.
|
||
|
||
### Customizing Registration
|
||
|
||
The user validation and creation process may be customized by modifying the
|
||
`App\Actions\Fortify\CreateNewUser` action that was generated when you
|
||
installed Laravel Fortify.
|
||
|
||
## Password Reset
|
||
|
||
### Requesting a Password Reset Link
|
||
|
||
To begin implementing our application's password reset functionality, we need
|
||
to instruct Fortify how to return our "forgot password" view. Remember,
|
||
Fortify is a headless authentication library. If you would like a frontend
|
||
implementation of Laravel's authentication features that are already completed
|
||
for you, you should use an [application starter kit](/docs/12.x/starter-kits).
|
||
|
||
All of Fortify's view rendering logic may be customized using the appropriate
|
||
methods available via the `Laravel\Fortify\Fortify` class. Typically, you
|
||
should call this method from the `boot` method of your application's
|
||
`App\Providers\FortifyServiceProvider` class:
|
||
|
||
|
||
|
||
1use Laravel\Fortify\Fortify;
|
||
|
||
2
|
||
|
||
3/**
|
||
|
||
4 * Bootstrap any application services.
|
||
|
||
5 */
|
||
|
||
6public function boot(): void
|
||
|
||
7{
|
||
|
||
8 Fortify::requestPasswordResetLinkView(function () {
|
||
|
||
9 return view('auth.forgot-password');
|
||
|
||
10 });
|
||
|
||
11
|
||
|
||
12 // ...
|
||
|
||
13}
|
||
|
||
|
||
use Laravel\Fortify\Fortify;
|
||
|
||
/**
|
||
* Bootstrap any application services.
|
||
*/
|
||
public function boot(): void
|
||
{
|
||
Fortify::requestPasswordResetLinkView(function () {
|
||
return view('auth.forgot-password');
|
||
});
|
||
|
||
// ...
|
||
}
|
||
|
||
Fortify will take care of defining the `/forgot-password` endpoint that
|
||
returns this view. Your `forgot-password` template should include a form that
|
||
makes a POST request to the `/forgot-password` endpoint.
|
||
|
||
The `/forgot-password` endpoint expects a string `email` field. The name of
|
||
this field / database column should match the `email` configuration value
|
||
within your application's `fortify` configuration file.
|
||
|
||
#### Handling the Password Reset Link Request Response
|
||
|
||
If the password reset link request was successful, Fortify will redirect the
|
||
user back to the `/forgot-password` endpoint and send an email to the user
|
||
with a secure link they can use to reset their password. If the request was an
|
||
XHR request, a 200 HTTP response will be returned.
|
||
|
||
After being redirected back to the `/forgot-password` endpoint after a
|
||
successful request, the `status` session variable may be used to display the
|
||
status of the password reset link request attempt.
|
||
|
||
The value of the `$status` session variable will match one of the translation
|
||
strings defined within your application's `passwords` [language
|
||
file](/docs/12.x/localization). If you would like to customize this value and
|
||
have not published Laravel's language files, you may do so via the
|
||
`lang:publish` Artisan command:
|
||
|
||
|
||
|
||
1@if (session('status'))
|
||
|
||
2 <div class="mb-4 font-medium text-sm text-green-600">
|
||
|
||
3 {{ session('status') }}
|
||
|
||
4 </div>
|
||
|
||
5@endif
|
||
|
||
|
||
@if (session('status'))
|
||
<div class="mb-4 font-medium text-sm text-green-600">
|
||
{{ session('status') }}
|
||
</div>
|
||
@endif
|
||
|
||
If the request was not successful, the user will be redirected back to the
|
||
request password reset link screen and the validation errors will be available
|
||
to you via the shared `$errors` [Blade template
|
||
variable](/docs/12.x/validation#quick-displaying-the-validation-errors). Or,
|
||
in the case of an XHR request, the validation errors will be returned with a
|
||
422 HTTP response.
|
||
|
||
### Resetting the Password
|
||
|
||
To finish implementing our application's password reset functionality, we need
|
||
to instruct Fortify how to return our "reset password" view.
|
||
|
||
All of Fortify's view rendering logic may be customized using the appropriate
|
||
methods available via the `Laravel\Fortify\Fortify` class. Typically, you
|
||
should call this method from the `boot` method of your application's
|
||
`App\Providers\FortifyServiceProvider` class:
|
||
|
||
|
||
|
||
1use Laravel\Fortify\Fortify;
|
||
|
||
2use Illuminate\Http\Request;
|
||
|
||
3
|
||
|
||
4/**
|
||
|
||
5 * Bootstrap any application services.
|
||
|
||
6 */
|
||
|
||
7public function boot(): void
|
||
|
||
8{
|
||
|
||
9 Fortify::resetPasswordView(function (Request $request) {
|
||
|
||
10 return view('auth.reset-password', ['request' => $request]);
|
||
|
||
11 });
|
||
|
||
12
|
||
|
||
13 // ...
|
||
|
||
14}
|
||
|
||
|
||
use Laravel\Fortify\Fortify;
|
||
use Illuminate\Http\Request;
|
||
|
||
/**
|
||
* Bootstrap any application services.
|
||
*/
|
||
public function boot(): void
|
||
{
|
||
Fortify::resetPasswordView(function (Request $request) {
|
||
return view('auth.reset-password', ['request' => $request]);
|
||
});
|
||
|
||
// ...
|
||
}
|
||
|
||
Fortify will take care of defining the route to display this view. Your
|
||
`reset-password` template should include a form that makes a POST request to
|
||
`/reset-password`.
|
||
|
||
The `/reset-password` endpoint expects a string `email` field, a `password`
|
||
field, a `password_confirmation` field, and a hidden field named `token` that
|
||
contains the value of `request()->route('token')`. The name of the "email"
|
||
field / database column should match the `email` configuration value defined
|
||
within your application's `fortify` configuration file.
|
||
|
||
#### Handling the Password Reset Response
|
||
|
||
If the password reset request was successful, Fortify will redirect back to
|
||
the `/login` route so that the user can log in with their new password. In
|
||
addition, a `status` session variable will be set so that you may display the
|
||
successful status of the reset on your login screen:
|
||
|
||
|
||
|
||
1@if (session('status'))
|
||
|
||
2 <div class="mb-4 font-medium text-sm text-green-600">
|
||
|
||
3 {{ session('status') }}
|
||
|
||
4 </div>
|
||
|
||
5@endif
|
||
|
||
|
||
@if (session('status'))
|
||
<div class="mb-4 font-medium text-sm text-green-600">
|
||
{{ session('status') }}
|
||
</div>
|
||
@endif
|
||
|
||
If the request was an XHR request, a 200 HTTP response will be returned.
|
||
|
||
If the request was not successful, the user will be redirected back to the
|
||
reset password screen and the validation errors will be available to you via
|
||
the shared `$errors` [Blade template variable](/docs/12.x/validation#quick-
|
||
displaying-the-validation-errors). Or, in the case of an XHR request, the
|
||
validation errors will be returned with a 422 HTTP response.
|
||
|
||
### Customizing Password Resets
|
||
|
||
The password reset process may be customized by modifying the
|
||
`App\Actions\ResetUserPassword` action that was generated when you installed
|
||
Laravel Fortify.
|
||
|
||
## Email Verification
|
||
|
||
After registration, you may wish for users to verify their email address
|
||
before they continue accessing your application. To get started, ensure the
|
||
`emailVerification` feature is enabled in your `fortify` configuration file's
|
||
`features` array. Next, you should ensure that your `App\Models\User` class
|
||
implements the `Illuminate\Contracts\Auth\MustVerifyEmail` interface.
|
||
|
||
Once these two setup steps have been completed, newly registered users will
|
||
receive an email prompting them to verify their email address ownership.
|
||
However, we need to inform Fortify how to display the email verification
|
||
screen which informs the user that they need to go click the verification link
|
||
in the email.
|
||
|
||
All of Fortify's view's rendering logic may be customized using the
|
||
appropriate methods available via the `Laravel\Fortify\Fortify` class.
|
||
Typically, you should call this method from the `boot` method of your
|
||
application's `App\Providers\FortifyServiceProvider` class:
|
||
|
||
|
||
|
||
1use Laravel\Fortify\Fortify;
|
||
|
||
2
|
||
|
||
3/**
|
||
|
||
4 * Bootstrap any application services.
|
||
|
||
5 */
|
||
|
||
6public function boot(): void
|
||
|
||
7{
|
||
|
||
8 Fortify::verifyEmailView(function () {
|
||
|
||
9 return view('auth.verify-email');
|
||
|
||
10 });
|
||
|
||
11
|
||
|
||
12 // ...
|
||
|
||
13}
|
||
|
||
|
||
use Laravel\Fortify\Fortify;
|
||
|
||
/**
|
||
* Bootstrap any application services.
|
||
*/
|
||
public function boot(): void
|
||
{
|
||
Fortify::verifyEmailView(function () {
|
||
return view('auth.verify-email');
|
||
});
|
||
|
||
// ...
|
||
}
|
||
|
||
Fortify will take care of defining the route that displays this view when a
|
||
user is redirected to the `/email/verify` endpoint by Laravel's built-in
|
||
`verified` middleware.
|
||
|
||
Your `verify-email` template should include an informational message
|
||
instructing the user to click the email verification link that was sent to
|
||
their email address.
|
||
|
||
#### Resending Email Verification Links
|
||
|
||
If you wish, you may add a button to your application's `verify-email`
|
||
template that triggers a POST request to the `/email/verification-
|
||
notification` endpoint. When this endpoint receives a request, a new
|
||
verification email link will be emailed to the user, allowing the user to get
|
||
a new verification link if the previous one was accidentally deleted or lost.
|
||
|
||
If the request to resend the verification link email was successful, Fortify
|
||
will redirect the user back to the `/email/verify` endpoint with a `status`
|
||
session variable, allowing you to display an informational message to the user
|
||
informing them the operation was successful. If the request was an XHR
|
||
request, a 202 HTTP response will be returned:
|
||
|
||
|
||
|
||
1@if (session('status') == 'verification-link-sent')
|
||
|
||
2 <div class="mb-4 font-medium text-sm text-green-600">
|
||
|
||
3 A new email verification link has been emailed to you!
|
||
|
||
4 </div>
|
||
|
||
5@endif
|
||
|
||
|
||
@if (session('status') == 'verification-link-sent')
|
||
<div class="mb-4 font-medium text-sm text-green-600">
|
||
A new email verification link has been emailed to you!
|
||
</div>
|
||
@endif
|
||
|
||
### Protecting Routes
|
||
|
||
To specify that a route or group of routes requires that the user has verified
|
||
their email address, you should attach Laravel's built-in `verified`
|
||
middleware to the route. The `verified` middleware alias is automatically
|
||
registered by Laravel and serves as an alias for the
|
||
`Illuminate\Auth\Middleware\EnsureEmailIsVerified` middleware:
|
||
|
||
|
||
|
||
1Route::get('/dashboard', function () {
|
||
|
||
2 // ...
|
||
|
||
3})->middleware(['verified']);
|
||
|
||
|
||
Route::get('/dashboard', function () {
|
||
// ...
|
||
})->middleware(['verified']);
|
||
|
||
## Password Confirmation
|
||
|
||
While building your application, you may occasionally have actions that should
|
||
require the user to confirm their password before the action is performed.
|
||
Typically, these routes are protected by Laravel's built-in `password.confirm`
|
||
middleware.
|
||
|
||
To begin implementing password confirmation functionality, we need to instruct
|
||
Fortify how to return our application's "password confirmation" view.
|
||
Remember, Fortify is a headless authentication library. If you would like a
|
||
frontend implementation of Laravel's authentication features that are already
|
||
completed for you, you should use an [application starter
|
||
kit](/docs/12.x/starter-kits).
|
||
|
||
All of Fortify's view rendering logic may be customized using the appropriate
|
||
methods available via the `Laravel\Fortify\Fortify` class. Typically, you
|
||
should call this method from the `boot` method of your application's
|
||
`App\Providers\FortifyServiceProvider` class:
|
||
|
||
|
||
|
||
1use Laravel\Fortify\Fortify;
|
||
|
||
2
|
||
|
||
3/**
|
||
|
||
4 * Bootstrap any application services.
|
||
|
||
5 */
|
||
|
||
6public function boot(): void
|
||
|
||
7{
|
||
|
||
8 Fortify::confirmPasswordView(function () {
|
||
|
||
9 return view('auth.confirm-password');
|
||
|
||
10 });
|
||
|
||
11
|
||
|
||
12 // ...
|
||
|
||
13}
|
||
|
||
|
||
use Laravel\Fortify\Fortify;
|
||
|
||
/**
|
||
* Bootstrap any application services.
|
||
*/
|
||
public function boot(): void
|
||
{
|
||
Fortify::confirmPasswordView(function () {
|
||
return view('auth.confirm-password');
|
||
});
|
||
|
||
// ...
|
||
}
|
||
|
||
Fortify will take care of defining the `/user/confirm-password` endpoint that
|
||
returns this view. Your `confirm-password` template should include a form that
|
||
makes a POST request to the `/user/confirm-password` endpoint. The
|
||
`/user/confirm-password` endpoint expects a `password` field that contains the
|
||
user's current password.
|
||
|
||
If the password matches the user's current password, Fortify will redirect the
|
||
user to the route they were attempting to access. If the request was an XHR
|
||
request, a 201 HTTP response will be returned.
|
||
|
||
If the request was not successful, the user will be redirected back to the
|
||
confirm password screen and the validation errors will be available to you via
|
||
the shared `$errors` Blade template variable. Or, in the case of an XHR
|
||
request, the validation errors will be returned with a 422 HTTP response.
|
||
|