Implementació d’access tokens i refresh tokens en Laravel Sanctum

En el desenvolupament d’APIs segures i escalables, l’autenticació té un paper clau. Laravel Sanctum ofereix una solució lleugera per gestionar access tokens i refresh tokens, permetent un control granular sobre els permisos de cada token. En aquest article, explorem la seva implementació, expliquem el seu funcionament i mostrem com protegir les rutes amb un middleware personalitzat.

Laravel Sanctum és una solució lleugera per a l’autenticació d’APIs en Laravel. En aquest article, aprofundirem en la implementació d’access tokens i refresh tokens, explicant el seu propòsit, el middleware necessari i l’endpoint per obtenir nous tokens.

05.03.2025 — Marc Bernet — 5 min read

Introducció a l’Autenticació amb Tokens
 

Abans de l’arribada dels sistemes basats en tokens, l’autenticació a les aplicacions web depenia principalment de sessions al servidor. Això funcionava bé en entorns monolítics, on el backend i el frontend estaven en la mateixa aplicació, però presentava problemes en arquitectures modernes amb múltiples clients (aplicacions mòbils, SPAs, microserveis, etc.).

Per què utilitzar Access Tokens i Refresh Tokens?

L’enfocament tradicional d’autenticació per sessions té diverses limitacions:
    •    Escalabilitat: Requereix emmagatzematge al servidor per a cada sessió activa.
    •    Distribució: No funciona bé en arquitectures distribuïdes sense compartir estat entre servidors.
    •    Gestió de l’expiració: Les sessions solen durar molt de temps o necessiten mecanismes addicionals per renovar-les.

Els access tokens i refresh tokens solucionen aquests problemes proporcionant:
    •    Autenticació sense estat: Cada petició envia un token signat sense necessitat d’emmagatzemar sessions al backend.
    •    Major seguretat: Els access tokens tenen una vida útil curta i els refresh tokens permeten obtenir nous access tokens sense necessitat de credencials de l’usuari.
    •    Compatibilitat amb microserveis: Faciliten l’autenticació en sistemes distribuïts, permetent que múltiples serveis verifiquin la identitat sense accedir a una base de dades central.

Middleware de Protecció de Tokens

El middleware TokenAccessGuard s’encarrega de verificar si un token té els permisos adequats per realitzar una acció. Vegem la seva implementació:
 


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ó del Middleware

    •    Obté l’usuari autenticat.
    •    Verifica si el token té els permisos necessaris:
    •    Si la ruta és refresh-token, el token ha de tenir l’habilitat ISSUE_ACCESS_TOKEN.
    •    Per a la resta de rutes, el token ha de tenir l’habilitat ACCESS_API.
    •    Si el token no compleix amb els permisos requerits, retorna un error 401 Unauthorized.

Endpoint de Refresh Token

Aquest endpoint permet als usuaris obtenir un nou access token utilitzant un refresh token vàlid:

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ó de l’Endpoint
    •    Obté l’usuari autenticat.
    •    Verifica si el token actual té la capacitat d’emetre nous access tokens.
    •    Si és vàlid, genera i retorna un nou access token.

Conclusió

Implementar access tokens i refresh tokens en Laravel Sanctum és una estratègia efectiva per millorar la seguretat d’una API. El middleware TokenAccessGuard protegeix les rutes assegurant que cada token tingui els permisos adequats, i l’endpoint refresh-token permet obtenir nous access tokens sense necessitat que l’usuari torni a autenticar-se.

Aquesta implementació garanteix una autenticació robusta i flexible en qualsevol API desenvolupada amb Laravel.

💡 Quant costa desenvolupar una app per al teu negoci? Descobreix els preus