apache/pulsar · error · AuthenticationException
Invalid signature
Error message
Invalid signature
What it means
After locating the signature suffix in a signed string, verifyAndExtract recomputes the HMAC over the payload with its configured secret and compares it to the received signature. If they differ the string was signed with a different secret or modified in transit, so an AuthenticationException "Invalid signature" is thrown. The comparison uses MessageDigest.isEqual (constant time) to avoid timing attacks.
Source
Thrown at pulsar-broker-auth-sasl/src/main/java/org/apache/pulsar/broker/authentication/SaslRoleTokenSigner.java:80
/**
* Verifies a signed string and extracts the original string.
*
* @param signedStr the signed string to verify and extract.
*
* @return the extracted original string.
*
* @throws AuthenticationException thrown if the given string is not a signed string or if the signature is invalid.
*/
public String verifyAndExtract(String signedStr) throws AuthenticationException {
int index = signedStr.lastIndexOf(SIGNATURE);
if (index == -1) {
throw new AuthenticationException("Invalid signed text: " + signedStr);
}
String originalSignature = signedStr.substring(index + SIGNATURE.length());
String rawValue = signedStr.substring(0, index);
String currentSignature = computeSignature(rawValue);
if (!MessageDigest.isEqual(originalSignature.getBytes(), currentSignature.getBytes())){
throw new AuthenticationException("Invalid signature");
}
return rawValue;
}
/**
* Returns the signature of a string.
*
* @param str string to sign.
*
* @return the signature for the string.
*/
protected String computeSignature(String str) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-512");
md.update(str.getBytes());
md.update(secret);View on GitHub (pinned to 820761864e)
Solutions
- Verify all broker nodes share the identical secretKey for SaslRoleTokenSigner
- Re-issue the token: re-authenticate so the client gets a token signed with the current secret
- If tampering is suspected, treat it as a security event and reject the request
Example fix
// server config: keep the same secret everywhere
// broker.conf (each node)
// saslRoleTokenSignerSecret=shared-hmac-secret
String role;
try {
role = signer.verifyAndExtract(signedToken);
} catch (AuthenticationException e) {
// force client re-authentication
throw new RestException(Response.Status.UNAUTHORIZED, "re-authenticate");
} Defensive patterns
Strategy: try-catch
Try / catch
try {
String role = signer.verifyAndExtract(signedStr);
} catch (AuthenticationException e) {
audit.log("signature mismatch for " + clientAddr); // security signal
respond(401);
} Prevention
- Keep signer secretKey identical across all broker nodes
- Rotate secrets only with coordinated token re-issuance
- Monitor 401 spikes — may indicate tampering or key drift
When it happens
Trigger: verifyAndExtract() receives a well-formed signed string whose signature does not match a recomputation with the current secret key — typically after a broker secret-key change/rotation, or the payload was tampered with.
Common situations: Multiple brokers with different SaslRoleTokenSigner secret keys behind a load balancer; secretKey config changed on one node but not others; token copied between clusters; MITM tampering.
Related errors
- Invalid signed text:
- Invalid broker configuration. Authentication must be enabled
- ERROR_VERIFYING_JWT_SIGNATURE
- Unauthorized to validateBothSuperuserAndClusterOperation for
- Unauthorized to validateBothSuperuserAndClusterPolicyOperati
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/4c73d2854e1ac895.
Report an issue: GitHub.