# invalid_dpop_proof

UserInfo refused the DPoP proof for a bound access token (401).

## Meaning

The access token is DPoP-bound and the `DPoP` proof is missing, repeated, malformed,
signed badly, made for another method or URL, too old, replayed, or does not carry
the token's hash (`ath`) (RFC 9449 §4.3, §7.1).

## Impact

The relying party gets no claims until it sends a valid proof. It is a client bug,
or clock skew between the client and the server.

## Diagnosis

Refusals are recorded as `oauth.token.presented` with a `dpop_*` cause, such as
`dpop_proof_missing`, `dpop_htu_mismatch`, `dpop_htm_mismatch`, `dpop_iat_too_old`,
`dpop_ath_mismatch` or `dpop_proof_replayed`. `WWW-Authenticate` gives a fixed
description, never the proof's own values.

## Mitigation

- As a client developer: create a new proof for every request, with `htm` and `htu`
  matching this request, a fresh `jti`, the current time in `iat`, and `ath` set to
  the hash of the access token. Keep the client's clock synchronised.

## Escalation

Escalate when a proof built to RFC 9449 is refused. Open an issue with the request
id, the audit cause, the client library and its version, and the server version.
Never attach the proof or the token.

---

[Problem code runbooks](https://www.nauthera.io/docs/v1/runbooks/problems) · Generated from [`internal/runbook/problems.yaml`](https://github.com/nauthera/nauthera-server/blob/main/internal/runbook/problems.yaml) in nauthera-server.
