1. Seguridad
  2. Autenticación

Únete a nuestra comunidad de Telegram @webblend!

Aquí encontrarás fragmentos de código de Laravel y consejos útiles sobre desarrollo web.

Introducción

Muchas aplicaciones web ofrecen una forma para que sus usuarios se autentiquen con la aplicación e "inicien sesión". Implementar esta función en aplicaciones web puede ser una tarea compleja y potencialmente arriesgada. Por esta razón, Laravel se esfuerza por proporcionarte las herramientas necesarias para implementar la autenticación de manera rápida, segura y fácil.

En su núcleo, las instalaciones de autenticación de Laravel se componen de "guards" (guardias) y "providers" (proveedores). Los guardias definen cómo se autentican los usuarios para cada solicitud. Por ejemplo, Laravel incluye un guardia session que mantiene el estado utilizando almacenamiento de sesión y cookies.

El archivo de configuración de autenticación de tu aplicación se encuentra en config/auth.php. Este archivo contiene varias opciones documentadas para ajustar el comportamiento de los servicios de autenticación de Laravel.

La configuración de autenticación de tu aplicación se encuentra en el archivo config/auth.php. Este archivo contiene varias opciones bien documentadas para ajustar el comportamiento de los servicios de autenticación de Laravel.

Nota No debes confundir guards y providers con "roles" y "permisos". Para obtener más información sobre cómo autorizar acciones de usuario mediante permisos, consulta la documentación de autorización.

Kits de inicio

¿Quieres comenzar rápido? Instala un kit de inicio de aplicación Laravel en una nueva aplicación Laravel. Después de migrar tu base de datos, navega en tu navegador a /register o a cualquier otra URL asignada a tu aplicación. ¡Los kits de inicio se encargarán de generar todo el sistema de autenticación por ti!

Incluso si decides no utilizar un kit de inicio en tu aplicación Laravel final, instalar el kit de inicio Laravel Breeze puede ser una maravillosa oportunidad para aprender cómo implementar todas las funciones de autenticación de Laravel en un proyecto Laravel real. Dado que Laravel Breeze crea controladores, rutas y vistas de autenticación por ti, puedes examinar el código dentro de estos archivos para aprender cómo se pueden implementar las funciones de autenticación de Laravel.

Consideraciones de la base de datos

De forma predeterminada, Laravel incluye un modelo Eloquent App\Models\User en tu directorio app/Models. Este modelo se puede usar con el controlador de autenticación Eloquent predeterminado. Si tu aplicación no utiliza Eloquent, puedes usar el proveedor de autenticación database que utiliza el generador de consultas de Laravel.

Al construir el esquema de la base de datos para el modelo App\Models\User, asegúrate de que la columna de la contraseña tenga al menos 60 caracteres de longitud. Por supuesto, la migración de la tabla users que se incluye en las nuevas aplicaciones Laravel ya crea una columna que supera esta longitud.

Además, verifica que tu tabla users (o similar) contenga una columna remember_token nula y de tipo cadena con 100 caracteres. Esta columna se utilizará para almacenar un token para los usuarios que seleccionen la opción "recordarme" al iniciar sesión en tu aplicación. Nuevamente, la migración de la tabla users que se incluye en las nuevas aplicaciones Laravel ya contiene esta columna.

Descripción general del ecosistema

Laravel ofrece varios paquetes relacionados con la autenticación. Antes de continuar, revisaremos el ecosistema general de autenticación en Laravel y discutiremos el propósito previsto de cada paquete.

Primero, considera cómo funciona la autenticación. Cuando se utiliza un navegador web, un usuario proporcionará su nombre de usuario y contraseña a través de un formulario de inicio de sesión. Si estas credenciales son correctas, la aplicación almacenará información sobre el usuario autenticado en la sesión del usuario. Una cookie emitida al navegador contiene el ID de la sesión para que las solicitudes subsiguientes a la aplicación puedan asociar al usuario con la sesión correcta. Después de recibir la cookie de sesión, la aplicación recuperará los datos de la sesión basados en el ID de la sesión, notará que la información de autenticación se ha almacenado en la sesión y considerará al usuario como "autenticado".

Cuando un servicio remoto necesita autenticarse para acceder a una API, normalmente no se utilizan cookies para la autenticación porque no hay un navegador web. En su lugar, el servicio remoto envía un token de API a la API en cada solicitud. La aplicación puede validar el token entrante contra una tabla de tokens de API válidos y "autenticar" la solicitud como si fuera realizada por el usuario asociado con ese token de API.

Servicios de autenticación de navegador integrados en Laravel

Laravel incluye servicios integrados de autenticación y sesión a los que generalmente se accede mediante las fachadas Auth y Session. Estas funciones proporcionan autenticación basada en cookies para solicitudes iniciadas desde navegadores web. Ofrecen métodos que te permiten verificar las credenciales de un usuario y autenticarlo. Además, estos servicios almacenarán automáticamente los datos de autenticación adecuados en la sesión del usuario y emitirán la cookie de sesión del usuario. Una discusión sobre cómo utilizar estos servicios se encuentra en esta documentación.

Application Starter Kits

Como se discute en esta documentación, puedes interactuar con estos servicios de autenticación de forma manual para construir la capa de autenticación de tu aplicación. Sin embargo, para ayudarte a comenzar más rápidamente, hemos lanzado paquetes gratuitos que proporcionan un andamiaje sólido y moderno de toda la capa de autenticación. Estos paquetes son Laravel Breeze, Laravel Jetstream y Laravel Fortify.

Laravel Breeze es una implementación simple y mínima de todas las funciones de autenticación de Laravel, que incluye inicio de sesión, registro, restablecimiento de contraseña, verificación de correo electrónico y confirmación de contraseña. La capa de vista de Laravel Breeze está compuesta por simples plantillas Blade con estilo de Tailwind CSS. Para comenzar, consulta la documentación sobre kits de inicio de aplicaciones de Laravel.

Laravel Fortify es un backend de autenticación sin cabeza para Laravel que implementa muchas de las funciones que se encuentran en esta documentación, incluida la autenticación basada en cookies, así como otras funciones como la autenticación de dos factores y la verificación de correo electrónico. Fortify proporciona el backend de autenticación para Laravel Jetstream o se puede utilizar de forma independiente en combinación con Laravel Sanctum para proporcionar autenticación para una SPA que necesita autenticarse con Laravel.

Laravel Jetstream es un sólido kit de inicio de aplicaciones que consume y expone los servicios de autenticación de Laravel Fortify con una interfaz de usuario moderna y hermosa, alimentada por Tailwind CSS, Livewire y / o Inertia. Laravel Jetstream incluye soporte opcional para la autenticación de dos factores, soporte para equipos, gestión de sesiones de navegador, gestión de perfiles e integración incorporada con Laravel Sanctum para ofrecer autenticación de token de API. Las ofertas de autenticación de API de Laravel se discuten a continuación.

Servicios de autenticación de API de Laravel

Laravel proporciona dos paquetes opcionales para ayudarte a gestionar tokens de API y autenticar solicitudes realizadas con tokens de API: Passport y Sanctum. Ten en cuenta que estas bibliotecas y los servicios de autenticación basados en cookies integrados de Laravel no son mutuamente excluyentes. Estas bibliotecas se centran principalmente en la autenticación mediante token de API, mientras que los servicios de autenticación integrados de Laravel se centran en la autenticación basada en cookies para navegadores web. Muchas aplicaciones utilizarán tanto los servicios de autenticación basados en cookies integrados de Laravel como uno de los paquetes de autenticación de API de Laravel.

Passport

Passport es un proveedor de autenticación OAuth2 que ofrece una variedad de "tipos de concesión" OAuth2 que te permiten emitir varios tipos de tokens. En general, este es un paquete robusto y complejo para la autenticación de API. Sin embargo, la mayoría de las aplicaciones no requieren las funciones complejas que ofrece la especificación OAuth2, lo que puede ser confuso tanto para los usuarios como para los desarrolladores. Además, históricamente, los desarrolladores han estado confundidos acerca de cómo autenticar aplicaciones SPA o aplicaciones móviles mediante proveedores de autenticación OAuth2 como Passport.

Sanctum

En respuesta a la complejidad de OAuth2 y a la confusión de los desarrolladores, nos propusimos construir un paquete de autenticación más simple y simplificado que pudiera manejar tanto las solicitudes web de primera parte desde un navegador web como las solicitudes de API a través de tokens. Este objetivo se logró con el lanzamiento de Laravel Sanctum, que debe considerarse el paquete de autenticación preferido y recomendado para aplicaciones que ofrecerán una interfaz de usuario web de primera parte además de una API, o que será impulsada por una aplicación de página única (SPA) que existe de manera independiente de la aplicación Laravel backend, o aplicaciones que ofrecen un cliente móvil.

Laravel Sanctum es un paquete de autenticación web / API híbrido que puede gestionar todo el proceso de autenticación de tu aplicación. Esto es posible porque cuando las aplicaciones basadas en Sanctum reciben una solicitud, Sanctum primero determinará si la solicitud incluye una cookie de sesión que hace referencia a una sesión autenticada. Sanctum logra esto llamando a los servicios de autenticación integrados de Laravel que discutimos anteriormente. Si la solicitud no se está autenticando mediante una cookie de sesión, Sanctum examinará la solicitud en busca de un token de API. Si hay un token de API presente, Sanctum autenticará la solicitud utilizando ese token. Para obtener más información sobre este proceso, consulta la documentación de "cómo funciona" de Sanctum.

Laravel Sanctum es el paquete API que hemos elegido incluir con el kit de inicio de aplicación Laravel Jetstream porque creemos que es la mejor opción para la mayoría de las necesidades de autenticación de aplicaciones web.

Resumen y elección de su conjunto de tecnologías

En resumen, si tu aplicación será accedida mediante un navegador y estás construyendo una aplicación monolítica de Laravel, tu aplicación utilizará los servicios de autenticación integrados de Laravel.

A continuación, si tu aplicación ofrece una API que será consumida por terceros, deberás elegir entre Passport o Sanctum para proporcionar autenticación con token API para tu aplicación. En general, se debe preferir Sanctum siempre que sea posible, ya que es una solución simple y completa para la autenticación de API, autenticación de SPA y autenticación móvil, incluido el soporte para "scopes" o "abilities".

Si estás construyendo una aplicación de página única (SPA) que será impulsada por un backend de Laravel, debes usar Laravel Sanctum. Al usar Sanctum, deberás implementar manualmente tus propias rutas de autenticación del backend o utilizar Laravel Fortify como un servicio de backend de autenticación sin cabeza que proporciona rutas y controladores para funciones como registro, restablecimiento de contraseña, verificación de correo electrónico y más.

Passport puede ser elegido cuando tu aplicación necesita absolutamente todas las funciones proporcionadas por la especificación OAuth2.

Y si deseas empezar rápidamente, nos complace recomendar Laravel Breeze como una manera rápida de iniciar una nueva aplicación de Laravel que ya utiliza nuestra pila de autenticación preferida de los servicios de autenticación integrados de Laravel y Laravel Sanctum.

Inicio rápido de autenticación

Advertencia Esta parte de la documentación trata sobre la autenticación de usuarios a través de los kits de inicio de aplicaciones de Laravel, que incluyen un andamiaje de interfaz de usuario para ayudarte a comenzar rápidamente. Si deseas integrarte directamente con los sistemas de autenticación de Laravel, consulta la documentación sobre autenticación manual de usuarios.

Instalar un kit de inicio

Primero, debes instalar un kit de inicio de aplicación de Laravel. Nuestros kits de inicio actuales, Laravel Breeze y Laravel Jetstream, ofrecen puntos de partida bellamente diseñados para incorporar la autenticación en tu nueva aplicación de Laravel.

Laravel Breeze es una implementación mínima y sencilla de todas las funciones de autenticación de Laravel, incluido inicio de sesión, registro, restablecimiento de contraseña, verificación de correo electrónico y confirmación de contraseña. La capa de vista de Breeze está compuesta por simples plantillas Blade estilizadas con Tailwind CSS. Además, Breeze proporciona opciones de estructura basadas en Livewire o Inertia, con la opción de usar Vue o React para el andamiaje basado en Inertia.

Laravel Jetstream es un kit de inicio de aplicación más robusto que incluye soporte para estructurar tu aplicación con Livewire o Inertia y Vue. Además, Jetstream cuenta con soporte opcional para autenticación de dos factores, equipos, gestión de perfiles, gestión de sesiones de navegador, soporte de API a través de Laravel Sanctum, eliminación de cuentas y más.

Recuperar el usuario autenticado

Después de instalar un kit de inicio de autenticación y permitir que los usuarios se registren y autentiquen con tu aplicación, a menudo necesitarás interactuar con el usuario autenticado actual. Mientras manejas una solicitud entrante, puedes acceder al usuario autenticado a través del método user de la fachada Auth:

use Illuminate\Support\Facades\Auth;
 
// Obtener el usuario autenticado actualmente...
$user = Auth::user();
 
// Obtener el ID del usuario autenticado actualmente...
$id = Auth::id();

Alternativamente, una vez que un usuario está autenticado, puedes acceder al usuario autenticado a través de una instancia de Illuminate\Http\Request. Recuerda que las clases con tipo serán inyectadas automáticamente en tus métodos de controlador. Al especificar el tipo de la clase Illuminate\Http\Request, puedes obtener acceso conveniente al usuario autenticado desde cualquier método de controlador en tu aplicación a través del método user de la solicitud:

<?php
 
namespace App\Http\Controllers;
 
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
 
class FlightController extends Controller
{
/**
* Actualizar la información del vuelo para un vuelo existente.
*/
public function update(Request $request): RedirectResponse
{
$user = $request->user();
 
// ...
 
return redirect('/flights');
}
}

Determinar si el usuario actual está autenticado

Para determinar si el usuario que realiza la solicitud HTTP entrante está autenticado, puedes usar el método check en la fachada Auth. Este método devolverá true si el usuario está autenticado:

use Illuminate\Support\Facades\Auth;
 
if (Auth::check()) {
// El usuario ha iniciado sesión...
}

Nota Aunque es posible determinar si un usuario está autenticado utilizando el método check, normalmente usarás un middleware para verificar que el usuario esté autenticado antes de permitir el acceso a ciertas rutas/controladores. Para obtener más información, consulta la documentación sobre proteger rutas.

Protección de rutas

El middleware de ruta se puede usar para permitir solo a usuarios autenticados acceder a una ruta específica. Laravel incluye un middleware llamado auth, que hace referencia a la clase Illuminate\Auth\Middleware\Authenticate. Dado que este middleware ya está registrado en el kernel HTTP de tu aplicación, lo único que necesitas hacer es adjuntar el middleware a la definición de la ruta:

Route::get('/flights', function () {
// Solo los usuarios autenticados pueden acceder a esta ruta...
})->middleware('auth');

Redirigir a usuarios no autenticados

Cuando el middleware auth detecta a un usuario no autenticado, redirigirá al usuario a la ruta login con nombre. Puedes modificar este comportamiento actualizando la función redirectTo en el archivo app/Http/Middleware/Authenticate.php de tu aplicación:

use Illuminate\Http\Request;
 
/**
* Obtener la ruta a la que se debe redirigir al usuario.
*/
protected function redirectTo(Request $request): string
{
return route('login');
}

Especificación de un guardia

Al adjuntar el middleware auth a una ruta, también puedes especificar qué "guardia" se debe usar para autenticar al usuario. La guardia especificada debe coincidir con una de las claves en el array guards de tu archivo de configuración auth.php:

Route::get('/flights', function () {
// Solo los usuarios autenticados pueden acceder a esta ruta...
})->middleware('auth:admin');

Limitación de inicio de sesión

Si estás utilizando los kits de inicio Laravel Breeze o Laravel Jetstream, se aplicará automáticamente un límite de velocidad a los intentos de inicio de sesión. De forma predeterminada, el usuario no podrá iniciar sesión durante un minuto si no proporciona las credenciales correctas después de varios intentos. La limitación se aplica de manera única a la dirección de correo electrónico / nombre de usuario del usuario y a su dirección IP.

Nota Si deseas limitar la velocidad de otras rutas en tu aplicación, consulta la documentación sobre límites de velocidad.

Autenticación manual de usuarios

No es obligatorio utilizar el andamiaje de autenticación incluido en los kits de inicio de aplicación de Laravel. Si decides no utilizar este andamiaje, deberás gestionar la autenticación de usuarios utilizando las clases de autenticación de Laravel directamente. ¡No te preocupes, es muy fácil!

Accederemos a los servicios de autenticación de Laravel a través de la fachada Auth, así que asegurémonos de importar la fachada Auth en la parte superior de la clase. A continuación, veamos el método attempt. El método attempt se utiliza normalmente para manejar intentos de autenticación desde el "formulario de inicio de sesión" de tu aplicación. Si la autenticación es exitosa, debes regenerar la sesión del usuario para evitar la fijación de sesiones:

<?php
 
namespace App\Http\Controllers;
 
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;
 
class LoginController extends Controller
{
/**
* Manejar un intento de autenticación.
*/
public function authenticate(Request $request): RedirectResponse
{
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
 
if (Auth::attempt($credentials)) {
$request->session()->regenerate();
 
return redirect()->intended('dashboard');
}
 
return back()->withErrors([
'email' => 'Las credenciales proporcionadas no coinciden con nuestros registros.',
])->onlyInput('email');
}
}

El método attempt acepta un array de pares clave / valor como su primer argumento. Los valores en el array se utilizarán para buscar al usuario en la tabla de tu base de datos. Así, en el ejemplo anterior, el usuario se recuperará por el valor de la columna email. Si se encuentra al usuario, se comparará la contraseña cifrada almacenada en la base de datos con el valor de password pasado al método a través del array. No debes cifrar el valor de password de la solicitud entrante, ya que el framework cifrará automáticamente el valor antes de compararlo con la contraseña cifrada en la base de datos. Se iniciará una sesión autenticada para el usuario si las dos contraseñas cifradas coinciden.

Recuerda que los servicios de autenticación de Laravel recuperarán usuarios de tu base de datos según la configuración de "proveedor" de tu guardia de autenticación. En el archivo de configuración predeterminado config/auth.php, se especifica el proveedor de usuario Eloquent y se le indica que utilice el modelo App\Models\User al recuperar usuarios. Puedes cambiar estos valores dentro de tu archivo de configuración según las necesidades de tu aplicación.

El método attempt devolverá true si la autenticación fue exitosa. De lo contrario, se devolverá false.

El método intended proporcionado por el redireccionador de Laravel redirigirá al usuario a la URL a la que intentaba acceder antes de ser interceptado por el middleware de autenticación. Puedes proporcionar una URI de reserva a este método en caso de que el destino previsto no esté disponible.

Especificar condiciones adicionales

Si lo deseas, también puedes agregar condiciones de consulta adicionales a la consulta de autenticación además del correo electrónico y la contraseña del usuario. Para lograr esto, simplemente agrega las condiciones de consulta al array pasado al método attempt. Por ejemplo, podemos verificar que el usuario esté marcado como "activo":

if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
// La autenticación fue exitosa...
}

Para condiciones de consulta más complejas, puedes proporcionar un cierre en tu array de credenciales. Este cierre se invocará con la instancia de la consulta, lo que te permite personalizar la consulta según las necesidades de tu aplicación:

use Illuminate\Database\Eloquent\Builder;
 
if (Auth::attempt([
'email' => $email,
'password' => $password,
fn (Builder $query) => $query->has('activeSubscription'),
])) {
// La autenticación fue exitosa...
}

Advertencia En estos ejemplos, email no es una opción obligatoria, simplemente se usa como ejemplo. Debes usar el nombre de columna que corresponda a un "nombre de usuario" en tu tabla de base de datos.

El método attemptWhen, que recibe un cierre como segundo argumento, se puede utilizar para realizar una inspección más extensa del usuario potencial antes de autenticar realmente al usuario. El cierre recibe al usuario potencial y debe devolver true o false para indicar si el usuario puede ser autenticado:

if (Auth::attemptWhen([
'email' => $email,
'password' => $password,
], function (User $user) {
return $user->isNotBanned();
})) {
// La autenticación fue exitosa...
}

Acceso a instancias específicas de guardias

A través del método guard de la fachada Auth, puedes especificar qué instancia de guardia te gustaría utilizar al autenticar al usuario. Esto te permite gestionar la autenticación para partes separadas de tu aplicación utilizando modelos o tablas de usuario completamente separados.

El nombre de la guardia pasado al método guard debe coincidir con una de las guardias configuradas en tu archivo de configuración auth.php:

if (Auth::guard('admin')->attempt($credentials)) {
// ...
}

Recordar usuarios

Muchas aplicaciones web ofrecen una casilla de verificación "recuérdame" en su formulario de inicio de sesión. Si deseas proporcionar la funcionalidad "recuérdame" en tu aplicación, puedes pasar un valor booleano como segundo argumento al método attempt.

Cuando este valor es true, Laravel mantendrá al usuario autenticado indefinidamente o hasta que cierre sesión manualmente. Tu tabla users debe incluir la columna de tipo string remember_token, que se utilizará para almacenar el token "recuérdame". La migración de la tabla users incluida en las nuevas aplicaciones Laravel ya incluye esta columna:

use Illuminate\Support\Facades\Auth;
 
if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) {
// Se está recordando al usuario...
}

Si tu aplicación ofrece funcionalidad "recuérdame", puedes utilizar el método viaRemember para determinar si el usuario autenticado actualmente fue autenticado usando la cookie "recuérdame":

use Illuminate\Support\Facades\Auth;
 
if (Auth::viaRemember()) {
// ...
}

Otros métodos de autenticación

Autenticar una instancia de usuario

Si necesitas establecer una instancia de usuario existente como el usuario autenticado actualmente, puedes pasar la instancia de usuario al método login de la fachada Auth. La instancia de usuario proporcionada debe ser una implementación del contrato Illuminate\Contracts\Auth\Authenticatable. El modelo App\Models\User incluido con Laravel ya implementa esta interfaz. Este método de autenticación es útil cuando ya tienes una instancia de usuario válida, como justo después de que un usuario se registra en tu aplicación:

use Illuminate\Support\Facades\Auth;
 
Auth::login($user);

Puedes pasar un valor booleano como segundo argumento al método login. Este valor indica si se desea la funcionalidad "recuérdame" para la sesión autenticada. Recuerda, esto significa que la sesión se autenticará indefinidamente o hasta que el usuario cierre sesión manualmente en la aplicación:

Auth::login($user, $remember = true);

Si es necesario, puedes especificar una guardia de autenticación antes de llamar al método login:

Auth::guard('admin')->login($user);

Autenticar un usuario por ID

Para autenticar a un usuario utilizando la clave primaria de su registro en la base de datos, puedes utilizar el método loginUsingId. Este método acepta la clave primaria del usuario que deseas autenticar:

Auth::loginUsingId(1);

Puedes pasar un valor booleano como segundo argumento al método loginUsingId. Este valor indica si se desea la funcionalidad "recuérdame" para la sesión autenticada. Recuerda, esto significa que la sesión se autenticará indefinidamente o hasta que el usuario cierre sesión manualmente en la aplicación:

Auth::loginUsingId(1, $remember = true);

Autenticar un usuario una vez

Puedes utilizar el método once para autenticar a un usuario en la aplicación por una única solicitud. No se utilizarán sesiones ni cookies al llamar a este método:

if (Auth::once($credentials)) {
// ...
}

Autenticación básica de HTTP

La autenticación básica de HTTP proporciona una forma rápida de autenticar a los usuarios de tu aplicación sin configurar una página de "inicio de sesión" dedicada. Para comenzar, adjunta el middleware auth.basic a una ruta. El middleware auth.basic está incluido en el framework Laravel, por lo que no es necesario definirlo:

Route::get('/profile', function () {
// Solo los usuarios autenticados pueden acceder a esta ruta...
})->middleware('auth.basic');

Una vez que el middleware se ha adjuntado a la ruta, se te pedirá automáticamente las credenciales al acceder a la ruta en tu navegador. Por defecto, el middleware auth.basic asumirá que la columna email en tu tabla de base de datos users es el "nombre de usuario" del usuario.

Nota sobre FastCGI

Si estás utilizando PHP FastCGI y Apache para servir tu aplicación Laravel, la autenticación básica de HTTP puede no funcionar correctamente. Para corregir estos problemas, las siguientes líneas se pueden agregar al archivo .htaccess de tu aplicación:

RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

Autenticación básica de HTTP sin estado

También puedes utilizar la autenticación básica de HTTP sin establecer una cookie de identificación de usuario en la sesión. Esto es especialmente útil si decides utilizar la Autenticación HTTP para autenticar solicitudes a la API de tu aplicación. Para lograr esto, define un middleware que llame al método onceBasic. Si el método onceBasic no devuelve ninguna respuesta, la solicitud se puede pasar más adelante en la aplicación:

<?php
 
namespace App\Http\Middleware;
 
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
 
class AuthenticateOnceWithBasicAuth
{
/**
* Manejar una solicitud entrante.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
return Auth::onceBasic() ?: $next($request);
}
 
}

A continuación, adjunta el middleware a una ruta:

Route::get('/api/user', function () {
// Solo los usuarios autenticados pueden acceder a esta ruta...
})->middleware(AuthenticateOnceWithBasicAuth::class);

Cerrar sesión

Para cerrar sesión manualmente a los usuarios de tu aplicación, puedes utilizar el método logout proporcionado por la fachada Auth. Esto eliminará la información de autenticación de la sesión del usuario para que las solicitudes subsiguientes no estén autenticadas.

Además de llamar al método logout, se recomienda invalidar la sesión del usuario y regenerar su token CSRF. Después de cerrar sesión del usuario, normalmente redirigirías al usuario a la raíz de tu aplicación:

use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;
 
/**
* Cerrar la sesión del usuario en la aplicación.
*/
public function logout(Request $request): RedirectResponse
{
Auth::logout();
 
$request->session()->invalidate();
 
$request->session()->regenerateToken();
 
return redirect('/');
}

Invalidar sesiones en otros dispositivos

Laravel también proporciona un mecanismo para invalidar y "cerrar sesión" en las sesiones de un usuario activas en otros dispositivos sin invalidar la sesión en su dispositivo actual. Esta función se utiliza típicamente cuando un usuario está cambiando o actualizando su contraseña y deseas invalidar sesiones en otros dispositivos mientras mantienes autenticado el dispositivo actual.

Antes de comenzar, asegúrate de que el middleware Illuminate\Session\Middleware\AuthenticateSession esté incluido en las rutas que deben recibir autenticación de sesión. Normalmente, deberías colocar este middleware en la definición de un grupo de rutas para que se aplique a la mayoría de las rutas de tu aplicación. Por defecto, el middleware AuthenticateSession puede ser adjuntado a una ruta utilizando el alias del middleware de ruta auth.session, como está definido en el kernel HTTP de tu aplicación:

Route::middleware(['auth', 'auth.session'])->group(function () {
Route::get('/', function () {
// ...
});
});

Luego, puedes utilizar el método logoutOtherDevices proporcionado por la fachada Auth. Este método requiere que el usuario confirme su contraseña actual, la cual tu aplicación debería aceptar a través de un formulario de entrada:

use Illuminate\Support\Facades\Auth;
 
Auth::logoutOtherDevices($currentPassword);

Cuando se invoca el método logoutOtherDevices, las otras sesiones del usuario se invalidarán por completo, lo que significa que se "cerrará sesión" en todas las guardias por las que estuvieran autenticados anteriormente.

Confirmación de contraseña

Mientras construyes tu aplicación, es posible que en ocasiones tengas acciones que requieran que el usuario confirme su contraseña antes de realizar la acción o antes de redirigir al usuario a una área sensible de la aplicación. Laravel incluye un middleware incorporado para hacer que este proceso sea muy sencillo. Implementar esta función requerirá que definas dos rutas: una ruta para mostrar una vista que pida al usuario que confirme su contraseña y otra ruta para confirmar que la contraseña es válida y redirigir al usuario a su destino previsto.

Nota La siguiente documentación explica cómo integrarse con las funciones de confirmación de contraseña de Laravel directamente; sin embargo, si deseas empezar más rápidamente, ¡los kits de inicio de aplicación de Laravel incluyen soporte para esta función!

Configuración

Después de confirmar su contraseña, a un usuario no se le pedirá que vuelva a confirmar su contraseña durante tres horas. Sin embargo, puedes configurar la duración del tiempo antes de que se le vuelva a pedir al usuario su contraseña cambiando el valor de la configuración password_timeout en el archivo de configuración config/auth.php de tu aplicación.

Enrutamiento

El formulario de confirmación de contraseña

Primero, definiremos una ruta para mostrar una vista que solicita al usuario que confirme su contraseña:

Route::get('/confirm-password', function () {
return view('auth.confirm-password');
})->middleware('auth')->name('password.confirm');

Como puedes imaginar, la vista que devuelve esta ruta debe tener un formulario que contenga un campo de password. Además, siéntete libre de incluir texto dentro de la vista que explique que el usuario está ingresando a una área protegida de la aplicación y debe confirmar su contraseña.

Confirmación de contraseña

A continuación, definiremos una ruta que manejará la solicitud de formulario desde la vista de "confirmar contraseña". Esta ruta será responsable de validar la contraseña y redirigir al usuario a su destino previsto:

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Redirect;
 
Route::post('/confirm-password', function (Request $request) {
if (! Hash::check($request->password, $request->user()->password)) {
return back()->withErrors([
'password' => ['La contraseña proporcionada no coincide con nuestros registros.']
]);
}
 
$request->session()->passwordConfirmed();
 
return redirect()->intended();
})->middleware(['auth', 'throttle:6,1']);

Antes de continuar, examinemos esta ruta con más detalle. Primero, se determina que el campo de password de la solicitud realmente coincide con la contraseña del usuario autenticado. Si la contraseña es válida, necesitamos informar a la sesión de Laravel que el usuario ha confirmado su contraseña. El método passwordConfirmed establecerá una marca de tiempo en la sesión del usuario que Laravel puede usar para determinar cuándo fue la última vez que el usuario confirmó su contraseña. Finalmente, podemos redirigir al usuario a su destino previsto.

Protección de rutas

Asegúrate de que cualquier ruta que realice una acción que requiera una reciente confirmación de contraseña tenga asignado el middleware password.confirm. Este middleware se incluye con la instalación predeterminada de Laravel y almacenará automáticamente el destino previsto del usuario en la sesión para que el usuario pueda ser redirigido a esa ubicación después de confirmar su contraseña. Después de almacenar el destino previsto del usuario en la sesión, el middleware redirigirá al usuario a la ruta con nombre password.confirm:

Route::get('/settings', function () {
// ...
})->middleware(['password.confirm']);
 
Route::post('/settings', function () {
// ...
})->middleware(['password.confirm']);

Agregar guardias personalizados

Puedes definir tus propias guardias de autenticación utilizando el método extend en la fachada Auth. Debes colocar tu llamada al método extend dentro de un proveedor de servicios. Dado que Laravel ya incluye un AuthServiceProvider, podemos colocar el código en ese proveedor:

<?php
 
namespace App\Providers;
 
use App\Services\Auth\JwtGuard;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Auth;
 
class AuthServiceProvider extends ServiceProvider
{
/**
* Registrar cualquier servicio de autenticación / autorización de la aplicación.
*/
public function boot(): void
{
Auth::extend('jwt', function (Application $app, string $name, array $config) {
// Devolver una instancia de Illuminate\Contracts\Auth\Guard...
 
return new JwtGuard(Auth::createUserProvider($config['provider']));
});
}
}

Como puedes ver en el ejemplo anterior, el callback pasado al método extend debe devolver una implementación de Illuminate\Contracts\Auth\Guard. Esta interfaz contiene algunos métodos que deberás implementar para definir una guardia personalizada. Una vez que tu guardia personalizada ha sido definida, puedes hacer referencia a la guardia en la configuración de guards de tu archivo de configuración auth.php:

'guards' => [
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],

Guardias de solicitud de cierre

La forma más sencilla de implementar un sistema de autenticación personalizado basado en solicitudes HTTP es mediante el uso del método Auth::viaRequest. Este método te permite definir rápidamente tu proceso de autenticación mediante un solo cierre.

Para empezar, llama al método Auth::viaRequest dentro del método boot de tu AuthServiceProvider. El método viaRequest acepta el nombre del controlador de autenticación como su primer argumento. Este nombre puede ser cualquier cadena que describa tu guardia personalizada. El segundo argumento pasado al método debe ser un cierre que reciba la solicitud HTTP entrante y devuelva una instancia de usuario o, si la autenticación falla, null:

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
 
/**
* Registrar cualquier servicio de autenticación / autorización de la aplicación.
*/
public function boot(): void
{
Auth::viaRequest('custom-token', function (Request $request) {
return User::where('token', (string) $request->token)->first();
});
}

Una vez que se haya definido tu controlador de autenticación personalizado, puedes configurarlo como un controlador dentro de la configuración de guards de tu archivo de configuración auth.php:

'guards' => [
'api' => [
'driver' => 'custom-token',
],
],

Finalmente, puedes hacer referencia a la guardia al asignar el middleware de autenticación a una ruta:

Route::middleware('auth:api')->group(function () {
// ...
});

Agregar proveedores de usuarios personalizados

Si no estás utilizando una base de datos relacional tradicional para almacenar a tus usuarios, deberás ampliar Laravel con tu propio proveedor de usuarios de autenticación. Utilizaremos el método provider en la fachada Auth para definir un proveedor de usuarios personalizado. El resolver del proveedor de usuarios debería devolver una implementación de Illuminate\Contracts\Auth\UserProvider:

<?php
 
namespace App\Providers;
 
use App\Extensions\MongoUserProvider;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Auth;
 
class AuthServiceProvider extends ServiceProvider
{
/**
* Registrar cualquier servicio de autenticación / autorización de la aplicación.
*/
public function boot(): void
{
Auth::provider('mongo', function (Application $app, array $config) {
// Devolver una instancia de Illuminate\Contracts\Auth\UserProvider...
 
return new MongoUserProvider($app->make('mongo.connection'));
});
}
}

Después de haber registrado el proveedor usando el método provider, puedes cambiar al nuevo proveedor de usuarios en tu archivo de configuración auth.php. Primero, define un provider que utilice tu nuevo controlador:

'providers' => [
'users' => [
'driver' => 'mongo',
],
],

Finalmente, puedes hacer referencia a este proveedor en tu configuración de guards:

'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
],

Contrato del proveedor de usuarios

Las implementaciones de Illuminate\Contracts\Auth\UserProvider son responsables de obtener una implementación de Illuminate\Contracts\Auth\Authenticatable de un sistema de almacenamiento persistente, como MySQL, MongoDB, etc. Estas dos interfaces permiten que los mecanismos de autenticación de Laravel sigan funcionando independientemente de cómo se almacenen los datos del usuario o qué tipo de clase se utilice para representar al usuario autenticado:

Echemos un vistazo al contrato Illuminate\Contracts\Auth\UserProvider:

<?php
 
namespace Illuminate\Contracts\Auth;
 
interface UserProvider
{
public function retrieveById($identifier);
public function retrieveByToken($identifier, $token);
public function updateRememberToken(Authenticatable $user, $token);
public function retrieveByCredentials(array $credentials);
public function validateCredentials(Authenticatable $user, array $credentials);
}

La función retrieveById recibe típicamente una clave que representa al usuario, como un ID autoincremental de una base de datos MySQL. La implementación de Authenticatable que coincida con el ID debe ser recuperada y devuelta por el método.

La función retrieveByToken recupera a un usuario por su único $identifier y el $token "recuérdame", almacenado típicamente en una columna de la base de datos como remember_token. Al igual que con el método anterior, la implementación de Authenticatable con un valor de token coincidente debe ser devuelta por este método.

El método updateRememberToken actualiza el remember_token del $user con el nuevo $token. Se asigna un nuevo token a los usuarios en un intento exitoso de autenticación "recuérdame" o cuando el usuario cierra sesión.

El método retrieveByCredentials recibe la matriz de credenciales pasada al método Auth::attempt al intentar autenticarse con una aplicación. Luego, el método debe "consultar" el almacenamiento persistente subyacente en busca del usuario que coincida con esas credenciales. Normalmente, este método ejecutará una consulta con una condición "where" que busque un registro de usuario con un "nombre de usuario" que coincida con el valor de $credentials['username']. El método debe devolver una implementación de Authenticatable. Este método no debe intentar validar la contraseña ni autenticar al usuario.

El método validateCredentials debe comparar el $user dado con las $credentials para autenticar al usuario. Por ejemplo, este método normalmente usará el método Hash::check para comparar el valor de $user->getAuthPassword() con el valor de $credentials['password']. Este método debe devolver true o false indicando si la contraseña es válida.

Contrato autenticable

Ahora que hemos explorado cada uno de los métodos en UserProvider, echemos un vistazo al contrato Authenticatable. Recuerda, los proveedores de usuarios deben devolver implementaciones de esta interfaz desde los métodos retrieveById, retrieveByToken y retrieveByCredentials:

<?php
 
namespace Illuminate\Contracts\Auth;
 
interface Authenticatable
{
public function getAuthIdentifierName();
public function getAuthIdentifier();
public function getAuthPassword();
public function getRememberToken();
public function setRememberToken($value);
public function getRememberTokenName();
}

Esta interfaz es simple. El método getAuthIdentifierName debe devolver el nombre del campo de "clave primaria" del usuario y el método getAuthIdentifier debe devolver la "clave primaria" del usuario. Al utilizar un back-end de MySQL, esto probablemente sería la clave primaria autoincremental asignada al registro de usuario. El método getAuthPassword debe devolver la contraseña hasheada del usuario.

Esta interfaz permite que el sistema de autenticación funcione con cualquier clase de "usuario", independientemente de la ORM o capa de abstracción de almacenamiento que estés utilizando. Por defecto, Laravel incluye una clase App\Models\User en el directorio app/Models que implementa esta interfaz.

Eventos

Laravel despacha una variedad de eventos durante el proceso de autenticación. Puedes adjuntar escuchadores a estos eventos en tu EventServiceProvider:

/**
* Los mapeos de escuchadores de eventos para la aplicación.
*
* @var array
*/
protected $listen = [
'Illuminate\Auth\Events\Registered' => [
'App\Listeners\LogRegisteredUser',
],
 
'Illuminate\Auth\Events\Attempting' => [
'App\Listeners\LogAuthenticationAttempt',
],
 
'Illuminate\Auth\Events\Authenticated' => [
'App\Listeners\LogAuthenticated',
],
 
'Illuminate\Auth\Events\Login' => [
'App\Listeners\LogSuccessfulLogin',
],
 
'Illuminate\Auth\Events\Failed' => [
'App\Listeners\LogFailedLogin',
],
 
'Illuminate\Auth\Events\Validated' => [
'App\Listeners\LogValidated',
],
 
'Illuminate\Auth\Events\Verified' => [
'App\Listeners\LogVerified',
],
 
'Illuminate\Auth\Events\Logout' => [
'App\Listeners\LogSuccessfulLogout',
],
 
'Illuminate\Auth\Events\CurrentDeviceLogout' => [
'App\Listeners\LogCurrentDeviceLogout',
],
 
'Illuminate\Auth\Events\OtherDeviceLogout' => [
'App\Listeners\LogOtherDeviceLogout',
],
 
'Illuminate\Auth\Events\Lockout' => [
'App\Listeners\LogLockout',
],
 
'Illuminate\Auth\Events\PasswordReset' => [
'App\Listeners\LogPasswordReset',
],
];