Saltar al contenido principal

Qué es Fortify

Laravel Fortify es una implementación de backend de autenticación independiente del frontend. Aporta todas las rutas y controladores necesarios para login, registro, restablecimiento de contraseña, verificación de email, 2FA y passkeys.
Fortify no tiene UI. Funciona cuando un starter kit o tu propia UI envía peticiones a las rutas de Fortify.
La idea de «independiente del frontend» es importante: puedes reutilizar el mismo backend de autenticación tanto con Blade como con Inertia (React/Vue/Svelte) o con una API. Esa es la razón por la que Fortify sigue vigente tantos años.

Historia: de Jetstream a los starter kits actuales

Por qué los starter kits actuales siguen usando Fortify

Los starter kits iniciales de React/Vue estaban implementados sin Fortify. Sin embargo, cuando se hizo necesario soportar autenticación de dos factores (2FA), se adoptó Fortify, y toda la autenticación se reorientó hacia esta base. Al estar diseñado como «independiente del frontend», Fortify se combina bien con los starter kits basados en Inertia y hoy sigue en uso.
Actualmente Fortify es el paquete oficial de autenticación de Laravel con más recorrido. Desde su aparición en 2020, ha ido cambiando de forma (Jetstream → starter kits actuales) manteniéndose en activo.

Composición del starter kit actual

En los starter kits de React/Vue, Fortify se configura en los siguientes archivos:
  • app/Providers/FortifyServiceProvider.php — registro de vistas, actions y rate limits.
  • config/fortify.php — funcionalidades habilitadas y configuración de autenticación.

Ajustes principales de 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,
        ]),
    ],
];
En los starter kits, las passkeys (Features::passkeys()) no vienen activadas por defecto. Para habilitarlas, añádelas al array features.

Configuración de FortifyServiceProvider

El FortifyServiceProvider del starter kit cumple tres funciones.

1. Configuración de las actions

private function configureActions(): void
{
    Fortify::resetUserPasswordsUsing(ResetUserPassword::class);
    Fortify::createUsersUsing(CreateNewUser::class);
}
La lógica de creación de usuarios y restablecimiento de contraseñas se personaliza en las clases colocadas en app/Actions/Fortify/. Allí se concentran la validación y el hashing.

2. Configuración de las vistas

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'));
}
Cada método de vista recibe una closure que devuelve un componente de Inertia. Un detalle importante es que se consulta el flag de la funcionalidad con Features::enabled() y se pasa a la vista.
En una aplicación Blade, en lugar de Inertia::render(...) se devuelve view('auth.login'). Si cambias de frontend, basta con modificar el FortifyServiceProvider y la lógica de autenticación no cambia.

3. Configuración del 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);
    });
}
  • Limitador login: limita por combinación de email + IP (protección contra fuerza bruta).
  • Limitador two-factor: limita por el ID de intento de login guardado en la sesión.
Debes registrar en RateLimiter::for() claves que coincidan con las de limiters en config/fortify.php.

Funcionalidades principales y rutas registradas

Resumen por funcionalidad de las principales rutas que registra Fortify.
FuncionalidadMétodoRuta
LoginGET/login
LoginPOST/login
LogoutPOST/logout
RegistroGET/register
RegistroPOST/register
Solicitud de restablecimiento de contraseñaGET / POST/forgot-password
Restablecimiento de contraseñaGET / POST/reset-password
Verificación de emailGET/email/verify
Reenvío del email de verificaciónPOST/email/verification-notification
Confirmación de contraseñaGET / POST/user/confirm-password
Activar 2FAPOST/user/two-factor-authentication
Challenge de 2FAGET / POST/two-factor-challenge
Login con passkeyGET / POST/passkeys/login
Gestión de passkeysGET / POST / DELETE/user/passkeys
Puedes ver las rutas registradas con php artisan route:list --name=fortify o simplemente con php artisan route:list.

Autenticación de dos factores (2FA)

En el starter kit está habilitado Features::twoFactorAuthentication(). Tanto confirm como confirmPassword están en true.
OpciónSignificado
confirmRequiere confirmar con un código de autenticación tras habilitar el 2FA.
confirmPasswordPide confirmar la contraseña antes de cambiar la configuración de 2FA.
Desde la pantalla de ajustes de 2FA, el usuario puede realizar las siguientes operaciones.
1

Activar 2FA

Envía una petición POST a /user/two-factor-authentication. Si tiene éxito, se guarda el estado two-factor-authentication-enabled en la sesión.
2

Consultar el código QR

Con una petición GET a /user/two-factor-qr-code se devuelve el SVG del QR que el usuario escaneará con su app de autenticación.
3

Confirmar con un código

Envía el código con una petición POST a /user/confirmed-two-factor-authentication y completa la configuración.
4

Guardar los códigos de recuperación

Con una petición GET a /user/two-factor-recovery-codes obtienes los códigos de recuperación; guárdalos en un lugar seguro.

Passkeys

Los passkeys se han añadido recientemente como una funcionalidad de Fortify. Se trata de una autenticación sin contraseña basada en WebAuthn, compatible con Face ID, Touch ID, Windows Hello y llaves de seguridad hardware.

Activación

Añádelo al array features de config/fortify.php.
'features' => [
    Features::registration(),
    Features::resetPasswords(),
    Features::emailVerification(),
    Features::twoFactorAuthentication([
        'confirm'         => true,
        'confirmPassword' => true,
    ]),
    Features::passkeys([
        'confirmPassword' => true,
    ]),
],
A continuación, añade el contrato PasskeyUser y el trait PasskeyAuthenticatable al modelo User.
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Fortify\Contracts\PasskeyUser;
use Laravel\Fortify\PasskeyAuthenticatable;

class User extends Authenticatable implements PasskeyUser
{
    use PasskeyAuthenticatable;
}
La configuración de WebAuthn se gestiona en la clave passkeys de 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,
],
Internamente, los passkeys de Fortify envuelven el paquete de Composer laravel/passkeys. No necesitas publicar el archivo de configuración de laravel/passkeys; la clave passkeys de config/fortify.php tiene prioridad.
Para más detalles sobre passkeys (el cliente JS @laravel/passkeys, helpers de React/Vue/Svelte, etc.), consulta también la investigación inicial de passkeys.

Páginas relacionadas

Guard de autenticación personalizado

Explica cómo crear un guard de autenticación personalizado implementando las interfaces Guard y StatefulGuard.

Documentación oficial: Laravel Fortify

Consulta la documentación oficial para instalación, funcionalidades completas y personalización.
Última modificación el 13 de julio de 2026