Les JSON Web Tokens (JWT) sont devenus le standard de facto pour l'authentification dans les applications modernes. Pourtant, une mauvaise gestion de leur sécurité peut exposer votre système à des attaques dévastatrices. Ce guide approfondi explore les deux piliers essentiels de la sécurité JWT : la gestion du cycle de vie des tokens et la rotation des clés secrètes.
Comprendre les fondamentaux du JWT
Un JWT est composé de trois parties encodées en Base64 et séparées par des points : le header, le payload et la signature. La sécurité repose sur cette signature, générée à partir d'une clé secrète (pour les algorithmes symétriques comme HS256) ou d'une paire de clés publique/privée (pour les algorithmes asymétriques comme RS256).
Selon l'OWASP, 34% des violations de données impliquant des API sont liées à une mauvaise gestion des tokens d'authentification. La question n'est pas de savoir si vous utiliserez des JWT, mais comment vous les sécuriserez.
Cycle de vie des tokens : la première ligne de défense
Pourquoi la durée de vie compte
Un token qui ne expire jamais est une bombe à retardement. Si un attaquant obtient un tel token (via XSS, interception réseau, ou fuite de logs), il dispose d'un accès permanent à votre système.
Recommandations de durée de vie selon le contexte :
| Type de token | Durée recommandée | Justification | |---------------|-------------------|---------------| | Access token (API) | 15 à 30 minutes | Limite la fenêtre d'exploitation | | Refresh token | 7 à 30 jours | Permet des sessions longues sans exposer l'access token | | Token de confirmation email | 24 heures | Équilibre entre UX et sécurité | | Token de réinitialisation mot de passe | 1 heure | Action sensible, fenêtre courte |
L'architecture access/refresh token
La meilleure pratique consiste à utiliser deux types de tokens :
Access token : Token de courte durée (15-30 min) qui autorise les requêtes API. Stocké en mémoire côté client, jamais dans localStorage ou un cookie accessible par JavaScript.
Refresh token : Token de longue durée stocké dans un cookie HttpOnly, Secure, SameSite=Strict. Utilisé uniquement pour obtenir de nouveaux access tokens.
Client Serveur
| |
|-- Login (credentials) ------->|
|<-- Access + Refresh tokens ---|
| |
|-- API Request (access) ------>|
|<-- Response ------------------|
| |
| [Access token expiré] |
| |
|-- Refresh Request ----------->|
|<-- Nouveaux tokens -----------|
Pour implémenter ce pattern correctement dans vos applications, notre service de développement sur mesure peut vous accompagner.
Révocation proactive des tokens
La révocation pose un défi architectural : les JWT sont conçus pour être vérifiés sans consulter une base de données. Plusieurs stratégies existent :
1. Liste noire de tokens (Token Blacklist)
Stockez les tokens révoqués dans Redis ou une base de données rapide. Vérifiez chaque requête contre cette liste.
Avantages : Simple à implémenter, révocation immédiate. Inconvénients : Ajoute une latence, nécessite une infrastructure de cache.
2. Versioning des tokens
Ajoutez un numéro de version dans le payload du token et stockez la version courante en base. Lors d'une révocation, incrémentez la version utilisateur.
{
"sub": "user123",
"token_version": 5,
"exp": 1717344000
}
3. Tokens de courte durée uniquement
Si vos access tokens expirent en moins de 15 minutes, la révocation du refresh token suffit dans la plupart des cas.
Rotation des secrets : la deuxième ligne de défense
Pourquoi les secrets doivent être rotés
Même avec une gestion parfaite du cycle de vie, une fuite de votre clé de signature serait catastrophique. Un attaquant pourrait alors :
- Créer des tokens valides pour n'importe quel utilisateur
- Contourner complètement votre système d'authentification
- Persister indéfiniment dans votre système
La rotation régulière des secrets limite la fenêtre d'exploitation en cas de compromission. Le NIST recommande une rotation au minimum tous les 90 jours pour les secrets cryptographiques.
Stratégies de rotation sans interruption de service
1. Multi-key verification
Maintenez plusieurs clés actives simultanément : la clé courante pour la signature et les clés précédentes pour la vérification uniquement.
// Exemple conceptuel
const keys = {
current: "key-2026-06", // Utilisée pour signer
previous: ["key-2026-03", "key-2025-12"] // Utilisées pour vérifier
};
function verifyToken(token) {
// Essayer la clé courante d'abord
// Puis les clés précédentes si nécessaire
}
2. Key ID (kid) dans le header
Incluez un identifiant de clé dans le header JWT pour savoir quelle clé utiliser pour la vérification.
{
"alg": "RS256",
"typ": "JWT",
"kid": "key-2026-06"
}
3. Rotation progressive
- Générez une nouvelle clé et ajoutez-la comme clé alternative
- Commencez à signer les nouveaux tokens avec la nouvelle clé
- Attendez que tous les anciens tokens expirent (durée de vie max du refresh token)
- Supprimez l'ancienne clé
Automatisation de la rotation
Pour les environnements de production, automatisez la rotation avec des outils comme :
- HashiCorp Vault : Gestion centralisée des secrets avec rotation automatique
- AWS Secrets Manager : Rotation native pour les applications AWS
- Azure Key Vault : Intégration native avec les services Azure
Notre équipe peut vous aider à mettre en place une infrastructure cloud sécurisée avec rotation automatisée des secrets.
Algorithmes : HS256 vs RS256
HS256 (Symétrique)
- Une seule clé partagée entre le générateur et le vérificateur
- Plus rapide en termes de performance
- Risque : la clé doit être partagée avec chaque service qui vérifie les tokens
Cas d'usage : Architectures monolithiques où un seul service génère et vérifie les tokens.
RS256 (Asymétrique)
- Clé privée pour signer, clé publique pour vérifier
- La clé publique peut être distribuée librement
- Plus lent mais plus sécurisé dans les architectures distribuées
Cas d'usage : Architectures microservices, OAuth/OIDC, APIs publiques.
Recommandation : Pour les applications modernes, privilégiez RS256 ou ES256. La légère pénalité de performance est largement compensée par la sécurité accrue.
Implémentation pratique : checklist de sécurité
Configuration du serveur
- [ ] Utilisez RS256 ou ES256 plutôt que HS256 pour les architectures distribuées
- [ ] Définissez une durée de vie courte pour les access tokens (15-30 min max)
- [ ] Stockez les refresh tokens dans des cookies HttpOnly, Secure, SameSite=Strict
- [ ] Implémentez un mécanisme de révocation (blacklist ou versioning)
- [ ] Validez toujours l'audience (aud) et l'issuer (iss) des tokens
Gestion des secrets
- [ ] Ne jamais hardcoder les secrets dans le code source
- [ ] Utilisez des variables d'environnement ou un gestionnaire de secrets
- [ ] Planifiez une rotation tous les 90 jours au minimum
- [ ] Maintenez au moins 2 clés actives pour les rotations sans interruption
- [ ] Auditez les accès aux secrets (qui y accède, quand)
Monitoring et alertes
- [ ] Loggez les tentatives de connexion échouées
- [ ] Alertez sur les pics d'utilisation de tokens
- [ ] Détectez les tokens utilisés depuis des localisations inhabituelles
- [ ] Surveillez les tentatives de réutilisation de refresh tokens
Erreurs courantes à éviter
Stocker les tokens dans localStorage
localStorage est accessible par n'importe quel script JavaScript, y compris les scripts malveillants injectés via XSS. Stockez les access tokens en mémoire et les refresh tokens dans des cookies HttpOnly. Cette erreur est particulièrement dangereuse car elle transforme n'importe quelle faille XSS en vol de session complet.
Tokens sans expiration
Un token qui ne expire jamais offre une persistance indéfinie à un attaquant. Même pour les cas d'usage "session longue", utilisez des refresh tokens avec rotation. La tentation de simplifier l'architecture en éliminant l'expiration est un piège classique qui compromet toute votre sécurité.
Ignorer l'algorithme "none"
Certaines bibliothèques JWT acceptent par défaut l'algorithme "none", qui permet de forger des tokens sans signature. Désactivez explicitement cet algorithme dans votre configuration. Cette vulnérabilité a été exploitée dans plusieurs incidents majeurs, notamment CVE-2015-9235 qui a affecté plusieurs bibliothèques populaires.
Exposer le secret dans les logs
Les erreurs de débogage incluent parfois le secret dans les messages d'erreur ou les stack traces. Auditez vos logs pour vous assurer qu'aucune information sensible n'est exposée. Utilisez des outils de redaction automatique dans votre pipeline de logging.
Utiliser des secrets faibles
Un secret JWT doit avoir au moins 256 bits d'entropie pour résister aux attaques par force brute. Évitez les mots de passe simples, les noms de projet, ou les valeurs par défaut. Utilisez un générateur cryptographique pour créer vos secrets.
Ne pas valider tous les claims
Valider uniquement la signature ne suffit pas. Vérifiez systématiquement les claims exp (expiration), iss (issuer), aud (audience), et nbf (not before). Une validation incomplète permet à un attaquant de réutiliser des tokens légitimes dans des contextes non autorisés.
Cas pratique : architecture sécurisée pour une API
Voici une architecture de référence combinant les meilleures pratiques :
┌─────────────────────────────────────────────────────────────┐
│ Application Client │
│ - Access token en mémoire │
│ - Refresh token en cookie HttpOnly │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ API Gateway │
│ - Valide la signature (clé publique) │
│ - Vérifie expiration, audience, issuer │
│ - Vérifie contre la blacklist Redis │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Service Auth │
│ - Génère les tokens (clé privée) │
│ - Gère les refresh tokens │
│ - Rotation automatique via Vault │
└─────────────────────────────────────────────────────────────┘
FAQ
Quelle est la différence entre expiration et révocation d'un JWT ?
L'expiration est automatique et basée sur le timestamp inclus dans le token (claim exp). La révocation est une action manuelle qui invalide un token avant son expiration naturelle. L'expiration ne nécessite aucune vérification serveur, tandis que la révocation exige un mécanisme de stockage (blacklist) pour vérifier si un token a été révoqué.
Comment gérer la rotation des secrets sans interrompre les utilisateurs ?
Utilisez une stratégie multi-clés : la nouvelle clé signe les nouveaux tokens tandis que l'ancienne clé reste active pour vérifier les tokens existants. Attendez que tous les tokens signés avec l'ancienne clé expirent (durée de vie du refresh token) avant de la supprimer. Incluez un identifiant de clé (kid) dans le header JWT pour faciliter la sélection de la bonne clé.
HS256 ou RS256 : lequel choisir ?
Pour une application monolithique simple, HS256 est suffisant et plus performant. Pour les architectures microservices, les APIs publiques ou les scénarios OAuth, RS256 est préférable car la clé publique peut être distribuée sans risque. La règle générale : si plusieurs services doivent vérifier vos tokens, utilisez RS256.
Quelle durée de vie recommandez-vous pour les access tokens ?
Entre 15 et 30 minutes pour les applications web classiques. Cette durée offre un bon équilibre entre sécurité (fenêtre d'exploitation limitée) et expérience utilisateur (rafraîchissements peu fréquents). Pour les applications hautement sensibles (bancaires, santé), réduisez à 5 ou 10 minutes avec un refresh automatique transparent.
Comment détecter une compromission de clé de signature ?
Surveillez les anomalies : tokens valides pour des utilisateurs inexistants, pics soudains de nouvelles sessions, tokens avec des claims inhabituels. Implémentez un logging exhaustif de l'utilisation des tokens. En cas de doute, effectuez une rotation d'urgence et forcez une réauthentification de tous les utilisateurs.
