Documentación de Laravel 10.x
Aquí encontrarás fragmentos de código de Laravel y consejos útiles sobre desarrollo web.
Laravel Sanctum proporciona un sistema de autenticación liviano para SPAs (aplicaciones de página única), aplicaciones móviles y API simples basadas en tokens. Sanctum permite que cada usuario de tu aplicación genere múltiples tokens de API para su cuenta. Estos tokens pueden recibir habilidades o alcances que especifican qué acciones se les permite realizar.
Laravel Sanctum existe para resolver dos problemas diferentes. Vamos a discutir cada uno antes de profundizar más en la biblioteca.
En primer lugar, Sanctum es un paquete simple que puedes utilizar para emitir tokens de API a tus usuarios sin la complicación de OAuth. Esta función está inspirada en GitHub y otras aplicaciones que emiten "tokens de acceso personal". Por ejemplo, imagina que la "configuración de la cuenta" de tu aplicación tiene una pantalla donde un usuario puede generar un token de API para su cuenta. Puedes usar Sanctum para generar y gestionar esos tokens. Estos tokens suelen tener un tiempo de caducidad muy largo (años), pero pueden revocarse manualmente por el usuario en cualquier momento.
Laravel Sanctum ofrece esta función almacenando los tokens de API del usuario en una sola tabla de base de datos y autenticando las solicitudes HTTP entrantes mediante la cabecera Authorization
, que debe contener un token de API válido.
En segundo lugar, Sanctum existe para ofrecer una forma sencilla de autenticar aplicaciones de página única (SPAs) que necesitan comunicarse con una API impulsada por Laravel. Estas SPAs pueden existir en el mismo repositorio que tu aplicación Laravel o pueden ser un repositorio completamente separado, como una SPA creada con Vue CLI o una aplicación Next.js.
Para esta función, Sanctum no utiliza tokens de ningún tipo. En su lugar, Sanctum utiliza los servicios de autenticación de sesión basados en cookies integrados de Laravel. Típicamente, Sanctum utiliza la guarda de autenticación web
de Laravel para lograr esto. Esto proporciona los beneficios de protección CSRF, autenticación de sesión, así como protege contra la filtración de las credenciales de autenticación mediante XSS.
Sanctum solo intentará autenticar mediante cookies cuando la solicitud entrante se origine desde tu propio frontend de SPA. Cuando Sanctum examina una solicitud HTTP entrante, primero verificará si hay una cookie de autenticación y, si no hay ninguna presente, Sanctum examinará la cabecera Authorization
en busca de un token de API válido.
Nota Es completamente válido usar Sanctum solo para la autenticación con tokens de API o solo para la autenticación SPA. Solo porque uses Sanctum no significa que estés obligado a utilizar ambas funciones que ofrece.
Nota Las versiones más recientes de Laravel ya incluyen Laravel Sanctum. Sin embargo, si el archivo
composer.json
de tu aplicación no incluyelaravel/sanctum
, puedes seguir las instrucciones de instalación a continuación.
Puedes instalar Laravel Sanctum a través del administrador de paquetes Composer:
composer require laravel/sanctum
A continuación, debes publicar los archivos de configuración y migración de Sanctum usando el comando Artisan vendor:publish
. El archivo de configuración sanctum
se ubicará en el directorio config
de tu aplicación:
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
Finalmente, debes ejecutar las migraciones de tu base de datos. Sanctum creará una tabla de base de datos en la que almacenará los tokens de API:
php artisan migrate
Después, si planeas utilizar Sanctum para autenticar una SPA, debes agregar el middleware de Sanctum al grupo de middleware api
dentro del archivo app/Http/Kernel.php
de tu aplicación:
'api' => [ \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, \Illuminate\Routing\Middleware\ThrottleRequests::class.':api', \Illuminate\Routing\Middleware\SubstituteBindings::class,],
Si no vas a utilizar las migraciones predeterminadas de Sanctum, debes llamar al método Sanctum::ignoreMigrations
en el método register
de tu clase App\Providers\AppServiceProvider
. Puedes exportar las migraciones predeterminadas ejecutando el siguiente comando: php artisan vendor:publish --tag=sanctum-migrations
Aunque normalmente no es necesario, eres libre de extender el modelo PersonalAccessToken
utilizado internamente por Sanctum:
use Laravel\Sanctum\PersonalAccessToken as SanctumPersonalAccessToken; class PersonalAccessToken extends SanctumPersonalAccessToken{ // ...}
Luego, puedes indicar a Sanctum que use tu modelo personalizado mediante el método usePersonalAccessTokenModel
proporcionado por Sanctum. Por lo general, debes llamar a este método en el método boot
de uno de los proveedores de servicios de tu aplicación:
use App\Models\Sanctum\PersonalAccessToken;use Laravel\Sanctum\Sanctum; /** * Inicializa cualquier servicio de la aplicación. */public function boot(): void{ Sanctum::usePersonalAccessTokenModel(PersonalAccessToken::class);}
Nota No debes usar tokens de API para autenticar tu propio SPA de primeros usuarios. En su lugar, utiliza las funciones integradas de autenticación SPA de Sanctum.
Sanctum te permite emitir tokens de API/tokens de acceso personal que se pueden utilizar para autenticar las solicitudes de la API de tu aplicación. Al realizar solicitudes mediante tokens de API, el token debe incluirse en la cabecera Authorization
como un token Bearer
.
Para comenzar a emitir tokens para los usuarios, tu modelo de usuario debe usar el rasgo Laravel\Sanctum\HasApiTokens
:
use Laravel\Sanctum\HasApiTokens; class User extends Authenticatable{ use HasApiTokens, HasFactory, Notifiable;}
Para emitir un token, puedes usar el método createToken
. El método createToken
devuelve una instancia de Laravel\Sanctum\NewAccessToken
. Los tokens de API se hashan mediante el hashing SHA-256 antes de almacenarse en tu base de datos, pero puedes acceder al valor en texto sin formato del token utilizando la propiedad plainTextToken
de la instancia NewAccessToken
. Debes mostrar este valor al usuario inmediatamente después de crear el token:
use Illuminate\Http\Request; Route::post('/tokens/create', function (Request $request) { $token = $request->user()->createToken($request->token_name); return ['token' => $token->plainTextToken];});
Puedes acceder a todos los tokens del usuario utilizando la relación Eloquent tokens
proporcionada por el rasgo HasApiTokens
:
foreach ($user->tokens as $token) { // ...}
Sanctum te permite asignar "habilidades" a los tokens. Las habilidades cumplen un propósito similar a los "alcances" de OAuth. Puedes pasar un array de habilidades como segundo argumento al método createToken
:
return $user->createToken('token-name', ['server:update'])->plainTextToken;
Cuando manejas una solicitud entrante autenticada por Sanctum, puedes determinar si el token tiene una habilidad específica utilizando el método tokenCan
:
if ($user->tokenCan('server:update')) { // ...}
Sanctum también incluye dos middleware que se pueden utilizar para verificar que una solicitud entrante esté autenticada con un token al que se le haya otorgado una habilidad específica. Para comenzar, agrega los siguientes middleware a la propiedad $middlewareAliases
de tu archivo app/Http/Kernel.php
de la aplicación:
'abilities' => \Laravel\Sanctum\Http\Middleware\CheckAbilities::class,'ability' => \Laravel\Sanctum\Http\Middleware\CheckForAnyAbility::class,
El middleware abilities
se puede asignar a una ruta para verificar que el token de la solicitud entrante tenga todas las habilidades enumeradas:
Route::get('/orders', function () { // El token tiene tanto las habilidades "check-status" como "place-orders"...})->middleware(['auth:sanctum', 'abilities:check-status,place-orders']);
El middleware ability
se puede asignar a una ruta para verificar que el token de la solicitud entrante tenga al menos una de las habilidades enumeradas:
Route::get('/orders', function () { // El token tiene la habilidad "check-status" o "place-orders"...})->middleware(['auth:sanctum', 'ability:check-status,place-orders']);
Para mayor comodidad, el método tokenCan
siempre devolverá true
si la solicitud autenticada entrante provino de tu SPA de primeros usuarios y estás utilizando la autenticación SPA integrada de Sanctum.
Sin embargo, esto no significa necesariamente que tu aplicación deba permitir que el usuario realice la acción. Típicamente, las políticas de autorización de tu aplicación determinarán si se ha otorgado al token el permiso para realizar las habilidades y también verificarán si la instancia de usuario en sí misma tiene permitido realizar la acción.
Por ejemplo, si imaginamos una aplicación que gestiona servidores, esto podría significar verificar que el token está autorizado para actualizar servidores y que el servidor pertenece al usuario:
return $request->user()->id === $server->user_id && $request->user()->tokenCan('server:update')
Al principio, permitir que se llame al método tokenCan
y que siempre devuelva true
para las solicitudes iniciadas por la interfaz de usuario de primeros usuarios puede parecer extraño; sin embargo, es conveniente poder asumir siempre que hay un token de API disponible y se puede inspeccionar mediante el método tokenCan
. Al adoptar este enfoque, siempre puedes llamar al método tokenCan
dentro de las políticas de autorización de tu aplicación sin preocuparte por si la solicitud se activó desde la interfaz de usuario de tu aplicación o fue iniciada por uno de los consumidores de tu API de terceros.
Para proteger rutas de modo que todas las solicitudes entrantes deban estar autenticadas, debes adjuntar la guarda de autenticación sanctum
a tus rutas protegidas dentro de tus archivos de ruta routes/web.php
y routes/api.php
. Esta guarda se asegurará de que las solicitudes entrantes estén autenticadas como solicitudes autenticadas por cookies o contengan una cabecera de token de API válida si la solicitud es de un tercero.
Puede que te preguntes por qué sugerimos que autentiques las rutas dentro del archivo routes/web.php
de tu aplicación utilizando la guarda sanctum
. Recuerda, Sanctum intentará primero autenticar las solicitudes entrantes utilizando la cookie de autenticación típica de Laravel. Si esa cookie no está presente, Sanctum intentará autenticar la solicitud utilizando un token en la cabecera Authorization
de la solicitud. Además, autenticar todas las solicitudes utilizando Sanctum garantiza que siempre podamos llamar al método tokenCan
en la instancia de usuario autenticada actualmente:
use Illuminate\Http\Request; Route::middleware('auth:sanctum')->get('/user', function (Request $request) { return $request->user();});
Puedes "revocar" tokens eliminándolos de tu base de datos utilizando la relación tokens
proporcionada por el rasgo Laravel\Sanctum\HasApiTokens
:
// Revoca todos los tokens...$user->tokens()->delete(); // Revoca el token que se utilizó para autenticar la solicitud actual...$request->user()->currentAccessToken()->delete(); // Revoca un token específico...$user->tokens()->where('id', $tokenId)->delete();
Por defecto, los tokens de Sanctum nunca caducan y solo pueden invalidarse revocando el token. Sin embargo, si deseas configurar un tiempo de caducidad para los tokens de API de tu aplicación, puedes hacerlo a través de la opción de configuración expiration
definida en el archivo de configuración sanctum
de tu aplicación. Esta opción de configuración define la cantidad de minutos hasta que se considere que un token emitido ha caducado:
'expiration' => 525600,
Si has configurado un tiempo de caducidad del token para tu aplicación, también puedes programar una tarea para eliminar los tokens caducados de tu aplicación. Afortunadamente, Sanctum incluye un comando Artisan sanctum:prune-expired
que puedes utilizar para lograr esto. Por ejemplo, puedes configurar una tarea programada para eliminar todos los registros de tokens caducados que hayan caducado durante al menos 24 horas:
$schedule->command('sanctum:prune-expired --hours=24')->daily();
Sanctum también existe para proporcionar un método simple de autenticar aplicaciones de página única (SPAs) que necesitan comunicarse con una API alimentada por Laravel. Estas SPAs pueden existir en el mismo repositorio que tu aplicación de Laravel o pueden ser un repositorio completamente separado.
Para esta función, Sanctum no utiliza tokens de ningún tipo. En su lugar, Sanctum utiliza los servicios de autenticación de sesión basados en cookies integrados de Laravel. Este enfoque de autenticación proporciona los beneficios de protección contra CSRF, autenticación de sesión, así como protección contra la filtración de las credenciales de autenticación mediante XSS.
Advertencia Para autenticarte, tu SPA y API deben compartir el mismo dominio de nivel superior. Sin embargo, pueden estar en subdominios diferentes. Además, asegúrate de enviar la cabecera
Accept: application/json
y ya sea la cabeceraReferer
oOrigin
con tu solicitud.
Primero, debes configurar qué dominios realizarán solicitudes desde tu SPA. Puedes configurar estos dominios mediante la opción de configuración stateful
en tu archivo de configuración sanctum
. Esta configuración determina qué dominios mantendrán la autenticación "con estado" utilizando cookies de sesión de Laravel al realizar solicitudes a tu API.
Advertencia Si accedes a tu aplicación a través de una URL que incluye un puerto (
127.0.0.1:8000
), asegúrate de incluir el número de puerto con el dominio.
A continuación, debes agregar el middleware de Sanctum al grupo de middleware api
dentro de tu archivo app/Http/Kernel.php
. Este middleware se encarga de garantizar que las solicitudes entrantes desde tu SPA puedan autenticarse mediante las cookies de sesión de Laravel, al tiempo que permite que las solicitudes de terceros o aplicaciones móviles se autentiquen mediante tokens de API:
'api' => [ \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, \Illuminate\Routing\Middleware\ThrottleRequests::class.':api', \Illuminate\Routing\Middleware\SubstituteBindings::class,],
Si tienes problemas para autenticarte con tu aplicación desde una SPA que se ejecuta en un subdominio separado, es probable que hayas configurado incorrectamente tus ajustes de CORS (Recursos Compartidos de Origen Cruzado) o cookies de sesión.
Asegúrate de que la configuración CORS de tu aplicación esté devolviendo la cabecera Access-Control-Allow-Credentials
con un valor de True
. Esto se puede lograr configurando la opción supports_credentials
dentro del archivo de configuración config/cors.php
de tu aplicación en true
.
Además, debes habilitar la opción withCredentials
en la instancia global de axios
de tu aplicación. Normalmente, esto se debe hacer en tu archivo resources/js/bootstrap.js
. Si no estás utilizando Axios para realizar solicitudes HTTP desde tu frontend, debes realizar la configuración equivalente en tu propio cliente HTTP:
axios.defaults.withCredentials = true;
Finalmente, asegúrate de que la configuración del dominio de la cookie de sesión de tu aplicación admita cualquier subdominio de tu dominio raíz. Puedes lograr esto agregando un punto .
al principio del dominio en el archivo de configuración config/session.php
de tu aplicación:
'domain' => '.domain.com',
Para autenticar tu SPA, la página de "inicio de sesión" de tu SPA debe realizar primero una solicitud al punto final /sanctum/csrf-cookie
para inicializar la protección CSRF para la aplicación:
axios.get('/sanctum/csrf-cookie').then(response => { // Iniciar sesión...});
Durante esta solicitud, Laravel establecerá una cookie XSRF-TOKEN
que contiene el token CSRF actual. Este token debe pasarse en la cabecera X-XSRF-TOKEN
en solicitudes subsiguientes, lo cual algunas bibliotecas de clientes HTTP, como Axios y Angular HttpClient, harán automáticamente por ti. Si tu biblioteca HTTP de JavaScript no establece el valor por ti, deberás configurar manualmente la cabecera X-XSRF-TOKEN
para que coincida con el valor de la cookie XSRF-TOKEN
que establece esta ruta.
Una vez que se ha inicializado la protección CSRF, debes realizar una solicitud POST
a la ruta /login
de tu aplicación Laravel. Esta ruta /login
se puede implementar manualmente o utilizando un paquete de autenticación sin cabeza como Laravel Fortify.
Si la solicitud de inicio de sesión es exitosa, estarás autenticado y las solicitudes subsiguientes a las rutas de tu aplicación se autenticarán automáticamente mediante la cookie de sesión que la aplicación Laravel emitió a tu cliente. Además, dado que tu aplicación ya realizó una solicitud a la ruta /sanctum/csrf-cookie
, las solicitudes subsiguientes deben recibir automáticamente protección CSRF siempre que tu cliente HTTP de JavaScript envíe el valor de la cookie XSRF-TOKEN
en la cabecera X-XSRF-TOKEN
.
Por supuesto, si la sesión de tu usuario expira debido a la falta de actividad, las solicitudes subsiguientes a la aplicación Laravel pueden recibir una respuesta de error HTTP 401 o 419. En este caso, debes redirigir al usuario a la página de inicio de sesión de tu SPA.
Advertencia Eres libre de escribir tu propio punto final
/login
; sin embargo, asegúrate de que autentique al usuario utilizando los servicios de autenticación basados en sesiones que proporciona Laravel de forma estándar. Normalmente, esto significa usar la guarda de autenticaciónweb
.
Para proteger rutas para que todas las solicitudes entrantes deban estar autenticadas, debes adjuntar la guarda de autenticación sanctum
a tus rutas API dentro de tu archivo routes/api.php
. Esta guarda garantizará que las solicitudes entrantes estén autenticadas como solicitudes autenticadas con estado desde tu SPA o contengan una cabecera de token de API válida si la solicitud es de un tercero:
use Illuminate\Http\Request; Route::middleware('auth:sanctum')->get('/user', function (Request $request) { return $request->user();});
Si tu SPA necesita autenticarse con canales de difusión privados/presenciales, debes colocar la llamada al método Broadcast::routes
dentro de tu archivo routes/api.php
:
Broadcast::routes(['middleware' => ['auth:sanctum']]);
A continuación, para que las solicitudes de autorización de Pusher tengan éxito, deberás proporcionar un authorizer
personalizado de Pusher al inicializar Laravel Echo. Esto permite que tu aplicación configure Pusher para usar la instancia axios
que está configurada correctamente para solicitudes entre dominios:
window.Echo = new Echo({ broadcaster: "pusher", cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER, encrypted: true, key: import.meta.env.VITE_PUSHER_APP_KEY, authorizer: (channel, options) => { return { authorize: (socketId, callback) => { axios.post('/api/broadcasting/auth', { socket_id: socketId, channel_name: channel.name }) .then(response => { callback(false, response.data); }) .catch(error => { callback(true, error); }); } }; },})
También puedes utilizar tokens de Sanctum para autenticar las solicitudes de tu aplicación móvil a tu API. El proceso para autenticar solicitudes de aplicaciones móviles es similar a autenticar solicitudes de API de terceros; sin embargo, hay pequeñas diferencias en cómo emitir los tokens de API.
Para empezar, crea una ruta que acepte el correo electrónico/nombre de usuario, la contraseña y el nombre del dispositivo del usuario, y luego intercambie esas credenciales por un nuevo token de Sanctum. El "nombre del dispositivo" proporcionado a este punto final es con fines informativos y puede ser cualquier valor que desees. En general, el valor del nombre del dispositivo debería ser un nombre que el usuario reconocería, como "iPhone 12 de Nuno".
Normalmente, harás una solicitud al punto final del token desde la pantalla de "inicio de sesión" de tu aplicación móvil. El punto final devolverá el token de API en texto plano, que luego se puede almacenar en el dispositivo móvil y utilizar para realizar solicitudes adicionales a la API:
use App\Models\User;use Illuminate\Http\Request;use Illuminate\Support\Facades\Hash;use Illuminate\Validation\ValidationException; Route::post('/sanctum/token', function (Request $request) { $request->validate([ 'email' => 'required|email', 'password' => 'required', 'device_name' => 'required', ]); $user = User::where('email', $request->email)->first(); if (! $user || ! Hash::check($request->password, $user->password)) { throw ValidationException::withMessages([ 'email' => ['The provided credentials are incorrect.'], ]); } return $user->createToken($request->device_name)->plainTextToken;});
Cuando la aplicación móvil utiliza el token para realizar una solicitud a tu aplicación, debe pasar el token en la cabecera Authorization
como un token Bearer
.
Nota Cuando emites tokens para una aplicación móvil, también eres libre de especificar habilidades del token.
Como se documentó anteriormente, puedes proteger rutas para que todas las solicitudes entrantes deben estar autenticadas adjuntando la guarda de autenticación sanctum
a las rutas:
Route::middleware('auth:sanctum')->get('/user', function (Request $request) { return $request->user();});
Para permitir a los usuarios revocar tokens de API emitidos a dispositivos móviles, puedes enumerarlos por nombre, junto con un botón "Revocar", dentro de la sección "configuración de la cuenta" de la interfaz de usuario de tu aplicación web. Cuando el usuario hace clic en el botón "Revocar", puedes eliminar el token de la base de datos. Recuerda que puedes acceder a los tokens de API de un usuario mediante la relación tokens
proporcionada por el rasgo Laravel\Sanctum\HasApiTokens
:
// Revocar todos los tokens...$user->tokens()->delete(); // Revocar un token específico...$user->tokens()->where('id', $tokenId)->delete();
Durante las pruebas, el método Sanctum::actingAs
se puede utilizar para autenticar a un usuario y especificar qué habilidades se deben otorgar a su token:
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/task'); $response->assertOk();}
Si deseas otorgar todas las habilidades al token, debes incluir *
en la lista de habilidades proporcionada al método actingAs
:
Sanctum::actingAs( User::factory()->create(), ['*']);