Résumé

  • draft-ietf-oauth-deferred-token-response-00 crée un code lié à l’émetteur pour représenter une demande de jeton encore en attente ; ce code n’est pas un jeton d’accès.
  • L’endpoint RFC 7009 répond 200 après une annulation effective comme après une requête qui ne change aucun état. La découverte du support et un poll de confirmation forment donc des preuves distinctes.
  • Si un jeton d’accès a déjà été remis, il possède sa propre durée de vie et doit être révoqué séparément ; annuler le différé ne prouve pas l’arrêt d’une opération protégée.

Un succès de transport, pas un verdict d’état

L’ambiguïté n’est pas un oubli du protocole. La révocation OAuth évite volontairement de dire si la valeur reçue était valide. Un attaquant obtient ainsi moins d’informations en testant des chaînes possibles. Mais la même protection retire au code HTTP sa capacité à servir de reçu opérationnel.

La révision 00 de Deferred Token Response applique cette mécanique à une décision de jeton qui peut durer : examen humain, contrôle antifraude ou vérification externe. Le client demande un achèvement différé. Si le serveur d’autorisation accepte, l’endpoint de jeton renvoie HTTP 400, authorization_pending, un deferral_code, une échéance et un rythme minimal de poll.

Cette réponse ne délivre aucun accès. Le code opaque désigne une seule demande en attente auprès d’un seul serveur. Il est contraint au même émetteur lorsque la requête initiale employait DPoP ou un certificat TLS mutuel. Le posséder hors de ce contexte ne suffit pas.

Le document est un Internet-Draft actif du groupe OAuth, pas un RFC ni un constat de déploiement. Il fournit néanmoins une carte précise des endroits où une automatisation peut confondre réception, transition et résultat.

Le même nom masque deux échéances

Le premier expires_in décrit la vie du code de différé. Une fois ce délai passé, le poll reçoit expired_token. Si la décision aboutit positivement, la réponse finale possède aussi un expires_in, mais celui-ci décrit le jeton d’accès. Réutiliser le premier minuteur pour le second serait une erreur de modèle, même si les champs portent le même nom.

Le client doit aussi conserver interval, fourni une seule fois. Tant que le résultat est en attente, il ne peut pas interroger plus vite ; slow_down ajoute au moins cinq secondes. Une trace qui ne garde que la dernière réponse perd donc la règle qui permet de dire si le client a respecté le serveur.

Le reçu utile associe le temps au bon objet : échéance du code, échéance éventuelle du jeton, cadence de poll et instant de chaque transition. Une durée n’autorise pas l’autre.

Le callback annonce une disponibilité, pas une décision

Un client peut enregistrer une URL HTTPS de notification. Quand la demande se résout — par succès, erreur ou annulation — le serveur y envoie le code de différé. Le message ne contient ni jeton ni résultat. Il signifie seulement qu’un poll produira désormais une réponse finale.

Avec un jeton de notification propre à la demande, le client peut authentifier l’appel. Sans lui, il doit protéger l’endpoint autrement et considérer le message comme indicatif jusqu’au poll. Même authentifié, un callback ne dit pas « approuvé » : il prouve l’origine de l’avis, pas sa branche terminale.

Le projet recommande de continuer à interroger à la cadence convenue. Le callback réduit l’attente ; le poll résiste à une notification perdue, retardée ou supprimée. Leur redondance améliore la disponibilité seulement si l’application conserve la différence entre réveil et résultat.

Le 200 regroupe des mondes incompatibles

L’annulation envoie le code exact à l’endpoint de révocation, avec l’indication de type prévue. Si le serveur reconnaît le code et l’attribue au client authentifié, il doit faire passer atomiquement la demande à l’état annulé. Il supprime le callback dont l’envoi n’a pas commencé et fait répondre access_denied aux polls suivants.

Mais un code inconnu, lié à un autre client, déjà utilisé, déjà annulé ou expiré produit le même HTTP 200 sans changement d’état. C’est la règle du RFC 7009, pas une exception de DTR.

La révision 00 ajoute donc la métadonnée revocation_endpoint_token_type_values_supported. Le serveur compatible doit y annoncer le type deferral-code. Un serveur qui ne l’annonce pas répond quand même 200 à la tentative. Le texte prévient explicitement que cette réponse est indiscernable d’une annulation réussie.

Une chaîne de preuve commence par l’instantané des métadonnées, continue avec l’envoi et son résultat de transport, puis se termine par un poll donnant access_denied. Le 200 reste utile, mais sa place est au milieu.

La course décide quel objet doit encore être révoqué

Si la décision positive est enregistrée mais que le jeton n’a pas été remis, l’annulation transforme le code en état « utilisé puis annulé ». Aucun jeton ne sort ; le prochain poll répond access_denied.

Si le jeton a déjà été remis, la révocation du code de différé ne doit pas le révoquer. Les deux identifiants sont des credentials indépendants avec des durées indépendantes. Le client qui veut couper l’accès doit révoquer le jeton lui-même et vérifier ensuite le comportement de la ressource.

Un callback peut aussi avoir commencé son trajet avant l’annulation. Le serveur n’est tenu de supprimer que celui dont l’émission n’a pas débuté. Une notification tardive n’invalide donc pas l’annulation ; elle ne doit surtout pas rouvrir automatiquement le dossier.

Les statuts opérationnels doivent nommer cette frontière : en attente ; résolu sans remise ; jeton remis. « Annulé » sans préciser la remise est trop pauvre pour gouverner le risque.

Le consentement ne reste pas figé pendant l’attente

Le code peut vivre plusieurs heures ou jours. Entre-temps, la personne peut retirer son consentement, la session peut finir, le client peut être désactivé. Avant d’émettre le jeton, le serveur doit réévaluer ces conditions et répondre access_denied si elles ne tiennent plus.

L’examinateur externe décide de son contrôle. Le serveur d’autorisation décide de l’émission sous l’état présent. Le serveur de ressources applique encore le scope et sa politique locale. Enfin, le service constate si l’action demandée a abouti. Aucun de ces acteurs ne peut hériter automatiquement du verdict du précédent.

Conserver la course sans conserver le secret

Un reçu minimal enregistre l’émetteur et le digest des métadonnées de support, l’identité du client et la référence de sa clé, une corrélation à sens unique du code, l’échéance et l’intervalle, la tentative d’annulation et ses reprises, le poll terminal, l’état du callback et la frontière de remise du jeton. Il ne met pas le code secret dans les journaux généraux.

Si un jeton est sorti, il ajoute la révocation indépendante. Si le risque concerne une action réelle, il ajoute l’admission par la ressource et le résultat de la transaction contrôlée. Cette forme minimale rend les produits comparables sans créer de registre central.

La distinction rejoint les couches de réalité décrites par Lu Heng. HTTP 200 est une assertion symbolique. L’annulation est une transition interne. access_denied est une observation protocolaire. La révocation du jeton est un autre événement. L’opération acceptée ou refusée est le résultat exécutable. La preuve progresse en descendant vers ce résultat, non en recopiant davantage le premier signal.

Sources

  1. Deferred Token Response rev00
  2. Historique DTR
  3. DTR rev00 HTML
  4. DTR rev00 texte
  5. RFC 6749 — OAuth 2.0
  6. RFC 7009 — Révocation OAuth
  7. RFC 8628 — Device Authorization Grant
  8. RFC 8693 — Token Exchange
  9. RFC 8705 — OAuth mTLS
  10. RFC 9449 — OAuth DPoP
  11. RFC 9700 — Bonnes pratiques de sécurité OAuth
  12. Registre IANA OAuth
  13. Lu Heng — Minimum Initial Specification
  14. Lu Heng — On Reality Layers
  15. Lu Heng — Running Code Primary