quarkusio/quarkus · error · AuthenticationFailedException
DPoP access token does not contain a confirmation 'cnf' clai
Error message
DPoP access token does not contain a confirmation 'cnf' claim with the JWK thumbprint
What it means
Thrown during DPoP (RFC 9449) proof-of-possession verification: the access token must contain a 'cnf' claim with a 'jkt' (JWK thumbprint) value binding it to the sender's DPoP key, but no such claim exists. Quarkus then rejects the DPoP-bound request because the token cannot be tied to the proof's public key.
Source
Thrown at extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcIdentityProvider.java:259
throw new AuthenticationFailedException(tokenMap(request.getToken()));
}
return t;
}
});
}
if (requestData.containsKey(OidcUtils.DPOP_PROOF_JWT_HEADERS)) {
result = result.onItem().transform(new Function<TokenVerificationResult, TokenVerificationResult>() {
@Override
public TokenVerificationResult apply(TokenVerificationResult t) {
String dpopJwkThumbprint = getDpopJwkThumbprint(requestData, t);
if (dpopJwkThumbprint == null) {
LOG.warn(
"DPoP access token does not contain a confirmation 'cnf' claim with the JWK thumbprint");
throw new AuthenticationFailedException(invalidDPoPProofMap(request.getToken()));
}
JsonObject proofHeaders = (JsonObject) requestData.get(OidcUtils.DPOP_PROOF_JWT_HEADERS);
JsonObject jwkProof = proofHeaders.getJsonObject(OidcConstants.DPOP_JWK_HEADER);
if (jwkProof == null) {
LOG.warn("DPoP proof jwk header is missing");
throw new AuthenticationFailedException(invalidDPoPProofMap(request.getToken()));
}
PublicJsonWebKey publicJsonWebKey = null;
try {
publicJsonWebKey = PublicJsonWebKey.Factory.newPublicJwk(jwkProof.getMap());
} catch (JoseException ex) {
LOG.warn("DPoP proof jwk header does not represent a valid JWK key");
throw new AuthenticationFailedException(ex, invalidDPoPProofMap(request.getToken()));
}
View on GitHub (pinned to e1c734241f)
Solutions
- Obtain the access token by sending a DPoP proof JWT with the token request so the AS embeds cnf.jkt (quarkus.oidc-client with DPoP enabled, or add the DPoP header to the token call).
- Ensure quarkus.oidc.token.verify-access-token-with-user-info / DPoP settings are consistent: if DPoP proofs are sent, tokens must be DPoP-bound by the AS.
- Disable DPoP proof generation on the HTTP client if the token is not DPoP-bound.
- Catch AuthenticationFailedException and re-authenticate to obtain a DPoP-bound token.
Example fix
// before: plain token + DPoP proof header
client.post("/protected").putHeader("DPoP", proof(token));
// after: request DPoP-bound token
// token request also carries a DPoP proof (htiu=token endpoint) so cnf.jkt is issued
client.post("/token").putHeader("DPoP", proofForTokenEndpoint(...)); Defensive patterns
Strategy: validation
Validate before calling
// Check the token is DPoP-bound before sending a DPoP proof
JsonWebToken jwt = parseUnverified(token);
var cnf = jwt.getClaimValue("cnf", Map.class);
if (cnf == null || cnf.get("jkt") == null) {
token = obtainDpopBoundToken(); // include a DPoP proof in the token request
} Type guard
static boolean isDpopBoundToken(JsonWebToken t) {
Map<String,Object> cnf = t.getClaimValue("cnf", Map.class);
return cnf != null && cnf.containsKey("jkt");
} Try / catch
try {
return callWithDpop(token);
} catch (AuthenticationFailedException e) {
return callWithDpop(refreshDpopBoundToken());
} Prevention
- Always request tokens with a DPoP proof when using DPoP at the resource server
- Don't enable DPoP proof headers globally for non-DPoP tokens
- Re-authenticate after changing client DPoP configuration
- Inspect cnf.jkt presence when debugging DPoP failures
When it happens
Trigger: A request includes a DPoP proof header, so the provider runs DPoP verification, but the access token was issued without DPoP binding (no cnf.jkt) — e.g. the token was obtained via a plain client_credentials/token call instead of one that sends the DPoP proof JWT to the token endpoint.
Common situations: Mixing a normal (non-DPoP) access token with a DPoP proof header added by an HTTP client library that enables DPoP globally; authorization server configured to issue DPoP tokens only for some clients; token obtained before enabling DPoP on the client.
Related errors
- DPoP access token hash does not match the DPoP proof access
- The '%s' annotation is only supported when proactive authent
- Client certificate thumbprint is not available
- DPoP proof jwk header is missing
- DPoP proof jwk header does not represent a valid JWK key
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/699c2f014fad053d.
Report an issue: GitHub.