apache/pulsar · error · AuthenticationException
SASL/JAAS error${e.getCause()}
Error message
SASL/JAAS error${e.getCause()} What it means
evaluateChallenge runs saslClient.evaluateChallenge inside Subject.doAs (JAAS). Any Exception raised there — SaslException from a failed GSSAPI exchange, PrivilegedActionException from the subject, GSS exceptions, IO problems — is caught and rethrown as an AuthenticationException with the message 'SASL/JAAS error' plus the cause. It signals the Kerberos/SASL handshake step itself failed.
Source
Thrown at pulsar-client-auth-sasl/src/main/java/org/apache/pulsar/client/impl/auth/PulsarSaslClient.java:113
if (saslToken == null) {
throw new AuthenticationException("saslToken is null");
}
try {
if (clientSubject != null) {
final byte[] retval = Subject.doAs(clientSubject, new PrivilegedExceptionAction<byte[]>() {
@Override
public byte[] run() throws SaslException {
return saslClient.evaluateChallenge(saslToken.getBytes());
}
});
return AuthData.of(retval);
} else {
return AuthData.of(saslClient.evaluateChallenge(saslToken.getBytes()));
}
} catch (Exception e) {
log.error().exception(e.getCause()).log("SASL error");
throw new AuthenticationException("SASL/JAAS error" + e.getCause());
}
}
public boolean hasInitialResponse() {
return saslClient.hasInitialResponse();
}
static class ClientCallbackHandler implements CallbackHandler {
@Override
public void handle(Callback[] callbacks) throws UnsupportedCallbackException {
for (Callback callback : callbacks) {
if (callback instanceof AuthorizeCallback) {
handleAuthorizeCallback((AuthorizeCallback) callback);
} else {
throw new UnsupportedCallbackException(callback, "Unrecognized SASL GSSAPI Client Callback.");
}
}
}View on GitHub (pinned to 820761864e)
Solutions
- Check the logged cause ('SASL error' line) — it names the underlying GSS/SASL problem
- Re-run kinit / confirm the keytab is valid and the ticket isn't expired (klist)
- Verify client principal in JAAS config matches what the broker authorizes and service principal is correct for the broker host (serverType/hostname)
- Ensure clock sync (NTP) between client, broker, and KDC; Kerberos fails with skew
- Confirm broker and client negotiate the same SASL mechanism (GSSAPI) and realm
Example fix
// before: token evaluated after ticket expiry without refresh
AuthData resp = saslClient.evaluateChallenge(challenge);
// after: ensure fresh credentials before handshake
if (!subject.getPrincipals().isEmpty() && isTicketExpired(subject)) {
reloginFromKeytab(); // refresh TGT from keytab
}
AuthData resp = saslClient.evaluateChallenge(challenge); Defensive patterns
Strategy: try-catch
Validate before calling
// before connecting, validate Kerberos credentials
import org.apache.pulsar.shade.javax.security.auth.kerberos.KerberosTicket;
boolean hasValidTgt(javax.security.auth.Subject s) {
return s.getPrincipals().size() > 0
&& s.getPrivateCredentials(KerberosTicket.class).stream()
.anyMatch(t -> !t.isDestroyed() && t.getEndTime().after(new java.util.Date()));
} Type guard
boolean isKerberosReady(javax.security.auth.Subject s) {
return s != null && !s.getPrincipals().isEmpty();
} Try / catch
try {
AuthData resp = saslClient.evaluateChallenge(challenge);
} catch (javax.naming.AuthenticationException e) {
// e.getMessage() starts with 'SASL/JAAS error' + cause; refresh creds, then optionally retry handshake
log.warn("SASL handshake failed: {}", e.getMessage(), e);
if (isTransient(e)) {
reloginFromKeytab();
// rebuild PulsarSaslClient and retry once
} else {
throw new IllegalStateException("Kerberos configuration error — fix JAAS/principal/clock", e);
}
} Prevention
- Run kinit or keytab-based auto-relogin before starting long-lived clients
- Sync clocks (NTP) across client, broker, and KDC
- Verify service principal hostnames resolve and match broker reverse DNS
- Keep client JAAS principal consistent with broker's authorized principals
- Catch AuthenticationException and rebuild the SASL client rather than reusing a failed handshake
When it happens
Trigger: Any exception from saslClient.evaluateChallenge(bytes) while processing a broker challenge: corrupt/out-of-order token, GSSAPI context failure, expired Kerberos ticket, clock skew, or doAs failing due to subject/privilege problems.
Common situations: Kerberos ticket expired mid-connection (kinit not refreshed); keytab principal mismatch between client JAAS config and broker; hostname/reverse-DNS mismatch causing GSSAPI service principal mismatch; broker and client SASL mechanism mismatch; clock skew between client and KDC.
Related errors
- Cannot create SASL client with empty JAAS subject principal
- Authentication use SASL/JAAS/GSSAPI but server not have Prin
- Unrecognized SASL GSSAPI Server Callback.
- loginContext name (JAAS file section header) was null. Pleas
- Kerberos authentication without KerberosTicket provided!
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/6ebe57a9340bcdf8.
Report an issue: GitHub.