Aller au contenu
ecdsa.com

DPoP Proof Inspector — inspecteur de preuves DPoP

Collez la valeur d’un en-tête de requête DPoP. Ajoutez la méthode et l’URL de la requête, ainsi que le jeton d’accès s’il a été envoyé, pour exécuter tous les contrôles que fait un serveur d’autorisation ou un serveur de ressources.

100 % local : tout s’exécute dans votre navigateur, rien n’est envoyé à aucun serveur

Source : RFC 9449 §4.1, figure 2, et §7.1, figure 13 ; le jkt est la valeur de la RFC 9449 §6.1. Vérification à la date de l’iat de la preuve elle-même.

Valeur de l’en-tête de requête DPoP
La requête qui l’accompagnait
Liaison au jeton
Sert uniquement à calculer ath ; jamais inclus dans les liens de partage
Lue dans un jeton d’accès JWT si le champ est vide
Politique du serveur
dpop_signing_alg_values_supported
Date de vérificationLes heures sont en UTC.

What the inspector checks

A DPoP proof (RFC 9449) is a short JWT that an OAuth client signs with its own private key and sends in the DPoP header of a request. It says "the holder of this key is making this request now": the header carries the public key as a jwk, the payload names the HTTP method (htm), the target URI (htu), a creation time (iat), a unique identifier (jti) and, when an access token is presented, the hash of that token (ath). A server that issued a DPoP-bound token accepts the token only together with a valid proof made with the bound key, so a token copied out of a log or a browser is useless on its own.

Section 4.3 of the RFC lists what a server must verify, and the inspector runs those steps in that order, reporting each one:

  1. There is exactly one DPoP header value, and it is a well-formed JWT.
  2. All required claims are present: jti, htm, htu, iat.
  3. typ is dpop+jwt — the explicit type that keeps a proof from ever being accepted as an ID token or an access token.
  4. alg names an asymmetric signature algorithm: never none, never an HS* MAC, and, if you list them, one of the algorithms your server advertises in dpop_signing_alg_values_supported.
  5. The jwk header holds a public key only. A proof whose key carries d, p, q or other private members means the client published its private key; the inspector flags it, and the share link refuses such a proof.
  6. The signature verifies with that embedded key, using the jose library restricted to the header's own algorithm.
  7. htm equals the request method — case-sensitively, as HTTP methods are.
  8. htu equals the request URI after normalisation.
  9. nonce equals the server's most recent DPoP-Nonce, when the server issued one.
  10. iat lies within the acceptance window: not in the future beyond the clock skew, and not older than the age you allow (five minutes by default).
  11. ath equals the hash of the presented access token.
  12. The proof's key is the key the token is bound to.

Replay detection by jti is server state, so the inspector reports the length of jti (RFC 9449 asks for at least 96 bits of randomness) but cannot know which values a server has already seen.

How htu is compared

The RFC compares htu with the request URI without query and fragment, after the syntax- and scheme-based normalisation of RFC 3986 §6.2.2 and §6.2.3: scheme and host in lower case, the default port removed, percent-encoded unreserved characters decoded, an empty path written as /. The inspector shows both normalised values next to each other, which is usually enough to spot the real culprit — a proxy that rewrote the host, an http:// URL behind a TLS terminator, or a client that put the query string into htu.

The jkt thumbprint and ath

Two values tie the pieces together. The first is the JWK thumbprint of the proof key (RFC 7638): the SHA-256 hash of the key's required members in lexicographic order, base64url-encoded. An authorization server writes it into a JWT access token as cnf.jkt, returns it from introspection, or receives it in advance as the dpop_jkt authorization request parameter. The inspector computes it, lets you copy it, and compares it with the value you give — or with the cnf.jkt it reads from a JWT access token, without verifying that token's own signature.

The second is ath: base64url(SHA-256(ASCII(access token))). It binds the proof to one token, so a proof captured with one token cannot be replayed with another. To check it, paste the access token; it is hashed in the page and is never placed into share links, because a token presented to a server that does not enforce the binding still works as a bearer token.

Going further

DPoP binds a token to a key but signs only the method and the URL. When the body and headers of a request must be protected too, that is the job of HTTP Message Signatures. To look inside an access token itself, paste it into the JWT debugger; to validate an OpenID Connect ID token issued in the same flow, use the OIDC token validator. The whole flow, with client and server code, is in DPoP explained.