Skip to content

The v1 docs follow nauthera-server's main branch and its 0.x releases on the way to 1.0, so fields and APIs can still change.

v1

invalid_dpop_proof

Docs version v1 (main)Nauthera is pre-1.0, in a design-partner program

The DPoP proof is missing or fails a validation check (RFC 9449 §4.3, §7.1).

Meaning

At /token (400, OAuth error body), a DPoP header that is not a valid proof for the request: too large or malformed, a typ other than dpop+jwt, an algorithm outside ES256, PS256/384/512 and RS256/384/512, a missing or private jwk, an unsupported key, a bad signature, missing claims, htm or htu not matching the request, an iat more than 60 seconds old or more than 5 seconds ahead, or a reused jti. At /userinfo and other protected resources (401, WWW-Authenticate: DPoP), also a bound token sent without a proof, or a proof whose ath does not match the token.

Impact

The request fails; the client gets no token or no claims. Mostly a client bug, a proxy that changes the URL the client signs, or clock skew on the client.

Diagnosis

  1. At /token the refusal is recorded under oauth.token.issued (or oauth.token.refreshed) with reason invalid_dpop_proof; at a protected resource under oauth.token.presented. The cause names the check, such as dpop_htu_mismatch, dpop_iat_too_old, dpop_iat_in_future, dpop_proof_replayed or dpop_ath_missing, and a refused iat records skew_seconds.
  2. For dpop_htu_mismatch, compare the htu with the issuer followed by the endpoint path, which is what the server checks.

Mitigation

  • As a client developer: create a new proof for every request, with htm and htu of that request, a fresh jti and the current time; at a resource include ath. See DPoP.
  • As an operator: if skew_seconds is large for every client, check the server's clock.
  • As a user: tell the application's owner.

Escalation

If a proof that satisfies RFC 9449 §4.3 is refused, open an issue with the request id, the server version and the recorded cause. Never attach the proof or the token.


OAuth error runbooks · Generated from internal/runbook/oauth.yaml in nauthera-server.