apereo/cas · error · IllegalArgumentException
Proof JWT algorithm does not match RSA holder key
Error message
Proof JWT algorithm does not match RSA holder key
What it means
Thrown by OidcVerifiableCredentialJwtProofValidator.verifyAlgorithm when the holder JWK is an RSAKey but the proof JWT's alg header is not in the JWSAlgorithm.RSA family (e.g. an ES256-signed JWT presented against an RSA holder key). The algorithm must be cryptographically consistent with the presented holder key type.
Solutions
- Sign the proof with an RSA-family algorithm (RS256/RS384/RS512, PS*) when the holder key is RSA.
- Align the signing key with the holder JWK type bound to the request.
- Make the proof builder choose the algorithm from the key type instead of hardcoding it.
Example fix
// before signed.sign(new ECDSASigner(ecKeyPair.getPrivate())); // EC alg, RSA holder key // after signed.sign(new RSASSASigner(rsaKeyPair.getPrivate()));
Defensive patterns
Strategy: validation
Validate before calling
if (holderJwk instanceof RSAKey && !JWSAlgorithm.Family.RSA.contains(alg)) {
throw new IllegalArgumentException("Use an RSA-family algorithm for RSA holder keys");
} Prevention
- Derive the signing algorithm from the holder key type instead of hardcoding it.
- Keep key type and algorithm in sync during key rotation.
When it happens
Trigger: Proof JWT signed with an EC algorithm while the bound holder JWK is RSA; kid resolving to an RSA JWK but the client signing with an EC key; generic proof-builder hardcoding ES256 regardless of key type.
Common situations: Copy-pasted proof code using ES256 defaults while the key material bound to the credential request is RSA; key rotation replacing an EC key with RSA (or vice versa) without updating signing code.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Proof JWT algorithm does not match EC holder key
- Proof JWT signature validation failed
- Proof JWT algorithm is invalid
- Could not determine the hash algorithm for token
- Proof nonce is invalid or missing
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/7e4bc8fa8737590c.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-oidc-vc/src/main/java/org/apereo/cas/oidc/vc/issuer/proof/OidcVerifiableCredentialJwtProofValidator.java:91
throw new IllegalArgumentException("Proof JWT signature validation failed");
}
}
protected void verifyAudience(final SignedJWT signedJwt) throws ParseException {
val audiences = signedJwt.getJWTClaimsSet().getAudience();
val credentialIssuer = casProperties.getAuthn().getOidc().getCore().getIssuer();
if (audiences == null || !audiences.contains(credentialIssuer)) {
throw new IllegalArgumentException("Proof audience does not match credential issuer");
}
}
protected void verifyAlgorithm(final SignedJWT signedJwt, final JWK holderJwk) {
val alg = signedJwt.getHeader().getAlgorithm();
if (alg == null || Algorithm.NONE.equals(alg)) {
throw new IllegalArgumentException("Proof JWT algorithm is invalid");
}
if (holderJwk instanceof RSAKey && !JWSAlgorithm.Family.RSA.contains(alg)) {
throw new IllegalArgumentException("Proof JWT algorithm does not match RSA holder key");
}
if (holderJwk instanceof ECKey && !JWSAlgorithm.Family.EC.contains(alg)) {
throw new IllegalArgumentException("Proof JWT algorithm does not match EC holder key");
}
}
protected void verifyFreshness(final SignedJWT signedJwt) throws ParseException {
val claims = signedJwt.getJWTClaimsSet();
val issuedAt = claims.getIssueTime();
if (issuedAt == null) {
throw new IllegalArgumentException("Proof JWT is missing iat");
}
val now = Instant.now(Clock.systemUTC());
val iat = issuedAt.toInstant();
if (iat.isAfter(now.plusSeconds(SECONDS_IN_FUTURE))) {
throw new IllegalArgumentException("Proof iat is in the future");
}
if (iat.isBefore(now.minus(Duration.ofMinutes(MINUTES_IN_PAST)))) {View on GitHub (pinned to e7288fc434)