apache/pulsar · error · AuthenticationException
ALGORITHM_MISMATCH
ALGORITHM_MISMATCH
Error message
Expected PublicKey alg [
What it means
While building the java-jwt Algorithm in verifyJWT, casting the provided PublicKey to the type implied by publicKeyAlg (e.g., (RSAPublicKey) or (ECPublicKey)) failed with ClassCastException — the key's actual type does not match the configured algorithm name. The provider throws AuthenticationException(ALGORITHM_MISMATCH) with a message that (despite the wording) means the expected and actual key types disagree.
Source
Thrown at pulsar-broker-auth-oidc/src/main/java/org/apache/pulsar/broker/authentication/oidc/AuthenticationProviderOpenID.java:439
case ALG_RS512:
alg = Algorithm.RSA512((RSAPublicKey) publicKey, null);
break;
case ALG_ES256:
alg = Algorithm.ECDSA256((ECPublicKey) publicKey, null);
break;
case ALG_ES384:
alg = Algorithm.ECDSA384((ECPublicKey) publicKey, null);
break;
case ALG_ES512:
alg = Algorithm.ECDSA512((ECPublicKey) publicKey, null);
break;
default:
incrementFailureMetric(AuthenticationExceptionCode.UNSUPPORTED_ALGORITHM);
throw new AuthenticationException("Unsupported algorithm: " + publicKeyAlg);
}
} catch (ClassCastException e) {
incrementFailureMetric(AuthenticationExceptionCode.ALGORITHM_MISMATCH);
throw new AuthenticationException("Expected PublicKey alg [" + publicKeyAlg + "] does match actual alg.");
}
// We verify issuer when retrieving the PublicKey, so it is not verified here.
// The claim presence requirements are based on https://openid.net/specs/openid-connect-basic-1_0.html#IDToken
Verification verifierBuilder = JWT.require(alg)
.acceptLeeway(acceptedTimeLeewaySeconds)
.withAnyOfAudience(allowedAudiences)
.withClaimPresence(RegisteredClaims.ISSUED_AT)
.withClaimPresence(RegisteredClaims.EXPIRES_AT)
.withClaimPresence(RegisteredClaims.SUBJECT);
if (isRoleClaimNotSubject) {
verifierBuilder = verifierBuilder.withClaimPresence(roleClaim);
}
JWTVerifier verifier = verifierBuilder.build();
try {View on GitHub (pinned to 820761864e)
Solutions
- Clear the broker's cached JWKS/keys (restart or let the cache refresh) so key 'kid' and algorithm mappings re-resolve together
- Verify that the key file/keystore you configured matches the configured algorithm (RS256/384/512 require an RSA public key; ES256/384/512 require an EC P-256/P-384/P-521 key)
- Check that your OIDC provider hasn't rotated signing keys to a different family; update the broker configuration accordingly
- When loading keys manually, validate key.getAlgorithm() equals the configured publicKeyAlg before calling verifyJWT
Example fix
// before: EC key configured under an RSA algorithm name
publicKeyAlg = "RS256"; publicKey = loadEcPem("idp_ec.pem");
// after: pair matches
publicKeyAlg = "ES256"; publicKey = loadEcPem("idp_ec.pem"); Defensive patterns
Strategy: validation
Validate before calling
boolean algMatchesKey(String alg, PublicKey k) {
boolean isRsa = alg.startsWith("RS");
boolean isEc = alg.startsWith("ES");
return (isRsa && k instanceof RSAPublicKey) || (isEc && k instanceof ECPublicKey);
} Try / catch
try {
return verifyJWT(publicKey, publicKeyAlg, jwt);
} catch (AuthenticationException e) {
if (e.getMessage().startsWith("Expected PublicKey alg")) {
log.error("Key/algorithm mismatch: expected {} got {}", publicKeyAlg, publicKey.getAlgorithm());
}
throw e;
} Prevention
- When configuring keys manually, assert key.getAlgorithm() matches the configured name
- Clear JWKS caches after IdP key rotation to avoid stale key/alg pairings
- Pair 'kid' with its algorithm from the same JWKS entry; never mix entries
- Alert on ClassCastException-driven auth failures — they indicate rotation or misconfiguration
When it happens
Trigger: verifyJWT() receives a publicKey whose runtime type contradicts publicKeyAlg: an EC key while publicKeyAlg says RS256 (or vice versa), an X509/invalid key object, or a null key typed in a way that fails the cast in one of the switch's cast branches.
Common situations: Broker keystore/cache holds a key fetched under the wrong 'kid' so an RSA alg is paired with an EC key; IdP rotated keys and rotated to a different family (RSA -> EC) but the broker cached the old algorithm mapping; manual key configuration specifying RS256 while loading an EC .pem.
Related errors
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/82b825a00ac0b736.
Report an issue: GitHub.