quarkusio/quarkus · error · AuthenticationFailedException
DPoP proof jwk header does not represent a valid JWK key
Error message
DPoP proof jwk header does not represent a valid JWK key
What it means
Thrown when the DPoP proof's 'jwk' header is present but its contents cannot be parsed as a valid public JWK by jose4j (PublicJsonWebKey.Factory.newPublicJwk throws JoseException). The proof's key material is malformed or of an unsupported type, so verification cannot proceed.
Source
Thrown at extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcIdentityProvider.java:275
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()));
}
if (publicJsonWebKey.getPrivateKey() != null) {
LOG.warn("DPoP proof JWK key is a private key but it must be a public key");
throw new AuthenticationFailedException(invalidDPoPProofMap(request.getToken()));
}
byte[] jwkProofDigest = publicJsonWebKey.calculateThumbprint("SHA-256");
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);View on GitHub (pinned to e1c734241f)
Solutions
- Emit a standards-compliant JWK object in the header: kty, and for EC kty=EC with crv/x/y, for RSA kty=RSA with n/e, base64url-encoded without padding.
- Use an established JOSE library (jose4j, nimbus-jose-jwt) to build the proof instead of hand-rolling the header.
- Avoid unsupported key types/curves; prefer ES256 (P-256) which Quarkus and ASes widely support.
- Validate locally with PublicJsonWebKey.Factory.newPublicJwk(json) before sending the proof.
Example fix
// before: PEM string in header
"jwk": "-----BEGIN PUBLIC KEY-----..."
// after: proper JWK object
"jwk": {"kty":"EC","crv":"P-256","x":"...","y":"..."} Defensive patterns
Strategy: validation
Validate before calling
// Pre-validate the JWK with jose4j before sending the proof
try {
PublicJsonWebKey.Factory.newPublicJwk(jwkMap);
} catch (JoseException e) {
throw new IllegalArgumentException("Proof jwk header is not a valid public JWK", e);
} Type guard
static boolean isValidPublicJwk(Map<String,Object> jwk) {
try { PublicJsonWebKey.Factory.newPublicJwk(jwk); return true; }
catch (JoseException e) { return false; }
} Try / catch
try {
return callWithProof(buildProof());
} catch (AuthenticationFailedException e) {
throw new IllegalStateException("Fix proof jwk: use kty EC (crv/x/y) or RSA (n/e), base64url", e);
} Prevention
- Prefer ES256/P-256 keys — universally supported
- Emit only standard JWK members, base64url without padding
- Never place a PEM or certificate string in the jwk header
- Round-trip test: serialize, parse, verify locally before deploying
When it happens
Trigger: The jwk header map has missing/incorrect members (wrong 'kty', missing 'crv' for EC, bad base64url 'n'/'e' for RSA), or the JSON is not a JWK at all (e.g. a PEM string or certificate object pasted in).
Common situations: Manually serializing a java.security.PublicKey incorrectly; using an unsupported curve/algorithm; double-encoding the JWK as a JSON string instead of an object inside the header.
Related errors
- DPoP proof JWK key is a private key but it must be a public
- DPoP access token does not contain a confirmation 'cnf' clai
- DPoP proof jwk header is missing
- DPoP access token JWK thumbprint does not match the DPoP pro
- DPoP proof token signature is invalid
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/d62672329da9392f.
Report an issue: GitHub.