Aprende a implementar la autenticación con API tokens y SPA con Laravel Sanctum. Desde la instalación del paquete hasta el uso avanzado, con un enfoque práctico.
Laravel Sanctum es un paquete de autenticación ligero pensado para SPAs (single page applications), apps móviles y APIs sencillas. Puedes emitir y gestionar varios API tokens por usuario sin necesidad de dominar OAuth.Sanctum cubre dos casos de uso:
Modo de autenticación
Mecanismo
Uso típico
API tokens
Cabecera Authorization: Bearer <token>
Apps móviles, integraciones de terceros
SPA
Cookie de sesión + protección CSRF
Frontend propio (Vue/React, etc.)
Si tu SPA llama a la API que tú mismo controlas, usa el modo SPA. Si la API la consumen apps móviles o terceros, usa API tokens. Puedes usar uno solo o los dos.
Usa createToken(). La propiedad plainTextToken contiene el valor en texto plano. Ese valor no se guarda en la base de datos, por lo que debes devolvérselo al usuario inmediatamente.
use Illuminate\Http\Request;Route::post('/tokens/create', function (Request $request) { $token = $request->user()->createToken($request->token_name); return ['token' => $token->plainTextToken];})->middleware('auth');
En la base de datos se guarda el token con hash SHA-256.
Puedes asignar abilities (scopes) al token para restringir las operaciones que permite.
// Token con scopes$token = $user->createToken('mobile-app', ['server:update', 'server:read']);return $token->plainTextToken;
Al procesar la petición, comprueba los scopes.
if ($request->user()->tokenCan('server:update')) { // Ejecutar la operación de actualización}if ($request->user()->tokenCant('server:update')) { abort(403);}
Registra el alias del middleware en bootstrap/app.php.
use Laravel\Sanctum\Http\Middleware\CheckAbilities;use Laravel\Sanctum\Http\Middleware\CheckForAnyAbility;->withMiddleware(function (Middleware $middleware): void { $middleware->alias([ 'abilities' => CheckAbilities::class, // Todas las abilities 'ability' => CheckForAnyAbility::class, // Alguna ability ]);})
Aplica el middleware a las rutas.
// Solo tokens con check-status y place-orders a la vezRoute::get('/orders', function () { // ...})->middleware(['auth:sanctum', 'abilities:check-status,place-orders']);// Tokens con check-status o place-ordersRoute::get('/orders', function () { // ...})->middleware(['auth:sanctum', 'ability:check-status,place-orders']);
// Eliminar todos los tokens$user->tokens()->delete();// Eliminar el token de la petición actual$request->user()->currentAccessToken()->delete();// Eliminar un token concreto$user->tokens()->where('id', $tokenId)->delete();
La autenticación SPA usa cookies de sesión, así que no necesitas emitir ni gestionar tokens. Es ideal para tu propio frontend (Vue, React, Next.js…) que consume tu API.
Para usar la autenticación SPA, el SPA y la API deben compartir dominio de nivel superior (los subdominios pueden ser distintos). Además, las peticiones deben incluir Accept: application/json y las cabeceras Referer u Origin.
// routes/api.phpRoute::middleware('auth:sanctum')->group(function () { // Devuelve el usuario actual Route::get('/user', function (Request $request) { return $request->user(); }); // Cierra sesión revocando el token actual Route::post('/logout', function (Request $request) { $request->user()->currentAccessToken()->delete(); return response()->json(['message' => 'Sesión cerrada.']); }); // Cierra sesión en todos los dispositivos Route::post('/logout/all', function (Request $request) { $request->user()->tokens()->delete(); return response()->json(['message' => 'Sesión cerrada en todos los dispositivos.']); });});
En los tests de Sanctum utiliza Sanctum::actingAs() para autenticar a un usuario y asignar abilities.
Pest
PHPUnit
use App\Models\User;use Laravel\Sanctum\Sanctum;test('se puede obtener el listado de tareas', function () { Sanctum::actingAs( User::factory()->create(), ['view-tasks'] ); $response = $this->get('/api/tasks'); $response->assertOk();});test('un token con todas las abilities puede acceder', function () { Sanctum::actingAs( User::factory()->create(), ['*'] ); $response = $this->get('/api/tasks'); $response->assertOk();});
use App\Models\User;use Laravel\Sanctum\Sanctum;public function test_task_list_can_be_retrieved(): void{ Sanctum::actingAs( User::factory()->create(), ['view-tasks'] ); $response = $this->get('/api/tasks'); $response->assertOk();}