.NET
Authentification JWT : Guide d'implémentation complet
Mettre en place une authentification sécurisée est un défi crucial pour les API web et applications modernes. Les JSON Web Tokens (JWT) sont devenus la solution standard de l'industrie pour l'authentification sans état, permettant aux serveurs de vérifier l'identité des utilisateurs sans maintenir de session côté serveur. À la fin de ce guide, vous comprendrez l'architecture complète de l'authentification basée sur JWT, serez capable d'implémenter l'émission et la validation sécurisées des tokens dans vos propres applications, et disposerez d'une stratégie prête pour la production concernant la gestion du cycle de vie des tokens. Vous repartirez avec les connaissances pratiques nécessaires pour implémenter l'authentification JWT de manière sécurisée dans n'importe quelle pile technologique.
Ce que vous allez apprendre
Vous comprendrez comment les JWT fonctionnent sur le plan architectural, pourquoi une implémentation correcte est importante pour la sécurité, et acquerrez des connaissances pratiques pour configurer un middleware d'authentification, émettre des tokens et protéger les points d'accès API. À la fin, vous serez équipé pour implémenter l'authentification JWT dans vos propres projets en toute confiance dans les décisions de sécurité que vous prendrez.
Comprendre l'architecture de l'authentification JWT
Avant de plonger dans le code, il est essentiel de comprendre comment fonctionne l'authentification JWT. Un JSON Web Token est un moyen compact et sûr pour les URL de représenter des revendications entre deux parties. Le token se compose de trois parties encodées en Base64URL et séparées par des points : l'en-tête, la charge utile et la signature (header.payload.signature).
Le flux d'authentification JWT suit un schéma clair : un client s'authentifie (généralement via un point d'accès de connexion), reçoit un token signé, puis inclut ce token dans l'en-tête Authorization des requêtes suivantes. Le serveur valide la signature et les revendications du token à chaque requête, rendant le système sans état — aucun stockage de session côté serveur n'est nécessaire.
Composants clés d'un JWT
| Composant | Objectif | Exemple |
|---|---|---|
| En-tête | Spécifie l'algorithme de signature et le type de token | {"alg":"RS256","typ":"JWT"} |
| Charge utile | Contient les revendications (données utilisateur, expiration, émetteur) | {"sub":"user123","exp":1700000000} |
| Signature | Garantit l'intégrité et l'authenticité du token | Hachage cryptographique de l'en-tête+charge utile avec la clé secrète |
Cette conception rend les JWT idéaux pour les systèmes distribués et les microservices où le maintien d'un état de session partagé serait peu pratique.
Comment implémenter l'authentification JWT : Guide étape par étape
Les étapes suivantes décrivent une approche prête pour la production pour implémenter l'authentification JWT. Bien que les exemples utilisent .NET et Node.js, les principes s'appliquent à tous les langages de programmation.
Étape 1 : Installer les packages d'authentification requis
Les frameworks modernes fournissent des gestionnaires d'authentification JWT Bearer officiels. Pour .NET, installez le package Microsoft.AspNetCore.Authentication.JwtBearer. Pour Node.js, utilisez jsonwebtoken.
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
# Node.js
npm install jsonwebtoken bcryptjs dotenv
S'appuyer sur des bibliothèques officielles et éprouvées est essentiel — n'implémentez jamais votre propre logique de signature cryptographique.
Étape 2 : Configurer les services d'authentification
La configuration d'authentification définit comment votre API valide les tokens entrants. Les paramètres de validation critiques incluent :
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options => {
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true, // Vérifie que le token provient d'une autorité connue
ValidateAudience = true, // Vérifie que le token est destiné à cette API
ValidateLifetime = true, // Rejette automatiquement les tokens expirés
ValidateIssuerSigningKey = true, // Vérifie la signature cryptographique
ValidIssuer = "https://votre-fournisseur-d-identite.com",
ValidAudience = "https://votre-api.com",
IssuerSigningKey = clePublique // La clé pour la vérification de la signature
};
});
Les quatre indicateurs de validation doivent être définis sur true en production. Désactiver l'un d'entre eux crée des vulnérabilités de sécurité. La IssuerSigningKey peut être chargée à partir d'un fichier PEM ou, en production, récupérée automatiquement depuis le point d'accès des métadonnées du fournisseur d'identité.
Étape 3 : Ajouter le middleware d'authentification et d'autorisation
L'ordre des composants middleware est crucial — l'authentification doit s'exécuter avant l'autorisation :
app.UseAuthentication(); // Valide le JWT et remplit HttpContext.User
app.UseAuthorization(); // Applique les politiques [Authorize] sur les points d'accès protégés
Lorsqu'une requête atteint UseAuthentication, le gestionnaire examine l'en-tête Authorization, valide le JWT et crée un ClaimsPrincipal représentant l'utilisateur authentifié. Cet objet est ensuite disponible tout au long du pipeline de requête pour les décisions d'autorisation.
Étape 4 : Protéger les points d'accès avec l'attribut [Authorize]
La sécurisation des points d'accès API nécessite l'attribut [Authorize] :
[Authorize]
[ApiController]
[Route("api/[controller]")]
public class SecureController : ControllerBase
{
[HttpGet]
public IActionResult GetSecureData()
{
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
return Ok($"Utilisateur authentifié : {userId}");
}
}
Les requêtes sans token valide reçoivent une réponse 401 Non autorisé. Lorsque l'authentification réussit mais que les autorisations requises sont insuffisantes, l'API renvoie 403 Interdit.
Étape 5 : Implémenter l'émission de tokens (Développement uniquement)
En production, l'émission de tokens appartient à un fournisseur d'identité (IdP) dédié implémentant OAuth 2.0 ou OpenID Connect. Le rôle de l'API se limite à la validation.
Cependant, pour le développement et les tests, vous pouvez avoir besoin d'un point d'accès local pour les tokens :
// Exemple Node.js avec jsonwebtoken
router.post('/login', async (req, res) => {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user || !(await bcrypt.compare(password, user.password))) {
return res.status(401).json({ message: 'Identifiants invalides' });
}
const token = jwt.sign(
{ id: user._id, email: user.email },
process.env.JWT_SECRET,
{ expiresIn: '15m' } // Tokens d'accès à courte durée de vie
);
res.json({ token });
});
Les tokens d'accès doivent avoir des durées de vie courtes — généralement 15 minutes — pour limiter les dommages en cas de vol de token.
Bonnes pratiques de sécurité pour la production
Ne jamais stocker les tokens dans le LocalStorage
Pour les applications web, stockez les JWT dans des cookies HttpOnly et Secure plutôt que dans localStorage ou sessionStorage. Cela empêche les attaques de script intersite (XSS) d'accéder aux tokens. La configuration des cookies doit inclure :
HttpOnly: true // Empêche l'accès JavaScript
Secure: true // Uniquement envoyé via HTTPS
SameSite: Lax ou Strict // Protection CSRF
Utiliser la rotation des tokens de rafraîchissement
Étant donné que les tokens d'accès expirent rapidement, implémentez un mécanisme de token de rafraîchissement pour maintenir les sessions utilisateur sans nécessiter de ré-authentification :
- Token de rafraîchissement : Longue durée de vie (ex. 7 jours), stocké de manière sécurisée sur le serveur
- Token d'accès : Courte durée de vie (ex. 15 minutes), envoyé avec chaque requête
- Rotation : Chaque demande de rafraîchissement émet une nouvelle paire accès+rafraîchissement, invalidant l'ancien token de rafraîchissement
Cette approche atténue l'impact des tokens volés et permet une fonctionnalité de déconnexion propre.
Utiliser la signature asymétrique (RS256/ES256) pour la production
Utilisez des algorithmes asymétriques (RS256 ou ES256) plutôt que HMAC (HS256) en production :
| Algorithme | Type de clé | Cas d'utilisation |
|---|---|---|
| HS256 | Symétrique (secret partagé) | Applications à service unique |
| RS256/ES256 | Asymétrique (clé publique/privée) | Systèmes multi-services, microservices |
La signature asymétrique permet à plusieurs services de vérifier les tokens à l'aide d'une clé publique tandis que seul l'émetteur détient la clé privée — suivant le principe du moindre privilège.
Valider toutes les revendications standard
Les revendications suivantes sont requises pour les tokens d'accès OAuth 2.0 et doivent être validées :
iss(Émetteur) — correspond à l'autorité attendueaud(Audience) — correspond à l'identifiant de votre APIexp(Expiration) — token non expirésub(Sujet) — identifiant utilisateuriat(Émis à) — token émis dans le passéjti(ID JWT) — identifiant unique pour le suivi des tokens
Authentification sans état avec Redis
Bien que les JWT soient sans état par conception, l'implémentation de la révocation des tokens nécessite une couche de stockage. Redis fournit une solution idéale :
// Stocker les métadonnées du token pour la révocation
func (r *Redis) SetJTI(ctx context.Context, key, userID string, exp time.Time) error {
return r.Client.Set(ctx, key, userID, time.Until(exp)).Err()
}
// Vérifier si le token est révoqué
func (r *Redis) GetUserByJTI(ctx context.Context, key string) (string, error) {
return r.Client.Get(ctx, key).Result()
}
Stockez l'identifiant unique du token (jti) dans Redis avec une TTL correspondant à l'expiration du token. Cela permet une déconnexion immédiate et empêche la réutilisation des tokens compromis.
Erreurs courantes d'implémentation JWT à éviter
Auto-émission de tokens en production : Les API doivent valider les tokens, pas les émettre. Utilisez un IdP dédié pour l'émission.
Clés de signature faibles : Utilisez des secrets cryptographiquement forts (au moins 32 octets) générés via
openssl rand -base64 32.Désactivation de la validation des revendications : Ne définissez jamais
ValidateIssuerouValidateAudiencesurfalseen production.Durées de vie longues des tokens : Les tokens d'accès doivent expirer dans les 15 minutes. Des durées de vie plus longues augmentent la surface d'attaque.
Absence de mécanisme de révocation : Implémentez la déconnexion et la révocation des tokens à l'aide de Redis ou d'un stockage similaire.
Questions fréquemment posées
Quelle est la différence entre l'authentification JWT et OAuth 2.0 ? JWT est un format de token, tandis qu'OAuth 2.0 est un cadre d'autorisation. OAuth 2.0 définit comment obtenir des tokens (y compris les JWT), tandis que JWT définit la structure du token lui-même. Ils sont complémentaires — OAuth 2.0 peut utiliser des JWT comme tokens d'accès, mais vous pouvez également utiliser des JWT indépendamment pour l'authentification dans des systèmes plus petits.
Comment stocker les JWT de manière sécurisée côté client ? Stockez les JWT dans des cookies HttpOnly et Secure plutôt que dans localStorage ou sessionStorage. Les cookies HttpOnly empêchent l'accès JavaScript, protégeant contre les attaques XSS. Pour les applications mobiles, utilisez des mécanismes de stockage sécurisés spécifiques à la plateforme.
Puis-je révoquer un JWT avant son expiration ? Oui, en maintenant une liste de révocation ou un stockage des identifiants de tokens (revendications jti). Redis est idéal pour cela — stockez le jti avec une TTL correspondant à l'expiration du token. Pour chaque requête, vérifiez si le jti existe dans le stockage de révocation. Cela permet une déconnexion immédiate et l'invalidation des tokens.
Dois-je utiliser HS256 ou RS256 pour signer les JWT ? Utilisez RS256 (asymétrique) pour les environnements de production multi-services où l'émission et la validation des tokens se produisent sur des systèmes différents. Utilisez HS256 uniquement pour les applications à service unique où le même secret peut être partagé de manière sécurisée. La signature asymétrique permet aux services de validation d'utiliser uniquement la clé publique, suivant le principe du moindre privilège.
Comment implémenter les tokens de rafraîchissement de manière sécurisée ?
Émettez un token de rafraîchissement à longue durée de vie (7 jours) en parallèle du token d'accès à courte durée de vie (15 minutes). Fournissez un point d'accès /refresh qui accepte le token de rafraîchissement, le valide et renvoie une nouvelle paire accès+rafraîchissement. Faites pivoter les tokens de rafraîchissement à chaque utilisation pour empêcher les attaques de rejeu. Stockez les tokens de rafraîchissement de manière sécurisée (ex. dans Redis) et invalidez-les lors de la déconnexion.
Sources
- Duende Software. "A step by step JWT authentication example." Duende Software. 2025.
- Microsoft Learn. "Configure JWT bearer authentication in ASP.NET Core." Microsoft. 2025.
- Duende Software. "Implementing Token Authentication in Controller-Based ASP.NET Core Web APIs." Duende Software. 2026.
- QuickNode. "How to Implement JSON Web Tokens (JWT) Authorization." QuickNode. 2025.
- freeCodeCamp. "How to Build a Secure Authentication System with JWT and Refresh Tokens." freeCodeCamp. 2025.
- Vonage. "JWT Authentication in Go with Gin." Vonage Developer. 2025.
— Editorial Team
Aucun commentaire pour le moment.