quarkusio/quarkus · error · AuthenticationFailedException
DPoP proof token signature can not be verified
Error message
DPoP proof token signature can not be verified
What it means
Thrown when verifying the DPoP proof throws a JoseException (malformed compact serialization, unsupported algorithm, key/alg conflict, etc.), so the signature cannot even be attempted/verified. Unlike error 1227 (verification returned false), this is an exception during the verification process itself.
Source
Thrown at extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcIdentityProvider.java:302
String jwkProofThumbprint = OidcCommonUtils.base64UrlEncode(jwkProofDigest);
if (!dpopJwkThumbprint.equals(jwkProofThumbprint)) {
LOG.warn("DPoP access token JWK thumbprint does not match the DPoP proof JWK thumbprint");
throw new AuthenticationFailedException(invalidDPoPProofMap(request.getToken()));
}
try {
JsonWebSignature jws = new JsonWebSignature();
jws.setAlgorithmConstraints(OidcProvider.ASYMMETRIC_ALGORITHM_CONSTRAINTS);
jws.setCompactSerialization((String) requestData.get(OidcUtils.DPOP_PROOF));
jws.setKey(publicJsonWebKey.getPublicKey());
if (!jws.verifySignature()) {
LOG.warn("DPoP proof token signature is invalid");
throw new AuthenticationFailedException(invalidDPoPProofMap(request.getToken()));
}
} catch (JoseException ex) {
LOG.warn("DPoP proof token signature can not be verified");
throw new AuthenticationFailedException(ex, invalidDPoPProofMap(request.getToken()));
}
JsonObject proofClaims = (JsonObject) requestData.get(OidcUtils.DPOP_PROOF_JWT_CLAIMS);
// Calculate the access token thumprint and compare with the `ath` claim
String accessTokenProof = proofClaims.getString(OidcConstants.DPOP_ACCESS_TOKEN_THUMBPRINT);
if (accessTokenProof == null) {
LOG.warn("DPoP proof access token hash is missing");
throw new AuthenticationFailedException(invalidDPoPProofMap(request.getToken()));
}
String accessTokenHash = null;
try {
accessTokenHash = OidcCommonUtils.base64UrlEncode(
OidcUtils.getSha256Digest(request.getToken().getToken()));
} catch (NoSuchAlgorithmException ex) {
// SHA256 is always supportedView on GitHub (pinned to e1c734241f)
Solutions
- Sign the proof with an asymmetric algorithm allowed by the constraints (ES256/RS256 etc.) and send the standard compact JWS.
- Check that no intermediary truncates or re-encodes the DPoP header value.
- Locally pre-verify with jose4j (new JsonWebSignature + verifySignature) before sending to catch malformed proofs early.
- Catch AuthenticationFailedException, log the JoseException cause, and fix the proof construction accordingly.
Example fix
// before jws.setAlgorithmConstraints(...); jws.setKey(hmacKey); // symmetric -> rejected // after jws.setAlgorithmConstraints(ASYMMETRIC_ALGORITHM_CONSTRAINTS); jws.setKey(ecPublicKey); // ES256 and similar asymmetric algs only
Defensive patterns
Strategy: validation
Validate before calling
// Pre-parse and constrain algorithms before sending
try {
JsonWebSignature jws = new JsonWebSignature();
jws.setCompactSerialization(proof);
jws.setAlgorithmConstraints(OidcProvider.ASYMMETRIC_ALGORITHM_CONSTRAINTS);
jws.setKey(publicKey);
jws.verifySignature();
} catch (JoseException e) {
throw new IllegalArgumentException("Malformed proof or unsupported/symmetric alg", e);
} Type guard
static boolean isCompactJws(String s) {
return s != null && s.chars().filter(c -> c == '.').count() == 2 && !s.contains(" ");
} Try / catch
try {
return call();
} catch (AuthenticationFailedException e) {
log.warnf("DPoP proof rejected (JoseException cause): check alg/key and compact form");
return callWithRebuiltProof();
} Prevention
- Use asymmetric algorithms only (ES256, RS256, EdDSA); never HS256 or none
- Send a standard 3-segment compact JWS in the DPoP header
- Check intermediaries for header truncation/re-encoding
- Pre-verify with jose4j locally in tests
When it happens
Trigger: The DPoP proof string is not a valid 3-segment compact JWS; the proof's 'alg' is not an asymmetric algorithm accepted by OidcProvider.ASYMMETRIC_ALGORITHM_CONSTRAINTS (e.g. HS256, or 'none'); corrupt base64url segments.
Common situations: Sending a JWE or opaque token in the DPoP header; clients using symmetric algorithms; truncation of the header value by middleware or size-limited HTTP stacks.
Related errors
- DPoP proof token signature is invalid
- DPoP access token does not contain a confirmation 'cnf' clai
- DPoP proof jwk header is missing
- DPoP proof jwk header does not represent a valid JWK key
- DPoP proof JWK key is a private key but it must be a public
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/601de83fba7428ac.
Report an issue: GitHub.