Laravel Fortify, qué es, cuando usar y primeros pasos para crear un sistema de autenticación flexible
Índice de contenido
- Laravel Fortify: qué es, cuándo usarlo y cómo crear un sistema de autenticación flexible en Laravel
- ¿Qué es Laravel Fortify y por qué es “headless”?
- Qué significa realmente que Fortify no tenga frontend
- ¿Cuándo tiene sentido usar Laravel Fortify (y cuándo no)?
- Situaciones donde Fortify no aporta ventajas
- Laravel Fortify vs Breeze vs Jetstream
- Nivel de intrusión y mantenimiento
- Laravel Fortify y Laravel Sanctum: cómo se complementan
- Instalación y configuración inicial de Laravel Fortify
- Configuración de features en Laravel Fortify
- Usar Laravel Fortify sin vistas: control total del frontend
- Usar Laravel Fortify en APIs y aplicaciones SPA
- Si Fortify se usa solo como backend:
- Redirecciones que conviene modificar
- Middlewares de Fortify que debes entender (y ajustar)
- RedirectIfAuthenticated
- Authenticate middleware
- Problemas comunes al usar Laravel Fortify (y cómo solucionarlos)
- Error 401 aun estando autenticado
- Errores de CORS
- Personalización avanzada de Laravel Fortify
- Ejemplo de uso y funcionamiento
- Login
- Registrar
- Conclusión: por qué Laravel Fortify es ideal para autenticación personalizada
Laravel Fortify es un paquete para la autenticación, registro, recuperación de contraseña, verificación de correo electrónico y más, en pocas palabras, permite realizar las mismas funcionalidades que Laravel Breeze que empleamos antes, pero la diferencia radica en que no es tan intrusivo, cuando instalamos Laravel Breeze el mismo instala Tailwind.css y género varios componentes, controladores, vistas y rutas asociadas.
En el caso de Laravel Fortify no es así y nos provee las mismas características pero sin necesidad de la interfaz gráfica, por lo tanto, es particularmente útil cuidando quieres desarrollar un backend de autenticación más personalizado que el que nos ofrece Breeze; es importante señalar a que si estás empleando Laravel Breeze o alguna solución similar no es necesario utilizar Laravel Fortify.
Otra posible comparación que pueda que estés realizando es con Sanctum, Laravel Fortify y Laravel Sanctum no son paquetes mutuamente excluyentes ni competidores si no, se pueden emplear en un mismo proyecto en caso de que se lo requiere, Laravel Sanctum solo se ocupa de administrar tokens API y autenticar a los usuarios existentes mediante cookies o tokens de sesión.
Sanctum no proporciona ninguna ruta que maneje el registro de usuarios, el restablecimiento de contraseñas, etc, en pocas palabras Sanctum está enfocado en la autenticación de una Api Rest y Laravel Fortify para una aplicación web tradicional.
Laravel Fortify: qué es, cuándo usarlo y cómo crear un sistema de autenticación flexible en Laravel
Cuando estás construyendo una aplicación con Laravel y llega el momento de implementar la autenticación, normalmente aparecen los mismos nombres: Breeze, Jetstream, Sanctum… y, si necesitas algo más flexible, Laravel Fortify.
En mi caso, Fortify empezó a tener sentido cuando necesitaba control total sobre el frontend, sin que el framework me impusiera vistas, estilos o componentes que luego iba a terminar desmontando. Si alguna vez has instalado Breeze “solo para probar” y después has pasado más tiempo borrando código que usándolo, probablemente entiendas por qué Fortify existe.
En este artículo te explico qué es Laravel Fortify, cuándo usarlo (y cuándo no), cómo configurarlo correctamente y qué problemas reales suelen aparecer cuando lo llevas a producción, especialmente en APIs y SPAs.
¿Qué es Laravel Fortify y por qué es “headless”?
Laravel Fortify es un backend de autenticación sin interfaz gráfica.
Cuando se dice que es headless, significa exactamente esto: Fortify se encarga de toda la lógica de autenticación, pero no incluye vistas, estilos ni componentes de UI.
Con Fortify tienes, entre otras cosas:
- Login y logout
- Registro de usuarios
- Recuperación de contraseña
- Verificación de email
- Confirmación de contraseña
- Rate limiting
- Autenticación en dos pasos (2FA)
Todo eso ya implementado, probado y mantenido por el equipo de Laravel… pero sin decidir por ti cómo debe verse el formulario de login.
Qué significa realmente que Fortify no tenga frontend
Esto es clave:
Fortify sí define rutas y controladores, pero no define vistas. Si intentas acceder a /login sin haber configurado nada, obtendrás un error del tipo:
Target [Laravel\Fortify\Contracts\LoginViewResponse] is not instantiable.
No es un bug. Es Fortify diciéndote: “dime tú cómo quieres que sea tu UI”.
Esto es exactamente lo que lo hace tan potente cuando trabajas con:
- Blade personalizado
- Vue / React
- SPAs
- APIs puras
¿Cuándo tiene sentido usar Laravel Fortify (y cuándo no)?
Aquí es donde mucha gente se equivoca.
Casos en los que Fortify encaja mejor que Breeze
- Laravel Fortify tiene todo el sentido cuando:
- Quieres control total del frontend
- No quieres Tailwind, componentes ni scaffolding automático
- Estás construyendo una SPA o una API
- Necesitas personalizar flujos de autenticación
- Te importa la mantenibilidad a medio/largo plazo
En proyectos reales, Fortify me ha resultado especialmente útil cuando el backend y el frontend evolucionan de forma independiente.
Situaciones donde Fortify no aporta ventajas
Fortify no es la mejor opción si:
- Quieres algo rápido y visual desde el minuto uno
- Estás prototipando
- No te importa el frontend por defecto
- Tu app es pequeña y no va a crecer
En esos casos, Laravel Breeze es más que suficiente y probablemente más productivo.
Laravel Fortify vs Breeze vs Jetstream
Diferencias en arquitectura y control del frontend
- Breeze
- Autenticación + vistas + Tailwind + controladores listos para usar.
Muy cómodo, pero intrusivo.
- Autenticación + vistas + Tailwind + controladores listos para usar.
- Jetstream
- Más completo aún (teams, perfiles, etc.).
Ideal para apps grandes, pero opinionado, ya no te recomiendo usar Jetstream al ya no ser la oficial.
- Más completo aún (teams, perfiles, etc.).
- Fortify
- Solo backend. Tú decides todo lo demás.
Yo suelo resumirlo así:
Breeze y Jetstream te dan una casa amueblada; Fortify te da los cimientos.
Nivel de intrusión y mantenimiento
Uno de los problemas de Breeze es que, cuando el proyecto crece, acabas peleándote con el scaffolding. Con Fortify, eso no pasa: solo consumes endpoints y lógica.
Laravel Fortify y Laravel Sanctum: cómo se complementan
Este es un punto donde hay mucha confusión.
Laravel Fortify y Laravel Sanctum no compiten.
- Fortify:
- Autenticación web (login, registro, reset, 2FA…)
- Sanctum:
- Autenticación de APIs (cookies, tokens)
En muchos proyectos reales he usado Fortify + Sanctum juntos:
- Fortify para gestionar usuarios
- Sanctum para autenticar peticiones API
Si estás construyendo una SPA, esta combinación es prácticamente estándar.
Instalación y configuración inicial de Laravel Fortify
Para instalar Laravel Fortify empleamos el siguiente comando:
$ composer require laravel/fortifyEl siguiente paso es ejecutar el comando de instalación:
$ php artisan fortify:installEste comando generará las migraciones, archivo de configuración, provide entre otros.
Ejecutamos las migraciones:
$ php artisan migrateEsto genera:
- Migraciones
- config/fortify.php
- FortifyServiceProvider
- Actions para login, registro, etc.
A partir de aquí, Fortify ya funciona… aunque todavía no “se ve”.
Y con esto, ya podemos emplear Laravel Fortify.
Configuración de features en Laravel Fortify
Una de las cosas que más me gusta de Fortify es que puedes activar solo lo que necesitas mediante características que podemos habilitar o deshabilitar a gusto:
config\fortify.php
'features' => [
Features::registration(),
Features::resetPasswords(),
Features::emailVerification(),
],Si no quieres verificación por email, simplemente la comentas.
Este enfoque modular hace que Fortify se adapte muy bien a proyectos reales, donde no siempre necesitas todo desde el principio.
Las mismas permite des/habilitar la opción de registro, reiniciar la contraseña y verificación por emails respectivamente, en caso de que no quieras emplear alguna o varias de estas opciones, simplemente la debes de comentar, por ejemplo, si quieres desactivar la verificación por email:
'features' => [
Features::registration(),
Features::resetPasswords(),
// Features::emailVerification(),
],Usar Laravel Fortify sin vistas: control total del frontend
Si visitas /login o /register sin configurar nada, Fortify falla a propósito. Eso te obliga a decidir:
- ¿Blade?
- ¿Vue?
- ¿React?
- ¿SPA externa?
Cuando necesito Blade simple, suelo definir las vistas en el FortifyServiceProvider:
Fortify::loginView(function () {
return view('auth.login');
});Lo mismo para el registro. Fortify no impone nada, solo espera que tú lo hagas.
Usar Laravel Fortify en APIs y aplicaciones SPA
Desactivar vistas en un backend puro
Si Fortify se usa solo como backend:
'views' => false,Esto evita comportamientos pensados para aplicaciones web tradicionales.
Redirecciones que conviene modificar
Uno de los problemas más comunes que me encontré es la redirección automática a /home cuando un usuario ya está autenticado.
Para una API, esto no tiene ningún sentido.
La solución pasa por adaptar middlewares como RedirectIfAuthenticated para devolver JSON cuando la request es AJAX.
Middlewares de Fortify que debes entender (y ajustar)
RedirectIfAuthenticated
Por defecto, redirige. En APIs, esto suele romper flujos.
Detectar $request->expectsJson() y devolver una respuesta clara evita muchos dolores de cabeza.
Authenticate middleware
Otro ajuste típico es redirigir al frontend correcto cuando el usuario no está autenticado, algo fundamental cuando backend y frontend viven en dominios distintos.
Problemas comunes al usar Laravel Fortify (y cómo solucionarlos)
Error 401 aun estando autenticado
Muy habitual cuando trabajas con Sanctum. Normalmente se debe a:
- SANCTUM_STATEFUL_DOMAINS mal configurado
- SESSION_DOMAIN incorrecto o innecesario
En más de un proyecto, el problema era simplemente haber incluido http:// donde no tocaba.
Errores de CORS
Otro clásico.
Revisa siempre:
- config/cors.php
- allowed_origins
- rutas incluidas en paths
Personalización avanzada de Laravel Fortify
Fortify permite ir mucho más allá:
- Rate limiting personalizado
- Cambiar username por email o teléfono
- Flujos de autenticación propios
- 2FA con TOTP o incluso SMS
He tenido casos donde el 2FA por defecto no encajaba en UX, y Fortify permite sobrescribir prácticamente todo sin hacks.
Ejemplo de uso y funcionamiento
Para ejemplificar su uso, si hacemos un:
$ php artisan r:lVeremos todas las rutas generadas por Fortify:
GET|HEAD register ............................................ register › Laravel\Fortify › RegisteredUserController@create
POST register ........................................................ Laravel\Fortify › RegisteredUserController@store
POST reset-password ................................... password.update › Laravel\Fortify › NewPasswordController@store
GET|HEAD reset-password/{token} ........................... password.reset › Laravel\Fortify › NewPasswordController@create
GET|HEAD two-factor-challenge ......... two-factor.login › Laravel\Fortify › TwoFactorAuthenticatedSessionController@create
POST two-factor-challenge ............................. Laravel\Fortify › TwoFactorAuthenticatedSessionController@store
GET|HEAD up ...............................................................................................................
GET|HEAD user/confirm-password ....................................... Laravel\Fortify › ConfirmablePasswordController@show
POST user/confirm-password ................... password.confirm › Laravel\Fortify › ConfirmablePasswordController@store
GET|HEAD user/confirmed-password-status .. password.confirmation › Laravel\Fortify › ConfirmedPasswordStatusController@show
POST user/confirmed-two-factor-authentication two-factor.confirm › Laravel\Fortify › ConfirmedTwoFactorAuthenticationC…
PUT user/password ................................. user-password.update › Laravel\Fortify › PasswordController@update
PUT user/profile-information . user-profile-information.update › Laravel\Fortify › ProfileInformationController@update
POST user/two-factor-authentication ..... two-factor.enable › Laravel\Fortify › TwoFactorAuthenticationController@store
DELETE user/two-factor-authentication .. two-factor.disable › Laravel\Fortify › TwoFactorAuthenticationController@destroy
GET|HEAD user/two-factor-qr-code .................... two-factor.qr-code › Laravel\Fortify › TwoFactorQrCodeController@show
GET|HEAD user/two-factor-recovery-codes ........ two-factor.recovery-codes › Laravel\Fortify › RecoveryCodeController@index
POST user/two-factor-recovery-codes .................................... Laravel\Fortify › RecoveryCodeController@store
GET|HEAD user/two-factor-secret-key ........... two-factor.secret-key › Laravel\Fortify › TwoFactorSecretKeyController@showSi ingresamos a la de login, veremos un error como el siguiente:
http://larafirstepspackages.test/login
Target [Laravel\Fortify\Contracts\LoginViewResponse] is not instantiable.Ya que, como comentamos antes, no contamos con páginas o pantallas listas como en Breeze sí no, debemos de crearlas de manera manual (o usarlas con otras tecnologías como consumir estas rutas mediante una app en Vue).
Si comentas el módulo de registrar:
config\fortify.php
// Features::registration(),E intentas ir a la ruta:
http://larafirstepspackages.test/register
Verás que devuelve una página de 404 ya que, acabamos de deshabilitar la acción para registrar usuarios.
Si exploras el objeto:
FortifyVeremos muchas opciones que podemos personalizar de Fortify; si revisamos el archivo de:
app\Providers\FortifyServiceProvider.php
Veremos todas las acciones de Fortify que podemos personalizar, como el tiempo de bloqueo tras logins fallidos:
RateLimiter::for('login', function (Request $request) {
***Login
Por ejemplo, podemos especificar la vista para el login:
class FortifyServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
//
}
public function boot(): void
{
***
Fortify::loginView(function(){
return view('auth.login');
});
}
}Y su vista:
resources\views\auth\login.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
@if ($errors->any())
@foreach ($errors->all() as $e)
<div>
{{ $e }}
</div>
@endforeach
@endif
<form action="" method="post">
@csrf
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" value="Send">
</form>
</body>
</html>Registrar
O para registrarse:
class FortifyServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
//
}
public function boot(): void
{
***
Fortify::registerView(function(){
return view('auth.register');
});
}
}Creemos una vista muy sencilla como las siguiente:
resources\views\auth\register.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
@if ($errors->any())
@foreach ($errors->all() as $e)
<div>
{{ $e }}
</div>
@endforeach
@endif
<form action="" method="post">
@csrf
<input type="text" name="name" placeholder="name">
<input type="email" name="email">
<input type="password" name="password" >
<input type="submit" value="Send">
</form>
</body>
</html>Al ingresar a las rutas correspondientes:
http://larafirstepspackages.test/login
http://larafirstepspackages.test/register
Verás el sistema completo para el login y registrarse provisto por Fortify; estas son solamente algunas acciones que tenemos disponibles, explorar su su uso mediante los ejemplo anteriores para que se entienda de manera práctica el funcionamiento del paquete.
Ya con esto, queda por parte del lector explorar el resto de las funcionalidades para que puedas emplearlos en tus proyectos que requieran emplear Fortify para crear un sistema de autenticación completamente personalizado en vez de Breeze:
https://laravel.com/docs/master/fortify
Preguntas frecuentes sobre Laravel Fortify
- ¿Laravel Fortify incluye frontend?
- No. Es completamente headless.
- ¿Se puede usar Fortify con Vue o React?
- Sí, y es uno de sus mejores casos de uso.
- ¿Fortify reemplaza a Sanctum?
- No. Se complementan.
- ¿Es buena idea usar Fortify en proyectos pequeños?
- Solo si sabes que el proyecto va a crecer o necesita personalización.
Conclusión: por qué Laravel Fortify es ideal para autenticación personalizada
Laravel Fortify no es para todos los proyectos, pero cuando encaja, encaja muy bien.
Si necesitas:
- Flexibilidad
- Control
- Backend limpio
- Integración con SPAs o APIs
Fortify es una de las mejores decisiones que puedes tomar en Laravel.
No te da una UI bonita, pero te da algo más importante: libertad.
Acepto recibir anuncios de interes sobre este Blog.
Laravel Fortify es un paquete para la autenticación, registro, recuperación de contraseña, verificación de correo electrónico y más, en pocas palabras, permite realizar las mismas funcionalidades que Laravel Breeze que empleamos antes, pero sin parte gráfica.