Implementando access tokens y refresh tokens en Laravel Sanctum

En el desarrollo de APIs seguras y escalables, la autenticación juega un papel clave. Laravel Sanctum ofrece una solución ligera para gestionar access tokens y refresh tokens, permitiendo un control granular sobre los permisos de cada token. En este artículo, exploramos su implementación, explicamos su funcionamiento y mostramos cómo proteger las rutas con un middleware personalizado.

Laravel Sanctum es una solución ligera para la autenticación de APIs en Laravel. En este artículo, vamos a profundizar en la implementación de access tokens y refresh tokens, explicando su propósito, el middleware necesario y el endpoint para obtener nuevos tokens.

05.03.2025 — Marc Bernet — 5 min read

Introducción a la Autenticación con Tokens

Antes de la llegada de los sistemas basados en tokens, la autenticación en las aplicaciones web dependía principalmente de sesiones en el servidor. Esto funcionaba bien en entornos monolíticos, donde el backend y el frontend estaban en la misma aplicación, pero presentaba problemas en arquitecturas modernas con múltiples clientes (aplicaciones móviles, SPAs, microservicios, etc.).

¿Por qué usar Access Tokens y Refresh Tokens?

El enfoque tradicional de autenticación por sesiones tiene varias limitaciones:

  • Escalabilidad: Requiere almacenamiento en el servidor para cada sesión activa.
  • Distribución: No funciona bien en arquitecturas distribuidas sin compartir estado entre servidores.
  • Manejo de Expiración: Las sesiones suelen durar mucho tiempo o necesitan mecanismos adicionales para renovarlas.

    Los tokens de acceso y de actualización solucionan estos problemas proporcionando:
     

  • Autenticación sin estado: Cada solicitud envía un token firmado sin necesidad de almacenar sesiones en el backend.
  • Mayor seguridad: Los access tokens tienen una vida útil corta y los refresh tokens permiten obtener nuevos access tokens sin necesidad de credenciales del usuario.
  • Compatibilidad con microservicios: Facilitan la autenticación en sistemas distribuidos, permitiendo que múltiples servicios verifiquen la identidad sin acceder a una base de datos central.

Middleware de Protección de Tokens

El middleware TokenAccessGuard se encarga de verificar si un token tiene los permisos adecuados para realizar una acción. Veamos su implementación:
 


namespace App\Http\Middleware;
use App\Enums\TokenAbilityEnum;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class TokenAccessGuard
{
   public function handle(Request $request, Closure $next): Response
   {
       $user = Auth::user();
       if (empty($user)) {
           return $next($request);
       }
       $token = $user->currentAccessToken();
       if ($token) {
           if ($request->routeIs('refresh-token') && $token->cant(TokenAbilityEnum::ISSUE_ACCESS_TOKEN->value)) {
               return response()->json([
                   'message' => 'Unauthorized',
                   'error' => 'Token can not issue access token',
               ], 401);
           } elseif (!$request->routeIs('refresh-token')) {
               if ($token->cant(TokenAbilityEnum::ACCESS_API->value)) {
                   return response()->json([
                       'message' => 'Unauthorized',
                       'error' => 'Token can not access api',
                   ], 401);
               }
           }
       }
       return $next($request);
   }
}

Explicación del Middleware

  • Obtiene el usuario autenticado.
  • Verifica si el token tiene los permisos necesarios:
  • Si la ruta es refresh-token, el token debe tener la habilidad ISSUE_ACCESS_TOKEN.
  • Para el resto de las rutas, el token debe tener la habilidad ACCESS_API.
  • Si el token no cumple con los permisos, devuelve un error 401 Unauthorized.

Endpoint de Refresh Token

Este endpoint permite a los usuarios obtener un nuevo access token utilizando un refresh token válido:

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Enums\TokenAbilityEnum;
use Illuminate\Support\Facades\Route;
Route::post('/refresh-token', function (Request $request) {
   $user = Auth::user();
   if (!$user) {
       return response()->json(['message' => 'Unauthorized'], 401);
   }
   $token = $user->currentAccessToken();
   if ($token->cant(TokenAbilityEnum::ISSUE_ACCESS_TOKEN->value)) {
       return response()->json([
           'message' => 'Unauthorized',
           'error' => 'Token can not issue access token',
       ], 401);
   }
   $newAccessToken = $user->createToken('access_token', [TokenAbilityEnum::ACCESS_API->value]);
   return response()->json([
       'access_token' => $newAccessToken->plainTextToken,
   ]);
});

Explicación del Endpoint

  • Obtiene el usuario autenticado.
  • Verifica si el token actual tiene la capacidad de emitir nuevos access tokens.
  • Si es válido, genera y devuelve un nuevo access token.

Conclusión

Implementar access tokens y refresh tokens en Laravel Sanctum es una estrategia efectiva para mejorar la seguridad de una API. El middleware TokenAccessGuard protege las rutas asegurando que cada token tenga los permisos adecuados, y el endpoint refresh-token permite obtener nuevos access tokens sin necesidad de que el usuario vuelva a autenticarse.

Esta implementación garantiza una autenticación robusta y flexible en cualquier API desarrollada con Laravel.

💡 ¿Cuánto cuesta desarrollar una app para tu negocio? Ver precios