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 supported

View on GitHub (pinned to e1c734241f)

Solutions

  1. Sign the proof with an asymmetric algorithm allowed by the constraints (ES256/RS256 etc.) and send the standard compact JWS.
  2. Check that no intermediary truncates or re-encodes the DPoP header value.
  3. Locally pre-verify with jose4j (new JsonWebSignature + verifySignature) before sending to catch malformed proofs early.
  4. 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

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


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/601de83fba7428ac. Report an issue: GitHub.