apache/pulsar · error · AuthenticationException
Invalid signed text:
Error message
Invalid signed text:
What it means
SaslRoleTokenSigner.verifyAndExtract verifies HMAC-signed strings (format: payload + SIGNATURE marker + signature). If the input string does not contain the SIGNATURE separator at all, it is not a signed string produced by sign(), so an AuthenticationException is thrown with the offending text appended.
Source
Thrown at pulsar-broker-auth-sasl/src/main/java/org/apache/pulsar/broker/authentication/SaslRoleTokenSigner.java:74
throw new IllegalArgumentException("NULL or empty string to sign");
}
String signature = computeSignature(str);
return str + SIGNATURE + signature;
}
/**
* 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) {View on GitHub (pinned to 820761864e)
Solutions
- Ensure the string passed to verifyAndExtract() comes from SaslRoleTokenSigner.sign() (or an equivalent client using the same secret) and was not truncated
- Check that no intermediary (proxy, header parser) strips or mangles the signed token before it reaches the broker
- Log/inspect the received string to confirm where the signature part was lost
Example fix
// before
String role = signer.verifyAndExtract(rawToken); // throws if rawToken unsigned
// after
if (rawToken == null || !rawToken.contains(SaslRoleTokenSigner.SIGNATURE)) {
throw new AuthenticationException("token missing signature");
}
String role = signer.verifyAndExtract(rawToken); Defensive patterns
Strategy: validation
Validate before calling
if (signedStr == null || !signedStr.contains(SIGNATURE)) {
throw new AuthenticationException("not a signed token");
} Type guard
static boolean isSigned(String s) {
return s != null && s.lastIndexOf(SaslRoleTokenSigner.SIGNATURE) >= 0;
} Try / catch
try {
String role = signer.verifyAndExtract(signedStr);
} catch (AuthenticationException e) {
// reject request / force re-auth
} Prevention
- Only pass tokens obtained from signer.sign()
- Beware proxies truncating headers
- Add contains-check before verifying
When it happens
Trigger: Calling verifyAndExtract() with a plain, unsigned, empty, or malformed string that lacks the signature separator (e.g. token truncated before the signature, or a value fetched from the wrong config/cookie field).
Common situations: SASL authentication handshakes where the client sent a raw role token instead of the signed one; proxy/load-balancer stripping or truncating the token; manually constructed credentials in tests or scripts.
Related errors
- Invalid signature
- Invalid broker configuration. Authentication must be enabled
- ERROR_VERIFYING_JWT_SIGNATURE
- Authentication use SASL/JAAS/GSSAPI but server not have Prin
- Unrecognized SASL GSSAPI Server Callback.
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/ba8b0d4cd73a5db7.
Report an issue: GitHub.