> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Laravel Fortify y los starter kits

> Explica el diseño interno de Laravel Fortify, un backend de autenticación independiente del frontend. Cubre por qué los starter kits actuales usan Fortify, la configuración de FortifyServiceProvider y cómo habilitar 2FA y passkeys.

## Qué es Fortify

[Laravel Fortify](https://github.com/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.

<Info>
  Fortify no tiene UI. Funciona cuando un starter kit o tu propia UI envía peticiones a las rutas de Fortify.
</Info>

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

```mermaid theme={null}
timeline
    title Evolución de Fortify
    2020 Laravel 8 : Aparece junto con Jetstream
               : Fortify se instala automáticamente como base de Jetstream
    2020 Laravel 8 : Aparece Breeze (sin Fortify)
               : Se independiza como scaffold sencillo de autenticación
    2025 Renovación de los starter kits : Los starter kits de React/Vue necesitan soporte 2FA
                         : Se reintroduce Fortify → toda la autenticación pasa a estar basada en Fortify
    2026 Soporte de passkeys : Se añade la funcionalidad de Passkeys a Fortify
```

### 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.

<Info>
  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.
</Info>

## 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`

```php theme={null}
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

```php theme={null}
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

```php theme={null}
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.

<Info>
  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.
</Info>

### 3. Configuración del rate limiting

```php theme={null}
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.

| Funcionalidad                               | Método                    | Ruta                               |
| ------------------------------------------- | ------------------------- | ---------------------------------- |
| Login                                       | `GET`                     | `/login`                           |
| Login                                       | `POST`                    | `/login`                           |
| Logout                                      | `POST`                    | `/logout`                          |
| Registro                                    | `GET`                     | `/register`                        |
| Registro                                    | `POST`                    | `/register`                        |
| Solicitud de restablecimiento de contraseña | `GET` / `POST`            | `/forgot-password`                 |
| Restablecimiento de contraseña              | `GET` / `POST`            | `/reset-password`                  |
| Verificación de email                       | `GET`                     | `/email/verify`                    |
| Reenvío del email de verificación           | `POST`                    | `/email/verification-notification` |
| Confirmación de contraseña                  | `GET` / `POST`            | `/user/confirm-password`           |
| Activar 2FA                                 | `POST`                    | `/user/two-factor-authentication`  |
| Challenge de 2FA                            | `GET` / `POST`            | `/two-factor-challenge`            |
| Login con passkey                           | `GET` / `POST`            | `/passkeys/login`                  |
| Gestión de passkeys                         | `GET` / `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ón            | Significado                                                              |
| ----------------- | ------------------------------------------------------------------------ |
| `confirm`         | Requiere confirmar con un código de autenticación tras habilitar el 2FA. |
| `confirmPassword` | Pide 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.

<Steps>
  <Step title="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.
  </Step>

  <Step title="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.
  </Step>

  <Step title="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.
  </Step>

  <Step title="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.
  </Step>
</Steps>

## 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`.

```php theme={null}
'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`.

```php theme={null}
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`.

```php theme={null}
'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,
],
```

<Info>
  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.
</Info>

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](/es/blog/passkeys-introduction).

## Páginas relacionadas

<Card title="Guard de autenticación personalizado" icon="shield" href="/es/advanced/custom-auth-guard">
  Explica cómo crear un guard de autenticación personalizado implementando las interfaces Guard y StatefulGuard.
</Card>

<Card title="Documentación oficial: Laravel Fortify" icon="book-open" href="https://laravel.com/docs/fortify">
  Consulta la documentación oficial para instalación, funcionalidades completas y personalización.
</Card>


## Related topics

- [Laravel Maestro — Orquestador de desarrollo de starter kits](/es/blog/maestro-introduction.md)
- [Cómo crear un starter kit de Laravel](/es/advanced/starter-kit-creation.md)
- [Laravel Chisel — Biblioteca de scripts de post-instalación para starter kits](/es/blog/chisel-introduction.md)
- [Resumen de las novedades de Laravel 13](/es/blog/laravel-13-new-features.md)
- [Presentación de Laravel Wayfinder](/es/blog/wayfinder-introduction.md)
