Gérer la durée de vie des jetons OAuth
- Accueil
- Identités, accès & habilitations
- OIDC, SAML et OAuth 2.1 en fédération
- Gérer la durée de vie des jetons OAuth
Gérer la durée de vie des jetons OAuth
Section intitulée « Gérer la durée de vie des jetons OAuth »Un jeton d’accès doit expirer vite, car un jeton volé est une capacité d’accès volée. Le jeton de rafraîchissement évite de transformer cette règle de sécurité en concours de déconnexions inutiles, mais il devient alors le secret le plus sensible de la session.
Un laissez-passer temporaire permet d’entrer quelque part sans redonner son identité à chaque porte. Une carte conservée plus longtemps permet d’en obtenir un nouveau quand le premier expire, mais sa perte doit alerter car elle ouvre la porte durablement.
→ Lire l’explication complète de la marmotte
Durée des jetons d’accès : réduire la fenêtre de vol
Section intitulée « Durée des jetons d’accès : réduire la fenêtre de vol »Dans OAuth 2.0, un cadre de délégation d’autorisation, le jeton d’accès porte une autorisation limitée : agir au nom d’une identité, pour une ressource et un ensemble de droits donnés. Sa durée de vie est la fenêtre pendant laquelle son vol permet un rejeu. Réduire cette durée réduit mécaniquement l’impact d’une exfiltration depuis un navigateur, un journal applicatif, une mémoire de processus ou un proxy mal configuré.
La recommandation par défaut est nette : un jeton d’accès destiné à une interface humaine doit vivre entre cinq et quinze minutes. Un jeton utilisé par un traitement machine peut vivre davantage seulement si son stockage, son identité d’exécution et sa rotation sont maîtrisés. Une durée de vingt-quatre heures pour éviter « les soucis de session » n’est pas un compromis d’expérience utilisateur, c’est une autorisation portable abandonnée sur le trottoir pendant une journée entière.
Le compromis central est là : une expiration courte limite le temps d’exploitation d’un vol, mais force l’obtention fréquente de nouveaux jetons. Sans mécanisme complémentaire, cela déclenche des réauthentifications répétées. Le jeton de rafraîchissement absorbe ce coût : il permet d’obtenir un nouveau jeton d’accès sans demander à nouveau les facteurs d’authentification, tant que la session reste autorisée.
Un jeton d’accès peut être opaque ou auto-porteur. Un jeton opaque est une valeur aléatoire dont le serveur d’autorisation conserve l’état. Une ressource doit interroger ce serveur, ou un cache d’introspection, pour connaître les droits associés. Un JSON Web Token (JWT) est auto-porteur : ses revendications sont signées, puis vérifiables localement avec une clé publique ou un secret partagé. Les principes généraux d’authentification des personnes et des services restent les mêmes, mais le choix du format change radicalement la révocation.
Fixer aussi les bornes temporelles avec précision. La revendication exp fixe l’expiration, nbf interdit l’usage avant une date et iat indique l’émission. Les serveurs doivent tolérer une dérive d’horloge réduite, généralement inférieure à soixante secondes. Une tolérance de cinq minutes masque une mauvaise synchronisation et rallonge la validité effective. Le temps réseau est déjà assez créatif sans lui offrir une semaine de congés.
Révocation des JWT : la promesse et la facture
Section intitulée « Révocation des JWT : la promesse et la facture »Révoquer une session signifie rendre inutilisables les jetons qui en dérivent. Cette propriété est naturelle avec un jeton opaque : supprimer ou marquer l’enregistrement serveur suffit, et la vérification suivante échoue. La contrepartie est un état central consulté à chaque appel, directement ou via un cache à cohérence contrôlée.
Un JWT signé ne possède pas cette propriété. Après émission, une ressource vérifie la signature, l’émetteur (iss), le destinataire (aud), l’expiration et les droits sans recontacter l’émetteur. Si ce JWT est volé, une révocation stockée uniquement côté serveur ne le change pas. Il reste accepté jusqu’à exp.
Une liste de révocation peut corriger ce comportement, par exemple en enregistrant l’identifiant jti de chaque jeton annulé et en le consultant à chaque requête. Mais cette liste réintroduit une dépendance réseau et un état partagé dans le chemin critique. Le gain de performance attribué au JWT disparaît alors, avec une couche de cache, des délais de propagation et des incidents de cohérence en prime. Le JWT sans état absolu est un animal mythologique, au même rayon que la transformation numérique qui ne demande aucun inventaire.
La décision d’architecture doit suivre le besoin de coupure immédiate :
- Exiger une révocation en quelques secondes pour un accès à privilèges, une console d’administration ou une donnée sensible : préférer des jetons opaques, ou imposer une introspection centralisée.
- Accepter une fenêtre résiduelle de cinq à quinze minutes : utiliser des JWT d’accès courts sans liste de révocation par jeton.
- Ne jamais compenser un JWT difficile à révoquer en le faisant vivre plus longtemps. Cela augmente simultanément le risque et la difficulté de correction.
Une révocation globale reste nécessaire : désactivation d’un compte, changement de rôle, réinitialisation de facteur d’authentification, suspicion de vol ou incident sur une application cliente. Pour cela, associer chaque session à une version d’autorisation ou à une date de révocation. Les ressources peuvent comparer cette version à un état central mis en cache. Cette approche invalide une famille entière, mais elle reste un appel d’état déguisé. Il faut l’assumer, le superviser et définir le comportement en cas d’indisponibilité.
Rotation des jetons de rafraîchissement et détection de rejeu
Section intitulée « Rotation des jetons de rafraîchissement et détection de rejeu »Le jeton de rafraîchissement ne doit jamais être présenté à une ressource métier. Il est remis uniquement au serveur d’autorisation afin d’obtenir un nouveau jeton d’accès. Sa durée peut atteindre plusieurs jours ou semaines, mais cette longévité impose un stockage protégé et une rotation.
La rotation consiste à invalider le jeton de rafraîchissement présenté et à émettre un successeur à usage unique. Chaque utilisation avance une famille de jetons. Le serveur conserve au minimum l’identifiant de famille, l’état du jeton courant, sa date d’expiration, son client autorisé et l’identité liée.
La détection de réutilisation est le mécanisme décisif. Si un ancien jeton, déjà consommé, réapparaît, deux détenteurs l’utilisent : le détenteur légitime et un acteur ayant copié le secret, ou deux exécutions concurrentes mal conçues. Le serveur doit traiter ce signal comme une compromission de famille : invalider le jeton courant et tous ses descendants, révoquer la session associée, puis exiger une nouvelle authentification.
Ne pas se contenter de renvoyer invalid_grant au jeton réutilisé. Cette réponse discrète laisse potentiellement l’attaquant continuer avec le successeur obtenu avant la détection. La famille entière doit tomber. C’est brutal, mais un secret copié ne devient pas moins copié parce qu’une erreur a été journalisée avec beaucoup de dignité.
La rotation crée une contrainte de concurrence. Deux requêtes de rafraîchissement simultanées peuvent présenter le même jeton légitime. Prévoir soit un verrouillage atomique côté serveur, soit une période de grâce extrêmement courte, liée au même client et à la même session. Une période de grâce large transforme la détection de rejeu en décoration murale. Pour les applications distribuées, sérialiser le rafraîchissement dans le client reste préférable.
Exemple : appel de rafraîchissement avec rotation
Section intitulée « Exemple : appel de rafraîchissement avec rotation »L’exemple suivant utilise curl contre un serveur d’autorisation conforme au point de terminaison de jetons OAuth 2.0. Le jeton retourné dans refresh_token remplace immédiatement l’ancien : conserver les deux valeurs est une erreur de conception.
# Le jeton de rafraîchissement provient d'un stockage chiffré côté serveur.# Ne jamais le placer dans un journal, une variable de diagnostic ou une URL.curl --fail --silent --show-error \ --request POST "https://auth.example.net/oauth/token" \ --header "Content-Type: application/x-www-form-urlencoded" \ --data-urlencode "grant_type=refresh_token" \ --data-urlencode "client_id=portail-interne" \ --data-urlencode "refresh_token=${REFRESH_TOKEN}"La réponse doit contenir un nouveau jeton d’accès et, lorsque la rotation est active, un nouveau jeton de rafraîchissement. Mettre à jour les deux valeurs dans une transaction atomique. Si l’écriture du nouveau jeton échoue après consommation de l’ancien, la session est perdue et une nouvelle authentification est requise. C’est le comportement attendu, pas un bug à masquer par une conservation clandestine de l’ancien jeton.
Pour une application web publique, éviter de livrer un jeton de rafraîchissement durable au code JavaScript. Préférer un échange côté serveur, avec un cookie de session HttpOnly, Secure et SameSite, ou appliquer les mécanismes documentés dans la stratégie architecture cyber. Un script injecté dans la page lit volontiers tout ce qui traîne dans le stockage du navigateur, puis disparaît avec une ponctualité remarquable.
Exploitation : stockage, supervision et reprise
Section intitulée « Exploitation : stockage, supervision et reprise »Un jeton de rafraîchissement est un secret d’authentification. Stocker sa représentation côté serveur sous forme hachée, avec un sel, comme un mot de passe. Le serveur n’a pas besoin de relire la valeur brute pour la comparer. Si le jeton doit être récupérable pour un appel sortant, le chiffrer avec une clé dédiée et gérer cette clé dans l’infrastructure de gestion de secrets. La rotation de clé doit conserver la capacité de déchiffrer les enregistrements existants jusqu’à leur migration ou leur expiration.
Journaliser les événements, pas les jetons : émission, rafraîchissement réussi, rotation, réutilisation détectée, révocation, expiration et échec de validation. Associer les événements à un identifiant de famille pseudonymisé, au client, à l’émetteur et au motif de rejet. Une journalisation contenant le jeton brut transforme le système de supervision en distributeur automatique d’accès.
Déclencher une alerte sur toute réutilisation détectée, sur les rafraîchissements impossibles depuis des contextes incompatibles et sur un pic d’échecs invalid_grant. La géolocalisation seule n’est pas une preuve : les réseaux mobiles, les sorties d’entreprise et les relais la rendent bavarde. Elle devient exploitable lorsqu’elle est corrélée à une réutilisation, un changement de client ou un changement de facteur d’authentification.
La sauvegarde de l’état des familles de jetons mérite une règle stricte : restaurer une sauvegarde ancienne peut réactiver des jetons déjà consommés ou révoqués. Stocker l’état de révocation dans un système durable, répliquer les écritures de consommation et, après reprise, invalider les familles dont la cohérence ne peut être garantie. Perdre une session coûte moins cher que ressusciter un accès compromis.
🐝 Ce qui arrive si on s’en passe
Section intitulée « 🐝 Ce qui arrive si on s’en passe »Sans gestion explicite de la durée de vie, la porte reste entrouverte bien après le départ du visiteur. Le premier coût est la réponse à incident : faute de familles de jetons identifiées et de bornes courtes, la seule coupure disponible devient la rotation de la clé de signature ou la purge globale des sessions, qui déconnecte l’ensemble des porteurs légitimes pour neutraliser un seul secret copié. Le second coût est la preuve : sans événements d’émission, de rotation et de consommation, il devient impossible de dater la fin effective d’un accès, donc de démontrer qu’un départ, une suspension de compte ou un retrait de droit a réellement pris effet. Les audits se heurtent alors à une autorisation dont personne ne peut fixer le terme, et la reconstitution après coup se résume à des suppositions.
🦫 Explication de la marmotte 🍫
Section intitulée « 🦫 Explication de la marmotte 🍫 »Une application reçoit d’abord un jeton d’accès après vérification de l’identité. Ce jeton permet d’appeler un service pendant peu de temps. Sa courte durée limite les dégâts si quelqu’un le copie : après son expiration, le service doit le refuser.
Pour éviter de redemander l’identité trop souvent, l’application peut aussi recevoir un jeton de rafraîchissement. Celui-ci ne sert pas à appeler les services métier. Il sert uniquement à demander un nouveau jeton d’accès au serveur qui gère les identités. Il doit être mieux protégé, car il reste valable plus longtemps.
À chaque utilisation, le serveur remplace normalement ce jeton de rafraîchissement par un nouveau et invalide l’ancien. Si l’ancien est présenté une seconde fois, cela indique qu’il a probablement été copié. Le serveur doit alors couper toute la session liée, y compris le nouveau jeton déjà donné, puis demander une nouvelle authentification.
Certains jetons contiennent leurs propres informations et peuvent être vérifiés sans contacter le serveur d’identité. Ils restent alors acceptés jusqu’à leur date de fin, même si le serveur a décidé de les retirer. Pour les arrêter plus tôt, chaque service doit consulter une liste centrale, ce qui ajoute des appels réseau et des risques de panne. La durée courte reste donc la protection principale.
À lire aussi
- OIDC, SAML et OAuth 2.1 en fédérationComparer OIDC et SAML, déployer OAuth 2.1 sans confusion, et gouverner la durée de vie, la portée et la révocation des jetons.
- Pièges OAuth 2.1 : PKCE, redirections et scopesOAuth 2.1 encadre la délégation d’autorisation, durcit les redirections, impose PKCE aux clients publics et réduit les privilèges excessifs.
- Attaque par confusion de scope OAuthDémonstration d’une élévation de périmètre OAuth causée par des scopes trop larges et exploitation d’un jeton d’accès compromis.
- Authentifier une API B2B hors annuaire interneChoisir, exploiter et révoquer les mécanismes d’authentification et d’autorisation pour les flux EDI et API B2B entre organisations.
Pages voisines
La citent
- OIDC, SAML et OAuth 2.1 en fédération
- DAC, MAC, RBAC, ABAC ou ReBAC : quel modèle choisir
- Architecture de traçabilité du consentement à grande échelle
- Attaque par confusion de scope OAuth
- Clauses de sécurité pour contrat fournisseur
- Comment sécuriser les jetons stockés sur mobile
- Configurer OIDC entre Keycloak et application interne
- Conformité export et sanctions numériques
- Connecteurs OAuth des assistants IA, portée et consentements
Gérer la durée de vie des jetons OAuth
Elle cite
: les deux pages se citent l’une l’autre.
