Construire une API Laravel sécurisée avec l’authentification JWT
L’authentification JWT (JSON Web Token) dans Laravel fournit un mécanisme cryptographiquement signé et sans état pour vérifier les consommateurs d’API sans stockage de session côté serveur. Un JWT encode une charge utile — généralement l’identité de l’utilisateur et des revendications — dans une chaîne compacte et sûre pour les URL, signée avec un secret ou une clé RSA, permettant à tout service détenant la clé de vérification de valider le token de manière indépendante.
Ce guide couvre l’implémentation complète de l’authentification JWT dans une API Laravel en utilisant le package `tymon/jwt-auth`, incluant la configuration, la configuration du modèle, la logique du contrôleur, la protection des routes, la stratégie de rafraîchissement des tokens et le renforcement en production. Chaque étape inclut un contexte technique qui va au-delà des tutoriels de surface.
Prérequis et hypothèses d’environnement
Avant de commencer, confirmez les points suivants :
- PHP 8.1 ou supérieur (PHP 8.2 recommandé pour Laravel 11)
- Laravel 10 ou 11 installé via Composer
- Composer 2.x
- MySQL 8.0, PostgreSQL 15, ou toute base de données compatible PDO
- Un fichier `.env` configuré avec des identifiants `DB_*` valides
- Familiarité de base avec le conteneur de services, les middlewares et l’ORM Eloquent de Laravel
Si vous déployez cette API dans un environnement de production, un plan Hébergement VPS avec accès root complet vous donne le contrôle nécessaire pour configurer PHP-FPM, gérer les variables d’environnement de manière sécurisée et définir correctement les permissions de fichiers — tous essentiels pour la gestion des secrets JWT.
Étape 1 : Créer un nouveau projet Laravel
“`bash
composer create-project laravel/laravel laravel-jwt-api
cd laravel-jwt-api
“`
Vérifiez l’installation :
“`bash
php artisan –version
“`
Définissez votre clé d’application si elle n’a pas été générée automatiquement :
“`bash
php artisan key:generate
“`
La `APP_KEY` dans `.env` est distincte du secret JWT. Les deux sont requis et servent des objectifs cryptographiques différents — `APP_KEY` protège les cookies chiffrés et les données de session, tandis que `JWT_SECRET` signe les tokens.
Étape 2 : Installer le package d’authentification JWT
Le package `tymon/jwt-auth` est le standard de facto pour JWT dans Laravel. Installez-le :
“`bash
composer require tymon/jwt-auth
“`
Publiez la configuration du package :
“`bash
php artisan vendor:publish –provider="TymonJWTAuthProvidersLaravelServiceProvider"
“`
Cela crée `config/jwt.php`, qui contrôle la durée de vie des tokens, la durée de vie du rafraîchissement, l’algorithme, le comportement de la liste noire et les revendications requises. Examinez attentivement ce fichier — les valeurs par défaut sont raisonnables pour le développement mais nécessitent un ajustement pour la production.
Paramètres de configuration clés dans `config/jwt.php` :
| Paramètre | Défaut | Recommandation pour la production |
|---|
| — | — | — |
|---|
| `ttl` | 60 minutes | 15–30 minutes |
|---|
| `refresh_ttl` | 20160 minutes (2 semaines) | 1440–10080 minutes |
|---|
| `algo` | `HS256` | `RS256` pour les systèmes distribués |
|---|
| `blacklist_enabled` | `true` | Doit être `true` |
|---|
| `blacklist_grace_period` | 0 seconde | 10–30 secondes pour les requêtes simultanées |
|---|
| `required_claims` | `['iss','iat','exp','nbf','sub','jti']` | Conserver tout ; ajouter `aud` pour les API multi-locataires |
|---|
Étape 3 : Générer la clé secrète JWT
“`bash
php artisan jwt:secret
“`
Cela ajoute `JWT_SECRET` à votre fichier `.env`. Cette valeur est utilisée comme clé de signature HMAC-SHA256 pour tous les tokens lors de l’utilisation de l’algorithme `HS256` par défaut.
Notes de sécurité critiques :
- Ne jamais valider `.env` dans le contrôle de version. Ajoutez-le immédiatement à `.gitignore`.
- Sur un pipeline de déploiement partagé, injectez `JWT_SECRET` comme variable d’environnement via votre système CI/CD plutôt que de le stocker dans un fichier.
- Si vous faites pivoter le secret, tous les tokens existants sont immédiatement invalidés. Planifiez les fenêtres de rotation en conséquence et communiquez-les aux consommateurs de l’API.
- Pour les architectures de microservices où plusieurs services doivent vérifier les tokens, passez à `RS256`. Générez une paire de clés RSA, stockez la clé privée sur le service d’authentification et distribuez uniquement la clé publique aux services consommateurs.
Étape 4 : Configurer le garde d’authentification
Ouvrez `config/auth.php` et mettez à jour les sections des valeurs par défaut et des gardes :
“`php
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
“`
Cela indique au système d’authentification de Laravel d’utiliser le driver JWT lors de la résolution du garde `api`. Le middleware `auth:api` déléguera désormais la validation des tokens à `tymon/jwt-auth` au lieu de Laravel Passport ou du driver de token par défaut.
Ne supprimez pas le garde `web`. De nombreux composants internes de Laravel en dépendent, et sa suppression provoque des échecs inattendus dans les commandes console et les workers de file d’attente qui interagissent avec le système d’authentification.
Étape 5 : Créer le modèle utilisateur et la migration
Si le modèle `User` par défaut et la migration existent déjà (c’est le cas dans une installation fraîche de Laravel), vous pouvez les modifier directement. Si vous partez de zéro :
“`bash
php artisan make:model User -m
“`
Ouvrez le fichier de migration dans `database/migrations/` et définissez le schéma :
“`php
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
“`
Exécutez la migration :
“`bash
php artisan migrate
“`
Note de production : Exécutez toujours les migrations avec l’indicateur `–force` dans les environnements de production où `APP_ENV=production`, car Laravel demandera une confirmation sinon :
“`bash
php artisan migrate –force
“`
Étape 6 : Implémenter l’interface JWTSubject dans le modèle utilisateur
Le package `tymon/jwt-auth` exige que votre modèle authentifiable implémente le contrat `JWTSubject`. Ouvrez `app/Models/User.php` :
“`php
<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateFoundationAuthUser as Authenticatable;
use IlluminateNotificationsNotifiable;
use TymonJWTAuthContractsJWTSubject;
class User extends Authenticatable implements JWTSubject
{
use HasFactory, Notifiable;
protected $fillable = [
'name',
'email',
'password',
];
protected $hidden = [
'password',
'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
/**
- Get the identifier that will be stored in the JWT subject claim.
*/
public function getJWTIdentifier(): mixed
{
return $this->getKey();
}
/**
- Return a key-value array of arbitrary claims to add to the JWT payload.
*/
public function getJWTCustomClaims(): array
{
return [];
}
}
“`
Sur les revendications personnalisées : La méthode `getJWTCustomClaims()` est l’endroit où vous intégrez des données spécifiques à l’application directement dans la charge utile du token. Les cas d’utilisation courants incluent l’intégration de `role`, `tenant_id` ou `permissions` afin que les services en aval puissent prendre des décisions d’autorisation sans requête de base de données. Soyez délibéré dans ce que vous intégrez — chaque revendication augmente la taille du token et est lisible par quiconque décode la charge utile en base64. N’intégrez jamais de données sensibles comme des mots de passe ou des informations personnellement identifiables.
Étape 7 : Construire le contrôleur d’authentification
“`bash
php artisan make:controller AuthController
“`
Remplissez `app/Http/Controllers/AuthController.php` avec la logique d’authentification complète :
“`php
<?php
namespace AppHttpControllers;
use AppModelsUser;
use IlluminateHttpJsonResponse;
use IlluminateHttpRequest;
use IlluminateSupportFacadesAuth;
use IlluminateSupportFacadesHash;
use IlluminateValidationValidationException;
use TymonJWTAuthExceptionsJWTException;
use TymonJWTAuthFacadesJWTAuth;
class AuthController extends Controller
{
/**
- Register a new user and return a JWT.
*/
public function register(Request $request): JsonResponse
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:8|confirmed',
]);
$user = User::create([
'name' => $validated['name'],
'email' => $validated['email'],
'password' => Hash::make($validated['password']),
]);
$token = JWTAuth::fromUser($user);
return response()->json([
'token' => $token,
'token_type' => 'bearer',
'expires_in' => auth('api')->factory()->getTTL() * 60,
], 201);
}
/**
- Authenticate a user and return a JWT.
*/
public function login(Request $request): JsonResponse
{
$credentials = $request->validate([
'email' => 'required|string|email',
'password' => 'required|string',
]);
if (!$token = Auth::guard('api')->attempt($credentials)) {
return response()->json(['error' => 'Invalid credentials'], 401);
}
return $this->respondWithToken($token);
}
/**
- Invalidate the current token (logout).
*/
public function logout(): JsonResponse
{
try {
Auth::guard('api')->logout();
} catch (JWTException $e) {
return response()->json(['error' => 'Failed to invalidate token'], 500);
}
return response()->json(['message' => 'Successfully logged out']);
}
/**
- Refresh the current token.
*/
public function refresh(): JsonResponse
{
try {
$token = Auth::guard('api')->refresh();
} catch (JWTException $e) {
return response()->json(['error' => 'Token cannot be refreshed'], 401);
}
return $this->respondWithToken($token);
}
/**
- Return the authenticated user's profile.
*/
public function me(): JsonResponse
{
return response()->json(Auth::guard('api')->user());
}
/**
- Format the token response consistently.
*/
protected function respondWithToken(string $token): JsonResponse
{
return response()->json([
'token' => $token,
'token_type' => 'bearer',
'expires_in' => auth('api')->factory()->getTTL() * 60,
]);
}
}
“`
Pourquoi la spécification explicite du garde est importante : Appeler `Auth::attempt()` sans spécifier le garde revient au garde par défaut. Si vous avez changé le défaut en `api`, cela fonctionne — mais c’est fragile. Appelez toujours `Auth::guard('api')->attempt()` explicitement pour éviter des bugs subtils lorsque le garde par défaut change lors d’une refactorisation.
Étape 8 : Définir les routes API
Ouvrez `routes/api.php` et définissez les routes d’authentification et les routes protégées :
“`php
<?php
use AppHttpControllersAuthController;
use IlluminateSupportFacadesRoute;
// Public authentication routes
Route::prefix('auth')->group(function () {
Route::post('register', [AuthController::class, 'register']);
Route::post('login', [AuthController::class, 'login']);
});
// Protected routes — require a valid JWT
Route::middleware('auth:api')->prefix('auth')->group(function () {
Route::post('logout', [AuthController::class, 'logout']);
Route::post('refresh', [AuthController::class, 'refresh']);
Route::get('me', [AuthController::class, 'me']);
});
// Example protected resource routes
Route::middleware('auth:api')->group(function () {
Route::apiResource('posts', AppHttpControllersPostController::class);
});
“`
Stratégie de préfixe de route : Regrouper les points de terminaison d’authentification sous `/api/auth/` est une convention largement adoptée qui rend la documentation de l’API plus claire et simplifie les règles de limitation de débit — vous pouvez appliquer une limitation plus stricte à `/api/auth/login` indépendamment des points de terminaison de ressources.
Étape 9 : Protéger les routes et gérer les échecs de middleware
Le middleware `auth:api` de Laravel retournera une réponse `401 Unauthenticated` lorsqu’un token est manquant, expiré ou invalide. Pour retourner une réponse JSON cohérente au lieu d’une redirection HTML, remplacez la méthode `unauthenticated` dans `app/Exceptions/Handler.php` :
“`php
use IlluminateAuthAuthenticationException;
use IlluminateHttpRequest;
protected function unauthenticated($request, AuthenticationException $exception)
{
if ($request->expectsJson() || $request->is('api/*')) {
return response()->json(['error' => 'Unauthenticated'], 401);
}
return redirect()->guest(route('login'));
}
“`
Sans cette substitution, les clients API reçoivent une redirection HTML 302 vers une page de connexion qui n’existe pas dans une application purement API — une source courante de confusion lors des tests d’intégration.
Étape 10 : Stratégie de rafraîchissement des tokens et liste noire
La nature sans état de JWT crée une tension : les tokens sont autonomes et valides jusqu’à leur expiration, mais vous avez besoin d’un moyen de les révoquer lors de la déconnexion. Le package `tymon/jwt-auth` résout cela avec une liste noire de tokens soutenue par le driver de cache Laravel.
Fonctionnement de la liste noire :
- Lors de la déconnexion, la revendication `jti` (ID JWT) du token est stockée dans le cache avec une durée de vie correspondant à la durée de vie restante du token.
- À chaque requête authentifiée, le middleware vérifie la liste noire avant d’accepter le token.
- Le paramètre `blacklist_grace_period` permet une brève fenêtre où un token en cours de rafraîchissement peut encore être utilisé, évitant les conditions de concurrence dans les clients qui effectuent des requêtes simultanées.
Assurez-vous que votre driver de cache prend cela en charge. Le driver `file` par défaut fonctionne pour les déploiements sur un seul serveur. Pour les API à mise à l’échelle horizontale fonctionnant sur plusieurs nœuds — courant lors de l’utilisation de Serveurs Dédiés dans une configuration à équilibrage de charge — passez à Redis ou Memcached :
“`env
CACHE_DRIVER=redis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
“`
Flux de rafraîchissement des tokens :
“`
Client API Server
| — POST /api/auth/refresh ——> |
|---|
| Authorization: Bearer <old> |
|---|
| — Validate old token |
|---|
| — Blacklist old token's jti |
|---|
| — Issue new token |
|---|
| <– 200 { token: <new> } ——– |
|---|
“`
L’ancien token est immédiatement mis en liste noire lors du rafraîchissement. Les clients doivent stocker le nouveau token et supprimer l’ancien. Implémentez cela comme un intercepteur Axios ou équivalent dans votre frontend pour gérer le rafraîchissement des tokens de manière transparente.
Étape 11 : Tester l’API
Utilisez `curl` ou Postman pour vérifier chaque point de terminaison.
Enregistrer un utilisateur :
“`bash
curl -X POST https://your-domain.com/api/auth/register
-H "Content-Type: application/json"
-d '{
"name": "Jane Smith",
"email": "jane@example.com",
"password": "SecurePass123!",
"password_confirmation": "SecurePass123!"
}'
“`
Réponse attendue (`201 Created`) :
“`json
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9…",
"token_type": "bearer",
"expires_in": 3600
}
“`
Se connecter :
“`bash
curl -X POST https://your-domain.com/api/auth/login
-H "Content-Type: application/json"
-d '{"email": "jane@example.com", "password": "SecurePass123!"}'
“`
Accéder à une route protégée :
“`bash
curl -X GET https://your-domain.com/api/auth/me
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9…"
“`
Rafraîchir le token :
“`bash
curl -X POST https://your-domain.com/api/auth/refresh
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9…"
“`
Se déconnecter :
“`bash
curl -X POST https://your-domain.com/api/auth/logout
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9…"
“`
JWT vs. Session vs. Laravel Sanctum vs. Passport
Comprendre quand JWT est le bon choix nécessite de le comparer aux alternatives disponibles dans l’écosystème Laravel.
| Critère | JWT (`tymon/jwt-auth`) | Laravel Sanctum | Laravel Passport | Basé sur la session |
|---|
| — | — | — | — | — |
|---|
| **État** | Sans état | Sans état (tokens SPA) / Avec état (cookies) | Avec état (tokens DB) | Avec état |
|---|
| **Stockage des tokens** | Côté client | Côté client ou cookie | Base de données | Session côté serveur |
|---|
| **Révocation** | Liste noire (cache) | Immédiate (suppression DB) | Immédiate (suppression DB) | Immédiate |
|---|
| **Évolutivité** | Excellente (pas de DB par requête) | Bonne | Modérée (recherche DB par requête) | Faible (synchronisation de session nécessaire) |
|---|
| **Support OAuth2** | Non | Non | Oui (serveur OAuth2 complet) | Non |
|---|
| **Complexité** | Moyenne | Faible | Élevée | Faible |
|---|
| **Idéal pour** | API sans état, microservices | SPA, applications mobiles | Clients OAuth tiers | Applications web traditionnelles |
|---|
| **Introspection des tokens** | Décoder la charge utile côté client | Nécessite un appel API | Nécessite un appel API | N/A |
|---|
Quand choisir JWT plutôt que Sanctum : Si votre API est consommée par des clients tiers, des applications mobiles ou des microservices qui ne peuvent pas partager un cookie de session ou une connexion de base de données avec votre application Laravel, la nature autonome de JWT est un avantage significatif. Si vous construisez une SPA propriétaire sur le même domaine, Sanctum avec l’authentification basée sur les cookies est plus simple et évite entièrement les problèmes de sécurité liés au stockage des tokens.
Renforcement de la sécurité en production
Une implémentation JWT fonctionnelle n’est pas sécurisée par défaut. Appliquez ces mesures de renforcement avant la mise en production :
1. Imposer HTTPS de manière inconditionnelle
Les tokens JWT transmis via HTTP sont facilement interceptables. Imposez TLS au niveau du serveur web et redirigez tout le trafic HTTP. Associez cela à un Certificat SSL pour garantir un transport chiffré pour chaque requête API.
2. Définir des durées de vie de tokens agressives
Les tokens d’accès à courte durée de vie (15–30 minutes) combinés avec des tokens de rafraîchissement à plus longue durée de vie (7–14 jours) limitent l’impact d’un token volé. Mettez à jour `config/jwt.php` :
“`php
'ttl' => 15,
'refresh_ttl' => 10080,
“`
3. Appliquer une limitation de débit aux points de terminaison d’authentification
Le middleware throttle intégré de Laravel prévient les attaques par force brute :
“`php
Route::middleware(['throttle:10,1'])->group(function () {
Route::post('auth/login', [AuthController::class, 'login']);
Route::post('auth/register', [AuthController::class, 'register']);
});
“`
Cela limite chaque IP à 10 requêtes par minute sur les points de terminaison d’authentification.
4. Valider la revendication `aud` pour les API multi-locataires
Si votre API sert plusieurs applications clientes, intégrez et validez une revendication `audience` pour empêcher la réutilisation des tokens entre les services :
“`php
// In getJWTCustomClaims()
return [
'aud' => config('app.jwt_audience'),
];
“`
5. Protéger le JWT_SECRET au niveau du système d’exploitation
Définissez des permissions de fichier restrictives sur `.env` :
“`bash
chmod 640 .env
chown www-data:www-data .env
“`
Sur un VPS avec cPanel correctement configuré, vous pouvez gérer la propriété et les permissions des fichiers via le Gestionnaire de fichiers ou SSH sans risquer d’exposer des secrets à d’autres utilisateurs du système.
6. Journaliser les événements d’authentification
Intégrez le système d’événements de Laravel pour journaliser les tentatives de connexion échouées, les rafraîchissements de tokens et les déconnexions vers un service de journalisation centralisé. Ceci est essentiel pour la détection des anomalies.
Ajout du contrôle d’accès basé sur les rôles
Les revendications personnalisées facilitent l’intégration des rôles directement dans le token :
“`php
// In User model
public function getJWTCustomClaims(): array
{
return [
'role' => $this->role, // e.g., 'admin', 'editor', 'viewer'
];
}
“`
Créez un middleware pour imposer les exigences de rôle :
“`php
<?php
namespace AppHttpMiddleware;
use Closure;
use IlluminateHttpRequest;
use TymonJWTAuthFacadesJWTAuth;
class RoleMiddleware
{
public function handle(Request $request, Closure $next, string $role): mixed
{
$payload = JWTAuth::parseToken()->getPayload();
if ($payload->get('role') !== $role) {
return response()->json(['error' => 'Forbidden'], 403);
}
return $next($request);
}
}
“`
Enregistrez-le dans `app/Http/Kernel.php` (Laravel 10) ou `bootstrap/app.php` (Laravel 11) et appliquez-le aux routes :
“`php
Route::middleware(['auth:api', 'role:admin'])->group(function () {
Route::apiResource('admin/users', AdminUserController::class);
});
“`
Mise en garde : Les données de rôle intégrées dans le token sont aussi récentes que le token lui-même. Si le rôle d’un utilisateur change, l’ancien token continue d’accorder l’ancien rôle jusqu’à son expiration ou son rafraîchissement. Pour les changements de rôle à haute sécurité (par exemple, révoquer immédiatement l’accès administrateur), combinez la mise en liste noire des tokens avec une courte durée de vie ou effectuez une vérification de rôle en base de données dans le middleware en parallèle de la vérification des revendications.
Considérations de déploiement pour les API Laravel JWT
Lors du passage du développement local à un serveur de production, plusieurs facteurs spécifiques à l’environnement affectent le comportement de JWT :
- Cohérence des fuseaux horaires : Les revendications `iat`, `nbf` et `exp` de JWT sont des horodatages Unix. Assurez-vous que le fuseau horaire de votre serveur est défini sur UTC (`date.timezone = UTC` dans `php.ini`) pour éviter le rejet des tokens dû à un décalage d’horloge.
- OPcache : Activez PHP OPcache pour réduire la surcharge liée au chargement des fichiers de la bibliothèque JWT à chaque requête. Cela est particulièrement impactant sur les API à fort trafic.
- Workers de file d’attente pour le nettoyage des tokens : Si vous implémentez des tâches personnalisées de nettoyage de la liste noire des tokens, assurez-vous que votre worker de file d’attente s’exécute en tant que processus supervisé (Supervisor ou systemd).
- Gestion des variables d’environnement : Sur les Panneaux de contrôle VPS, utilisez le gestionnaire de variables d’environnement du panneau plutôt que de modifier `.env` directement en production, pour éviter les écrasements accidentels lors des déploiements.
Liste de contrôle avant la mise en production
Utilisez cette liste de contrôle pour vérifier que votre implémentation est prête pour la production :
- `JWT_SECRET` fait au moins 32 caractères, est généré aléatoirement et n’est pas validé dans le contrôle de version
- `blacklist_enabled` est défini sur `true` dans `config/jwt.php`
- La durée de vie des tokens est de 30 minutes ou moins pour les tokens d’accès
- La durée de vie du rafraîchissement est définie sur une valeur appropriée à votre politique de session
- Tous les points de terminaison API sont servis exclusivement via HTTPS
- La limitation de débit est appliquée aux points de terminaison `/login` et `/register`
- Le gestionnaire d’exceptions `unauthenticated` retourne du JSON, pas une redirection HTML
- Les revendications personnalisées ne contiennent pas de mots de passe, secrets ou informations personnellement identifiables sensibles
- Le driver de cache est Redis ou Memcached (pas `file`) dans les déploiements multi-serveurs
- Les événements d’authentification sont journalisés et surveillés
- Les changements de rôle nécessitant un effet immédiat sont gérés via la mise en liste noire, pas uniquement par l’expiration des revendications
- Les permissions du fichier `.env` sont restreintes à l’utilisateur du serveur web
FAQ
Quelle est la différence entre `JWT_SECRET` et `APP_KEY` dans Laravel ?
`APP_KEY` est utilisé par le service de chiffrement de Laravel pour chiffrer les cookies, les données de session et les valeurs passées via `Crypt::encrypt()`. `JWT_SECRET` est utilisé exclusivement par `tymon/jwt-auth` pour signer et vérifier les JSON Web Tokens. Ils sont cryptographiquement indépendants et servent des objectifs entièrement différents. Les deux doivent être gardés secrets.
Pourquoi mon token JWT continue-t-il à retourner 401 même s’il n’a pas expiré ?
Les causes les plus courantes sont : le token a été mis en liste noire (par exemple, après une déconnexion ou un rafraîchissement), le `JWT_SECRET` a été pivoté après l’émission du token, le driver de cache stockant la liste noire est indisponible, ou il y a un décalage d’horloge entre le serveur émetteur et le serveur de validation dépassant le paramètre `leeway` dans `config/jwt.php`. Vérifiez chacun de ces points dans l’ordre.
Puis-je utiliser l’authentification JWT avec les files d’attente Laravel ou les commandes console ?
JWT est conçu pour l’authentification des requêtes HTTP. Dans les tâches de file d’attente ou les commandes Artisan, il n’y a pas de contexte de requête HTTP, vous ne pouvez donc pas résoudre un utilisateur à partir d’un token via un middleware. Passez plutôt la clé primaire de l’utilisateur comme paramètre de tâche et chargez le modèle directement avec `User::find($userId)`.
Comment gérer les requêtes simultanées lors du rafraîchissement des tokens sans obtenir d’erreurs 401 ?
Définissez `blacklist_grace_period` dans `config/jwt.php` sur une valeur entre 10 et 30 secondes. Durant cette fenêtre, un token qui vient d’être rafraîchi (et techniquement mis en liste noire) sera encore accepté. Cela prévient les conditions de concurrence dans les clients qui envoient plusieurs requêtes simultanées pendant qu’un rafraîchissement est en cours.
`tymon/jwt-auth` est-il compatible avec Laravel 11 ?
Au cours du cycle de publication actuel, `tymon/jwt-auth` version `2.x` prend en charge Laravel 10 et 11 via la branche `dev-develop` ou les versions taguées qui déclarent la compatibilité. Vérifiez toujours les contraintes `composer.json` du package et le suivi des problèmes GitHub avant de mettre à niveau les versions de Laravel dans un projet qui dépend de ce package. Envisagez d’épingler la version du package dans `composer.json` pour éviter des changements cassants inattendus lors des `composer update`.
