¿QUÉ ES LARAVEL SANCTUM?

Laravel Sanctum es una herramienta de autenticación de Laravel que proporciona una forma simple de permitir que las aplicaciones de SPA (Single-Page Application), APis y aplicaciones móviles autentiquen a sus usuarios mediante el uso de tokens pudiendo otorgarles habilidades/alcances que especifican qué acciones pueden realizar.
Laravel Sanctum proporciona toda la lógica necesaria para permitir que las aplicaciones realicen la autenticación y obtengan tokens de acceso, que luego pueden utilizar para autenticar las solicitudes a las API de la aplicación. Alternativamente a los tokens, Sanctum también proporciona la capacidad de autenticar a los usuarios haciendo uso de cookies, lo cubriremos más adelante.
Laravel Sanctum utiliza tokens CSRF, para incrementar la protección ante ataques de falsificación de solicitudes entre sitios. Al generar un token CSRF para cada usuario autenticado, Laravel Sanctum permite que las HTTP request sean verificadas automáticamente en su propia aplicación Laravel sin requerir un flujo tradicional de inicio de sesión.

Instalar Laravel Sanctum

Ejecutar el siguiente comando para instalar Laravel Sanctum a través de Composer:

composer require laravel/sanctum
Después ejecutar el siguiente comando para publicar los archivos de configuración de Laravel Sanctum:

php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
A continuación, ejecutar el siguiente comando para crear la tabla de tokens de acceso en la base de datos:

php artisan migrate
El comando creará la tabla personal_access_tokens, utilizada por Laravel Sanctum cuando se hace uso de tokens.

Autenticación con Laravel Sanctum y API Tokens

  1. Modelo User (necesario)

    // app/Models/User.php
    namespace App\Models;
    
    use Illuminate\Foundation\Auth\User as Authenticatable;
    use Laravel\Sanctum\HasApiTokens;
    
    class User extends Authenticatable
    {
        use HasApiTokens;   // ← ¡Este trait es el corazón de Sanctum!
        
        // ... resto de traits y propiedades
    }
    
  2. Rutas API (routes/api.php);

    se App\Http\Controllers\AuthController;
    
    Route::post('/register', [AuthController::class, 'register']);
    Route::post('/login',    [AuthController::class, 'login']);
    
    Route::middleware('auth:sanctum')->group(function () {
        Route::get('/user', fn() => auth()->user());
        Route::post('/logout', [AuthController::class, 'logout']);
        
        // Tus rutas protegidas aquí...
        Route::apiResource('posts', PostController::class);
    });
    
  3. Controlador de autenticación

    // app/Http/Controllers/AuthController.php
    namespace App\Http\Controllers;
    
    use App\Models\User;
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Hash;
    use Illuminate\Validation\ValidationException;
    
    class AuthController extends Controller
    {
        public function register(Request $request)
        {
            $data = $request->validate([
                'name'     => ['required', 'string', 'max:255'],
                'email'    => ['required', 'email', 'unique:users'],
                'password' => ['required', 'min:8', 'confirmed'],
            ]);
    
            $user = User::create([
                'name'     => $data['name'],
                'email'    => $data['email'],
                'password' => Hash::make($data['password']),
            ]);
    
            // Creamos token al registrar (muy común)
            $token = $user->createToken('auth_token')->plainTextToken;
    
            return response()->json([
                'user'  => $user,
                'token' => $token
            ], 201);
        }
    
        public function login(Request $request)
        {
            $request->validate([
                'email'    => 'required|email',
                'password' => 'required',
                'device_name' => 'required', // ← muy recomendado para identificar el token
            ]);
    
            $user = User::where('email', $request->email)->first();
    
            if (! $user || ! Hash::check($request->password, $user->password)) {
                throw ValidationException::withMessages([
                    'email' => ['Las credenciales proporcionadas son incorrectas.'],
                ]);
            }
    
            // Token con nombre del dispositivo (ideal para revocar por dispositivo)
            $token = $user->createToken($request->device_name)->plainTextToken;
    
            return response()->json([
                'user'  => $user,
                'token' => $token
            ]);
        }
    
        public function logout(Request $request)
        {
            // Revoca el token actual (el que se usa en esta petición)
            $request->user()->currentAccessToken()->delete();
    
            // O revocar TODOS los tokens del usuario:
            // $request->user()->tokens()->delete();
    
            return response()->json(['message' => 'Sesión cerrada correctamente']);
        }
    }