Laravel JWT : authentification stateless pour vos APIs
Sanctum couvre la plupart des besoins d'auth SPA et mobile. Mais quand votre API doit être vérifiée indépendamment par plusieurs services sans session partagée, JWT est le bon outil. Voici comment l'implémenter correctement.
Sanctum gère proprement la majorité des besoins d'auth Laravel,tokens SPA, tokens mobile, tokens API simples. JWT résout un problème plus spécifique : vérifier un token sans toucher une base de données ou un store de session partagé. Si vous n'avez pas ce problème, JWT ajoute de la complexité pour rien.
JWT vs Sanctum : quand vraiment choisir JWT
Un token Sanctum est une ligne en base de données,chaque requête fait une vérification pour confirmer qu'il est toujours valide, ce qui rend aussi la révocation instantanée et simple. Un JWT est auto-suffisant : sa signature seule prouve sa validité, donc tout service détenant la clé publique (ou le secret partagé) peut le vérifier sans toucher votre base. Ça compte quand plusieurs services indépendants doivent vérifier le même token.
Si vous avez une seule app Laravel qui parle à un seul frontend, Sanctum est plus simple et plus sûr. Ne recourir à JWT que lorsque plusieurs services indépendants doivent vérifier des tokens sans store de session partagé.
Anatomie d'un JWT
Un JWT a trois parties : un header (algorithme de signature), un payload (claims,sujet, expiration, données custom), et une signature. La signature empêche la falsification, mais le payload n'est qu'encodé en base64, pas chiffré. Ne jamais mettre de secrets ou de données sensibles dans les claims JWT,n'importe qui peut les décoder et les lire.
Implémentation avec tymon/jwt-auth
// config/auth.php
'guards' => [
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
// AuthController.php
public function login(LoginRequest $request)
{
if (! $token = auth('api')->attempt($request->validated())) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return response()->json([
'access_token' => $token,
'expires_in' => auth('api')->factory()->getTTL() * 60,
]);
}Refresh tokens : la partie souvent mal faite
Garder les access tokens courts (15 minutes à 1 heure) et les associer à un refresh token plus long. Faire tourner le refresh token à chaque utilisation,en émettre un nouveau et invalider l'ancien,pour qu'un refresh token volé ne puisse être utilisé qu'une fois avant que le prochain refresh de l'utilisateur légitime ne révèle le vol.
public function refresh()
{
$newToken = auth('api')->refresh();
return response()->json([
'access_token' => $newToken,
'expires_in' => auth('api')->factory()->getTTL() * 60,
]);
}Pièges de sécurité à éviter
- ✓Attaques par confusion d'algorithme : toujours fixer l'algorithme attendu côté serveur, jamais faire confiance au header alg du token lui-même.
- ✓La révocation est difficile : un JWT volé reste valide jusqu'à expiration. Garder des durées de vie courtes pour l'access token et maintenir une blocklist uniquement pour les refresh tokens.
- ✓Ne jamais stocker les JWT dans le localStorage pour une app navigateur,utiliser des cookies httpOnly pour éviter le vol de token via XSS.
- ✓Toujours valider les claims exp, iss et aud, pas seulement la signature.
JWT résout un problème précis : la vérification stateless entre services indépendants. Si ce n'est pas votre architecture, la simplicité de Sanctum,et sa révocation facile,l'emporte à chaque fois.
Besoin d'aide sur ce sujet ? Conception d'API REST
Découvrir ce service →