JWT : Structure et vulnérabilités
1) Qu'est-ce que JWT et où il est utilisé
JWT est un conteneur d'affirmations compact et autosuffisant au format 'Base64Url (header). Base64Url(payload). Base64Url(signature)`.
Utilisé pour :- JWS (jetons signés - authenticité/intégrité),
- JWE (jetons cryptés - confidentialité),
- OIDC/OAuth2 en tant que tokens access/ID et authentification service-to-service.
Avantages : autonomie, cachabilité, petits frais généraux. Inconvénients : risque de validation incorrecte, cas complexes de rappel.
2) Structure JWT
2. 1 Titre (header, JSON)
Minimum : algorithme et ID de clé.
json
{ "alg": "ES256", "kid": "jwt-2025-10", "typ": "JWT" }
'alg' : algorithme de signature/cryptage (RS256/ES256/PS256/HS256, etc.).
'kid' : pointeur vers la clé (pour la rotation JWKS).
Sources de clés optionnelles : 'jku', 'x5u' (voir vulnérabilités § 6. 3).
2. 2 Charge utile (payload, JSON)
Marques normalisées :- `iss` (issuer), `aud` (audience), `sub` (subject)
- « bou » (heure d'expiration), « nbf » (pas avant), « iat » (émis)
- 'jti' (ID de token, approprié pour les commentaires)
- « scope/roles », « tenant », « kyc _ level », etc.
2. 3 Signature (signature)
JWS = `sign(base64url(header) + "." + base64url(payload), private_key)`
Vérification : strictement conforme à la clé publique et exactement l'algorithme que le serveur attend.
3) Invariants de base de vérification
1. L'algorithme est fixé par la configuration ressource-serveur (allow-list) plutôt que par le contenu 'header. alg`.
2. Vérifier 'iss' et 'aud' pour une correspondance exacte, 'bou/nbf' - en tenant compte d'un petit 'clock _ skew' (± 30-60s).
3. Refuser les jetons sans 'kid' seulement si la seule clé n'est pas rotative ; sinon, exiger 'kid'.
4. Ne faites confiance à aucune marque sans autorisation au niveau objet (BOLA-first).
5. Parsing - après cryptoprotection ; contrôles de taille de base avant le décodage.
4) JWS vs JWE
JWS : signé mais à lire. Ne pas placer dans payload PII/secrets.
JWE : Chiffre payload ; l'intégration est plus difficile, le modèle clé est critique.
Dans la plupart des API, JWS + l'interdiction des données sensibles dans payload suffit.
5) Cycle de vie du token
Accès : courte durée (5-30 minutes).
Refresh : plus long (7-30 jours), rotate-on-use (jetable), stocker la « liste noire » 'jti/sid'.
Revocation : listes 'jti' avec TTL, introspection pour les tokens opaques, abréviation 'bou' en cas d'incident.
Rotation des clés : JWKS avec chevauchement (ancien + nouveau), voir l'article « Rotation des clés ».
6) Vulnérabilités fréquentes et comment les fermer
6. 1 'alg = none '/remplacement de l'algorithme
Essence : le serveur fait confiance au champ 'alg' et accepte un jeton non signé.
Protection : liste rigide des algorithmes sur le serveur ; rejeter 'none' et les valeurs inattendues.
6. 2 RS256→HS256 swap (symétrie)
L'intrus remplace 'alg' par 'HS256' et utilise la clé publique comme secret HMAC.
Protection : lier la clé à l'algorithme par une configuration ; ne pas mélanger les fournisseurs symétriques/asymétriques dans un seul 'kid'.
6. 3 Injection de clés ('kid/jku/x5u')
Scripts :- 'jku' indique un JWKS contrôlé par un intrus (il va glisser sa clé).
- 'x5u '/' x5c' abus de certificats externes.
- 'kid' avec injection de chemin/SQL ('../../privkey. pem « 'ou » « OR 1 = 1 -- »).
- Ignorer les 'jku/x5u' distants ou filtrer selon une liste rigoureuse de domaines allow-list.
- 'kid'n'est utilisé que comme clé dans le répertoire local (table/cache), sans chemins de fichiers/concaténations SQL.
- JWKS expédier à partir d'URL de confiance, court TTL, signature/pinning canal.
6. 4 Secrets faibles de HS256 (force brute)
L'essentiel : Le secret HMAC est court/canard → l'échange de signature.
Protection : utiliser l'asymétrie (RS/ES/PS) ou la longueur du secret ≥ 256 bits, les secrets sont uniquement dans KMS.
6. 5 Marques manquantes/non valides
Aucun 'aud'/' iss '/' bou' → le jeton cross-service est utilisable ou infini.
Trop long 'bou' → risque de compromission.
Protection : Exiger un ensemble complet de marques, 'bou' court, 'nbf '/' iat'à valider avec 'clock _ skew'.
6. 6 Replay et vol de token
L'essentiel : interception/répétition de token (fuite dans les logs, XSS, MitM sans TLS).
Protection :- TLS везде, `Secure`+`HttpOnly` cookie, SameSite=Lax/Strict.
- DPoP/PoP (ancrage du jeton à la clé client) et/ou mTLS pour les partenaires.
- Court 'bou', refresh-rotation, device-binding.
6. 7 Fuites via XSS/stockage
L'essentiel : le stockage de JWT dans 'localStorage '/' sessionStorage' est → disponible par JS.
Protection : stocker des jetons d'accès dans un cookie HttpOnly (si un modèle de cookie est possible) + des types CSP/Trusted rigoureux.
Pour SPA sans cookie - isoler le token dans la mémoire, vivre au minimum, protéger contre XSS.
6. 8 CSRF
L'essentiel : dans les sessions de cookies, demandes d'un site tiers.
Protection : SameSite, jetons anti-CSRF (double submit), 'Origin/Referer', filtres Fetch-Metadata.
6. 9 Oversize/abus de taille
L'essentiel : énormes payload/titres, DoS sur le parsing.
Protection : limites de taille des en-têtes/corps, early-reject 431/413, jeu de marquages fix.
6. 10 Remplacement de 'typ '/' cty'
L'essence est la confusion des types ('typ : « JWT »), les objets JOSE imbriqués.
Protection : ignorer 'typ/cty' pour la sécurité, s'appuyer sur des algorithmes fixes et un schéma de marquage.
7) Stockage et transfert de tokens
7. 1 API serveur (machine-to-machine)
mTLS/HMAC, de préférence asymétrie pour JWT, canaux - via mesh.
Stockage de clés - KMS/HSM, rotation programmée, JWKS avec recouvrement.
7. 2 Clients du navigateur
HttpOnly Secure Cookie для access/refresh; TTL courts ; mise à jour - via « silent refresh » avec 'SameSite = None' uniquement sous HTTPS.
Rigoureux CSP, Trusted Types, protéger contre XSS ; Pour SPA - si possible, ne pas stocker le jeton sur le disque.
8) JWKS, rotation et rappel
Le JWKS est publié par l'ordonnateur ; les consommateurs mettent en cache pendant 5 à 15 minutes.
Plan de rotation : ajouter un nouveau 'kid' → commencer à le signer → supprimer l'ancien de JWKS → purge après N jours.
Rappel : listes 'jti/sid'c TTL ; en cas d'incident, raccourcir temporairement « bou » et force-logout (invalider refresh).
9) Multi-tenant et minimisation des données
Inclure 'tenant '/' org' dans le jeton uniquement si nécessaire par architecture ; Sinon, serrer les attributs du PDP par 'sub'.
Pas de PII ; un ensemble minimal de marques → moins de risques de fuites et de corollations.
10) Chèque de validation pratique (serveur de ressources)
- Parsim seulement après vérification de la signature et des limites de taille de base.
- 'alg' de la configuration ; rejeter l'inattendu.
- Vérifiez 'iss' ∧' aud' ∧ 'bou' ∧ 'nbf' ∧ 'iat' (avec 'clock _ skew').
- Vérifiez 'kid' par répertoire local/JWKS (court TTL).
- Filtrer/normaliser les pointeurs externes ('jku/x5u'n'est qu'allow-list).
- Limiter la longueur/composition des marques (schéma).
- Appliquer l'autorisation d'objet à la ressource (BOLA-first).
- Loger 'kid', 'sub', 'aud', 'iss', 'jti', 'bou', 'tenant', 'trace _ id' (sans PII).
- Métriques d'erreurs de signature, de retard, d'audit de rotation.
11) Exemples de politiques de sécurité (pseudo)
11. 1 Configuration des attentes de l'algorithme
yaml jwt:
expected_issuer: "https://auth. example. com"
expected_audience: ["wallet-service"]
allowed_algs: ["ES256"] # fix the jwks_url: "https ://auth. example. com/.well-known/jwks. json"
jwks_cache_ttl: 600s clock_skew: 60s required_claims: ["iss","aud","sub","exp","iat"]
11. 2 Refus de distance 'jku/x5u'
yaml reject_untrusted_key_sources: true allowed_jku_hosts: ["auth. example. com"] # if absolutely necessary
11. 3 Exemple de liste de commentaires (Redis)
pseudo if redis. exists("revoke:jti:" + jti) then deny()
if now() > exp then deny()
12) Observabilité et forensisme
Метрики: `jwt_verify_fail_total{reason}`, `jwt_expired_total`, `jwks_refresh_total`, доля `kid`.
Logs (structurés) : 'iss/aud/sub/kid/jti/bou/tenant/trace _ id', cause de l'échec.
Dashboards : « expirant bientôt », sursaut d'erreurs de validation, répartition par région/client.
Alert : croissance de 'verify _ fail' (signature/algorithme), erreurs JWKS, proportion de tokens périmés.
13) Anti-modèles
Faire confiance à 'alg' du token ; maintenir 'none'.
Tokens d'accès à longue durée de vie et pas de rotation de refresh.
HS256 avec un secret court/secret dans le BOU sans KMS.
Accepter 'jku/x5u' de n'importe quel domaine ; Charger dynamiquement JWKS sans allow-list.
Mettre PII/secrets dans payload JWS.
Stocker les jetons dans 'localStorage' en cas de risque XSS.
Arrêter les erreurs de validation (renvoyer 200 avec « soft error »).
L'absence de contrôles BOLA et le fait de ne compter que sur « scope/role ».
14) Spécificité de l'iGaming/finance
Stimes : 'kyc _ level', 'risk _ tier', 'tenant', rigoureux 'aud'.
TTL courts pour les opérations d'écriture (dépôts/retraits), PoP/DPoP ou mTLS pour les itinéraires critiques.
Audit réglementaire : journaux d'entrées/pannes immuables, stockage des logs dans les limites de la région.
Les partenaires/PSP ont des clés séparées/' aud', des clés per-tenante et des JWKS séparés.
15) Chèque-liste prod-prêt
- Liste rigide des algorithmes ; 'none' est interdite.
- 'iss/aud/bou/nbf/iat/jti' sont vérifiés ; court 'bou'.
- JWKS avec chevauchement, cache TTL court ; surveillance des parts de 'kid'.
- Refresh — rotate-on-use; les listes "jti/sid'avec TTL ; pleybuk de commentaires.
- PoP/DPoP ou mTLS sur les routes critiques.
- HttpOnly-cookies pour le navigateur, CSP/Trusted Types vs XSS ; Protection CSRF.
- Sans PII dans payload ; ensemble minimal de marques.
- Métriques/logs de validation et de refus ; alerte JWKS/verify_fail.
- Tests de scénarios négatifs : RS→HS swap, 'kid' -injection, 'jku' spoofing, oversize, clock-skew.
16) TL; DR
Fixez l'algorithme et les clés côté serveur, ne faites pas confiance à 'alg' du token, demandez 'iss/aud/bou/nbf/iat/jti'. Tournez les clés à travers JWKS avec le recouvrement, gardez les jetons courts et refresh jetables. Stockez les jetons en toute sécurité (cookie HttpOnly pour le Web), réduisez les marques, ne placez pas de PII. Fermez 'jku/x5u/kid', évitez les HS256 avec des secrets faibles, ajoutez PoP/DPoP ou mTLS sur les chemins critiques et faites toujours des vérifications BOLA au niveau de la ressource.