Skip to main content

Documentation Index

Fetch the complete documentation index at: https://kawax.biz/llms.txt

Use this file to discover all available pages before exploring further.

What is Fortify?

Laravel Fortify is a frontend-agnostic authentication backend implementation. It provides all the routes and controllers required for login, registration, password reset, email verification, two-factor authentication, and passkeys.
Fortify has no UI of its own. It works by receiving requests from a starter kit or your own frontend and routing them to the appropriate authentication logic.
The “frontend-agnostic” design is the key idea. Whether you use Blade, Inertia (React/Vue/Svelte), or a pure API, you can reuse the same authentication backend. This is why Fortify has remained in active use for so long.

History: from Jetstream to the current starter kits

Why the current starter kits still use Fortify

The original React/Vue starter kits were implemented without Fortify. However, when two-factor authentication (2FA) support was needed, Fortify was adopted directly, which caused the entire authentication layer to switch to a Fortify-based implementation. Because Fortify is designed to be frontend-agnostic, it integrates naturally with Inertia-based starter kits and continues to be used today.
Fortify is currently the longest-serving official Laravel authentication package. Since its debut in 2020, it has remained active through Jetstream and the current starter kits.

Current starter kit setup

In the React/Vue starter kits, Fortify is configured through these two files:
  • app/Providers/FortifyServiceProvider.php — registers views, actions, and rate limiters
  • config/fortify.php — specifies enabled features and authentication settings

Key settings in config/fortify.php

use Laravel\Fortify\Features;

return [
    'guard'    => 'web',
    'username' => 'email',
    'home'     => '/dashboard',

    'limiters' => [
        'login'      => 'login',
        'two-factor' => 'two-factor',
    ],

    'features' => [
        Features::registration(),
        Features::resetPasswords(),
        Features::emailVerification(),
        Features::twoFactorAuthentication([
            'confirm'         => true,
            'confirmPassword' => true,
        ]),
    ],
];
Passkeys (Features::passkeys()) are not enabled by default in the starter kits. Add the feature to the features array to enable them.

FortifyServiceProvider configuration

The starter kit’s FortifyServiceProvider handles three responsibilities.

1. Configuring actions

private function configureActions(): void
{
    Fortify::resetUserPasswordsUsing(ResetUserPassword::class);
    Fortify::createUsersUsing(CreateNewUser::class);
}
Classes in app/Actions/Fortify/ let you customize user creation and password reset logic. Validation and hashing are centralized here.

2. Configuring views

private function configureViews(): void
{
    Fortify::loginView(fn (Request $request) => Inertia::render('auth/login', [
        'canResetPassword' => Features::enabled(Features::resetPasswords()),
        'canRegister'      => Features::enabled(Features::registration()),
        'status'           => $request->session()->get('status'),
    ]));

    Fortify::resetPasswordView(fn (Request $request) => Inertia::render('auth/reset-password', [
        'email' => $request->email,
        'token' => $request->route('token'),
    ]));

    Fortify::requestPasswordResetLinkView(
        fn (Request $request) => Inertia::render('auth/forgot-password', [
            'status' => $request->session()->get('status'),
        ])
    );

    Fortify::verifyEmailView(
        fn (Request $request) => Inertia::render('auth/verify-email', [
            'status' => $request->session()->get('status'),
        ])
    );

    Fortify::registerView(fn () => Inertia::render('auth/register'));

    Fortify::twoFactorChallengeView(fn () => Inertia::render('auth/two-factor-challenge'));

    Fortify::confirmPasswordView(fn () => Inertia::render('auth/confirm-password'));
}
Each view method accepts a closure that returns an Inertia component. Notice how Features::enabled() checks feature flags before passing them to the view.
In a Blade application, return view('auth.login') instead of Inertia::render(...). Changing the frontend only requires updating FortifyServiceProvider; the authentication logic remains unchanged.

3. Configuring rate limiting

private function configureRateLimiting(): void
{
    RateLimiter::for('two-factor', function (Request $request) {
        return Limit::perMinute(5)->by($request->session()->get('login.id'));
    });

    RateLimiter::for('login', function (Request $request) {
        $throttleKey = Str::transliterate(
            Str::lower($request->input(Fortify::username())) . '|' . $request->ip()
        );

        return Limit::perMinute(5)->by($throttleKey);
    });
}
  • login limiter: rate-limits by email address and IP address combination (brute-force protection)
  • two-factor limiter: rate-limits by the login attempt ID stored in the session
Register a RateLimiter::for() key that matches each key in the limiters array of config/fortify.php.

Features and registered routes

The table below lists the main routes Fortify registers, grouped by feature.
FeatureMethodRoute
LoginGET/login
LoginPOST/login
LogoutPOST/logout
RegistrationGET/register
RegistrationPOST/register
Password reset requestGET / POST/forgot-password
Password resetGET / POST/reset-password
Email verificationGET/email/verify
Resend verification emailPOST/email/verification-notification
Password confirmationGET / POST/user/confirm-password
Enable 2FAPOST/user/two-factor-authentication
2FA challengeGET / POST/two-factor-challenge
Passkey loginGET / POST/passkeys/login
Passkey managementGET / POST / DELETE/user/passkeys
Run php artisan route:list --name=fortify or simply php artisan route:list to inspect all registered routes.

Two-factor authentication (2FA)

The starter kits enable Features::twoFactorAuthentication() with both confirm and confirmPassword set to true.
OptionMeaning
confirmRequire the user to confirm with an authentication code after enabling 2FA
confirmPasswordRequire a password confirmation before changing 2FA settings
From the 2FA settings screen, users can perform the following steps:
1

Enable 2FA

Send a POST request to /user/two-factor-authentication. On success, the session receives a two-factor-authentication-enabled status.
2

Scan the QR code

Send a GET request to /user/two-factor-qr-code to receive the SVG QR code to scan with an authenticator app.
3

Confirm with an authentication code

POST the confirmation code to /user/confirmed-two-factor-authentication to complete setup.
4

Save recovery codes

Send a GET request to /user/two-factor-recovery-codes to retrieve the recovery codes and store them somewhere safe.

Passkeys

Passkeys are a recent addition to Fortify. They provide passwordless authentication via WebAuthn, supporting Face ID, Touch ID, Windows Hello, and hardware security keys.

Enabling passkeys

Add the feature to the features array in config/fortify.php:
'features' => [
    Features::registration(),
    Features::resetPasswords(),
    Features::emailVerification(),
    Features::twoFactorAuthentication([
        'confirm'         => true,
        'confirmPassword' => true,
    ]),
    Features::passkeys([
        'confirmPassword' => true,
    ]),
],
Next, add the PasskeyUser contract and PasskeyAuthenticatable trait to your User model:
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Fortify\Contracts\PasskeyUser;
use Laravel\Fortify\PasskeyAuthenticatable;

class User extends Authenticatable implements PasskeyUser
{
    use PasskeyAuthenticatable;
}
WebAuthn settings are managed under the passkeys key in config/fortify.php:
'passkeys' => [
    'relying_party_id'  => parse_url(config('app.url'), PHP_URL_HOST),
    'allowed_origins'   => [config('app.url')],
    'user_handle_secret' => config('app.key'),
    'timeout'           => 60000,
],
Fortify’s passkey support wraps the laravel/passkeys Composer package internally. You do not need to publish the laravel/passkeys config file — the passkeys key in config/fortify.php takes precedence.
For more on passkeys (the @laravel/passkeys JS client, React/Vue/Svelte helpers, and more), see the passkeys introduction guide.

Custom authentication guards

Learn how to implement custom authentication guards using the Guard and StatefulGuard interfaces.

Official docs: Laravel Fortify

Full installation instructions, all features, and customization details are in the official documentation.
Last modified on May 6, 2026