¿Cómo se implementa autenticación en una API de Laravel?
Implementar autenticación en una API de Laravel es un paso fundamental para asegurar tus endpoints. Laravel ofrece varias opciones, pero la más moderna y recomendada para la mayoría de las API (especialmente las que son consumidas por Single Page Applications o aplicaciones móviles) es Laravel Sanctum.
Vamos a centrarnos en Laravel Sanctum como la solución principal, y luego mencionaremos brevemente otras alternativas.
Autenticación de API con Laravel Sanctum (Recomendado)
Laravel Sanctum es un paquete ligero que ofrece un sistema simple de autenticación basado en tokens para APIs. Es ideal para:
- SPAs (Single Page Applications): Donde tu frontend de JavaScript (React, Vue, Angular) y tu API de Laravel están en el mismo dominio o dominios relacionados. Aquí, Sanctum utiliza cookies/sesiones (con protección CSRF) para autenticar al usuario.
- Aplicaciones Móviles o Third-Party: Donde no puedes usar cookies. Para estos casos, Sanctum permite generar tokens de API que se envían en el encabezado
Authorization
.
Conceptos Clave de Sanctum:
- Tokens de API: Son strings alfanuméricos largos y seguros que los usuarios pueden generar (o que se generan para ellos). Cada token está asociado a un usuario y puede tener "habilidades" (abilities/scopes) específicas que definen qué acciones puede realizar.
- Trait
HasApiTokens
: Se añade a tu modeloUser
para que pueda generar y gestionar tokens. - Middleware
auth:sanctum
: Es el middleware de protección que usas en tus rutas de API. - SPA Authentication (Autenticación para SPAs): Si tu SPA y tu API están en el mismo dominio, Sanctum usa un proceso de "cookie-based authentication" que es similar a una sesión web tradicional, pero optimizado para SPAs. Implica el intercambio de un token CSRF al inicio de la sesión.
Implementación Paso a Paso de Laravel Sanctum:
1. Instalación de Sanctum
Abre tu terminal en la raíz de tu proyecto Laravel y ejecuta:
composer require laravel/sanctum
2. Publicar Migraciones y Ejecutar
Sanctum necesita una tabla en la base de datos para almacenar los tokens de API.
php artisan vendor:publish --tag="sanctum-migrations"
php artisan migrate
Esto creará una tabla personal_access_tokens
en tu base de datos.
Alternativamente, Este paso se puede realizar con
php artisan install:api
3. Configuración del Modelo User
Abre tu modelo app/Models/User.php
y añade el trait HasApiTokens
:
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens; // <--- Añade esta línea
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable; // <--- Añade HasApiTokens aquí
// ... el resto de tu modelo
}
4. Proteger Rutas de API
Para proteger tus rutas de API, usa el middleware auth:sanctum
. Generalmente, esto se hace en tu archivo routes/api.php
:
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
// Rutas públicas o de autenticación (login, registro)
Route::post('/register', [App\Http\Controllers\Auth\RegisterController::class, 'register']);
Route::post('/login', [App\Http\Controllers\Auth\LoginController::class, 'login']);
// Rutas protegidas por Sanctum
Route::middleware('auth:sanctum')->group(function () {
Route::get('/user', function (Request $request) {
return $request->user();
});
Route::post('/logout', [App\Http\Controllers\Auth\LoginController::class, 'logout']);
// Ejemplo de ruta con habilidades/scopes
Route::get('/orders', function (Request $request) {
// El token debe tener la habilidad 'read:orders'
if ($request->user()->tokenCan('read:orders')) {
return response()->json(['message' => 'Lista de órdenes']);
}
return response()->json(['message' => 'No tienes permiso para leer órdenes'], 403);
});
});
5. Implementar Lógica de Autenticación (Login/Logout)
Necesitarás controladores para manejar el registro y el login. Aquí un ejemplo simplificado de un controlador de Login:
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;
class LoginController extends Controller
{
public function login(Request $request)
{
$request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
'device_name' => ['required'], // Necesario para la autenticación de tokens
]);
$user = User::where('email', $request->email)->first();
if (! $user || ! Hash::check($request->password, $user->password)) {
throw ValidationException::withMessages([
'email' => ['Las credenciales proporcionadas son incorrectas.'],
]);
}
// Si el login es exitoso, crea un token
// Puedes definir habilidades (scopes) aquí
$token = $user->createToken($request->device_name, ['read', 'write:orders'])->plainTextToken;
return response()->json(['token' => $token]);
}
public function logout(Request $request)
{
// Revocar el token actual usado para la autenticación
$request->user()->currentAccessToken()->delete();
return response()->json(['message' => 'Sesión cerrada exitosamente']);
}
}
6. Cómo usar el Token en el Cliente (Móvil/Third-Party)
Una vez que el cliente obtiene el token
(después de un login exitoso), debe enviarlo en el encabezado Authorization
de todas las solicitudes subsiguientes a rutas protegidas.
Authorization: Bearer YOUR_GENERATED_TOKEN_HERE
Ejemplo con JavaScript (fetch API):
// Después de iniciar sesión y obtener el token
const token = 'tu_token_generado_aqui';
fetch('http://localhost:8000/api/user', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Authorization': `Bearer ${token}` // Envía el token Bearer
}
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
7. Configuración para SPAs (Autenticación basada en Cookies)
Si tu SPA y tu API están en el mismo dominio (o subdominio), puedes usar la autenticación basada en cookies.
-
Añade el middleware EnsureFrontendRequestsAreStateful:
Abre app/Http/Kernel.php y asegúrate de que el middleware \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class esté en el grupo de middleware api o web. (Generalmente ya está en web por defecto).
-
Configura tus dominios frontend en config/sanctum.php:
Asegúrate de que el dominio de tu SPA esté listado en la propiedad stateful del archivo config/sanctum.php.
PHP// config/sanctum.php 'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1')),
También configura CORS en
config/cors.php
. -
Llama al endpoint sanctum/csrf-cookie:
Desde tu SPA, antes de intentar iniciar sesión, debes hacer una solicitud GET a /sanctum/csrf-cookie. Esto establece la cookie XSRF que Sanctum usará para las solicitudes subsiguientes (login, etc.).
JavaScript// En tu SPA, al cargar la aplicación o antes del login fetch('http://localhost:8000/sanctum/csrf-cookie') .then(response => { // Ahora puedes proceder con la solicitud de login (POST /api/login) // que enviará automáticamente las cookies de sesión y CSRF. });
Después de esto, las solicitudes de login y otras solicitudes API enviadas desde tu SPA al mismo dominio serán autenticadas a través de la cookie de sesión.
Otras Opciones de Autenticación de API en Laravel:
-
Laravel Passport (OAuth2):
- Cuándo usarlo: Si necesitas una solución OAuth2 completa para tu API, especialmente si vas a tener clientes de terceros (otras aplicaciones, no solo tu propia SPA/móvil) que necesiten interactuar con tu API y requerirán diferentes "grant types" (ej. Authorization Code, Client Credentials, Password Grant). Es más robusto y complejo que Sanctum.
- Requiere: Instalación de
laravel/passport
y una configuración más extensa.
-
JWT (JSON Web Tokens):
- Cuándo usarlo: Si prefieres un enfoque completamente stateless y tienes experiencia con JWTs. Requiere una librería de terceros como
tymon/jwt-auth
. El token contiene toda la información del usuario en su interior (firmada, no cifrada). - Requiere: Instalación de
tymon/jwt-auth
y configuración manual del middleware.
- Cuándo usarlo: Si prefieres un enfoque completamente stateless y tienes experiencia con JWTs. Requiere una librería de terceros como
¿Cuál elegir?
- Para la mayoría de los casos (SPAs y aplicaciones móviles que tú controlas): Laravel Sanctum es la opción más sencilla, ligera y recomendada. Cubre perfectamente las necesidades de autenticación basada en tokens y sesiones para SPAs.
- Para APIs públicas o si necesitas soporte OAuth2 completo (con diferentes tipos de "grants"): Laravel Passport es la solución adecuada.
- Si tienes requisitos muy específicos o ya estás familiarizado con JWTs:
tymon/jwt-auth
puede ser una opción, pero para muchos, Sanctum ya cumple con los mismos objetivos de forma más integrada en Laravel.
Siempre recuerda la importancia de usar HTTPS para todas tus comunicaciones API, ya que los tokens se transmiten por la red.
No hay comentarios:
Publicar un comentario