Skip to content

Invalid DPoP Proof

URI: https://docs.ankatech.co/errors/invalid_dpop_proof
HTTP Status: 400 Bad Request (token endpoint) · 401 Unauthorized (Admin API)

This error corresponds to the RFC 9449 OAuth 2.0 error code invalid_dpop_proof of the same name. The RFC 9457 type suffix uses the identical underscore form so the two identifiers match.

When you see this

An administrative workload* sent a DPoP proof (RFC 9449) that was refused. A proof is a fresh JWS that binds one request to the key the workload's token is bound to.

  • At the token endpoint (POST /api/v3/auth/token) the answer is 400 with the body below. The proof is checked before any credential, so no credential was examined and no token was issued.
  • At the Admin API the answer is 401 with WWW-Authenticate: DPoP error="invalid_dpop_proof", algs="ES256 ES384 PS256 RS256" and the Admin API's unauthenticated problem body. Nothing changed.

Common Causes

  • No DPoP header, or more than one.
  • typ is not dpop+jwt; the algorithm is none, an HMAC or anything but ES256, ES384, PS256, RS256; the jwk header carries a private member; the signature does not verify.
  • htm is not the request's method, or htu is not the request's public URL. At the token endpoint htu must equal the token_endpoint of the authorization server metadata; at the Admin API, the public URL of the request without query or fragment.
  • iat is more than 60 seconds old or more than 5 seconds in the future (check the client clock).
  • The proof's jti was already used: every request needs a new proof.
  • At the Admin API: ath is not the hash of the presented token, or the proof key is not the key the token is bound to (cnf.jkt).

Response Example

{
  "error": "invalid_dpop_proof",
  "error_description": "The DPoP proof is invalid",
  "error_uri": "https://docs.ankatech.co/errors/invalid_dpop_proof",
  "type": "https://docs.ankatech.co/errors/invalid_dpop_proof",
  "title": "Invalid Dpop Proof",
  "status": 400,
  "detail": "The DPoP proof is invalid",
  "instance": "/api/v3/auth/token",
  "timestamp": 1730000000
}

Content-Type: application/json at the token endpoint, as for every RFC 6749 §5.2 token error. The Auth API carries no correlation member in the body: correlate through the X-Correlation-Id response header.

How to Resolve

  1. Build a new proof for every request, with a fresh jti and the current time as iat.
  2. Take the token endpoint URL for htu from GET /api/v3/auth/.well-known/oauth-authorization-server (token_endpoint), never from the address you happen to dial.
  3. Sign every proof with the same key the token was issued for, and include ath on Admin API requests.
  4. The Key Management SDK and the Key Management CLI build proofs for you; prefer them to hand-written clients.

For full schema definitions, examples, and interactive testing, see the Developer Hub Reference.

* restricted content — see higher-tier documentation