laravel/fortify
Laravel Fortify is a frontend-agnostic authentication backend for Laravel. It provides registration, login, password reset, email verification, and two-factor authentication endpoints and features used by Laravel starter kits, while letting you build your own UI.
## Getting Started
### Minimal Setup
1. **Installation**:
```bash
composer require laravel/fortify
Run the publisher to publish Fortify’s configuration and migration:
php artisan vendor:publish --provider="Laravel\Fortify\FortifyServiceProvider"
php artisan migrate
Configure Auth Guard:
In config/auth.php, set the default guard to web (or your preferred guard):
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
Register Fortify:
In AppServiceProvider@boot(), register Fortify with your preferred frontend (e.g., Livewire, Inertia, or Blade):
use Laravel\Fortify\Fortify;
public function boot()
{
Fortify::createUsersUsing(app(\Illuminate\Contracts\Auth\Registrar::class));
Fortify::authenticateUsing(app(\Illuminate\Contracts\Auth\Authenticatable::class));
Fortify::registerViewHandlers();
// OR for SPA (e.g., Inertia):
// Fortify::registerRouteControllers();
}
First Use Case:
@auth, @guest, and {{ route('login') }} in your views./login, /register) for frontend handling. Example:
// Inertia.js (SPA)
router.post('/login', (req) => {
return axios.post('/sanctum/csrf-cookie');
});
Login/Logout:
Fortify provides LoginController and LogoutController with built-in CSRF protection, throttling, and session handling.
// Customize login logic (e.g., add 2FA check)
public function validateLogin(Request $request)
{
return parent::validateLogin($request)->safe()->also(function ($request, $user) {
if ($user->hasEnabledTwoFactorAuthentication()) {
$request->session()->put('two_factor_intent', true);
return redirect()->route('two-factor.login');
}
});
}
Password Reset:
Use PasswordResetLinkController and PasswordResetController with email-based or token-based flows:
// Customize reset logic (e.g., log attempts)
public function reset(Request $request)
{
$response = parent::reset($request);
event(new PasswordResetAttempted($request->email));
return $response;
}
EnableTwoFactorAuthentication and DisableTwoFactorAuthentication actions:
use Laravel\Fortify\Actions\EnableTwoFactorAuthentication;
public function enableTwoFactor(Request $request)
{
return (new EnableTwoFactorAuthentication())($request)->response();
}
TwoFactorRecoveryCodeController:
// Generate new codes
$user->generateTwoFactorRecoveryCodes();
UpdateUserProfileInformation and UpdateUserPassword actions:
use Laravel\Fortify\Actions\UpdateUserPassword;
public function updatePassword(Request $request)
{
return (new UpdateUserPassword())($request)->response();
}
resources/views/vendor/fortify/.// routes/web.js (Inertia)
import { createInertiaApp } from '@inertiajs/inertia-react';
createInertiaApp({
resolve: (name) => require(`./Pages/${name}.jsx`),
setup({ el, App, props }) {
return createApp({ render: () => h(App, props) }).mount(el);
},
});
Use Fortify’s API endpoints (e.g., POST /login) in your frontend.Database Guard:
Fortify works out-of-the-box with Laravel’s default web guard. For custom guards (e.g., api), configure:
Fortify::authenticateUsing(app(\App\Services\CustomAuthenticatable::class));
Sanctum for SPAs: Ensure Sanctum is installed and configured:
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
Fortify integrates with Sanctum automatically for SPA sessions.
Middleware:
Use Fortify’s built-in middleware (e.g., EnsureEmailIsVerified, RedirectIfTwoFactorAuthenticatable) in routes:
Route::middleware(['auth', 'verified'])->group(function () {
// Protected routes
});
Events:
Listen to Fortify events (e.g., TwoFactorAuthenticationEnabled) for custom logic:
event(new TwoFactorAuthenticationEnabled($user));
Testing: Use Fortify’s test helpers:
use Laravel\Fortify\Testing\Concerns\InteractsWithFortify;
public function test_login()
{
$this->actingAs(User::factory()->create())
->post('/logout')
->assertRedirect('/');
}
Passkeys (v1.37+): Enable passkey authentication:
Fortify::enablePasskeys();
Update your frontend to support WebAuthn (e.g., using @simplewebauthn/browser).
Route Conflicts:
/sanctum for SPAs and /login for Blade. Ensure no conflicts with existing routes.FortifyServiceProvider or use route middleware to restrict access.Session Handling:
Fortify::regenerateSessionOnLogin(false);
2FA State Management:
InteractsWithTwoFactorState trait manages 2FA state across requests. Clear it manually if needed:
$request->session()->forget('two_factor_intent');
Password Reset Tokens:
config/fortify.php:
'password_reset' => [
'expire_after' => 60, // minutes
],
SPA Sanctum Issues:
$router->middlewareGroup('web', [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
// Other middleware...
]);
Passkey Browser Support:
Throttling:
config/fortify.php for limits:
'throttle' => [
'max_attempts' => 5,
'decay_minutes' => 1,
],
Email Verification:
$user->hasVerifiedEmail(); // Check status
$user->markEmailAsVerified(); // Manually verify
2FA QR Codes:
pragmarx/google2fa is installed and the two_factor_secret column exists in your users table.Route Debugging:
php artisan route:list | grep fortify
Custom Actions:
Extend Fortify’s actions (e.g., CreateNewUser). Example:
use Laravel\Fortify\Actions\CreateNewUser;
class CustomCreateNewUser extends CreateNewUser
{
public function create(array $data)
{
$user = parent::create($data);
// Custom logic (e.g., assign role)
return $user;
}
}
Register in AppServiceProvider:
Fortify::createUsersUsing(app(CustomCreateNewUser::class));
Custom Views: Override Fortify’s Blade views in `resources/views/vendor
How can I help you explore Laravel packages today?