apache/pulsar · error · AuthenticationException
Failed to get TLS certificates from client
Error message
Failed to get TLS certificates from client
What it means
AuthenticationProviderTls.authenticate() extracts the client's X.509 certificate chain from the AuthenticationDataSource to derive the role from the certificate's CN. It throws this AuthenticationException when getTlsCertificates() returns null — the client presented no TLS certificate chain, so there is nothing to authenticate against.
Source
Thrown at pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationProviderTls.java:97
* if (authData.hasDataFromHttp()) {
* String authType = authData.getHttpAuthType();
* if (!HttpServletRequest.CLIENT_CERT_AUTH.equals(authType)) {
* throw new AuthenticationException(
* String.format( "Authentication type mismatch, Expected: %s, Found: %s",
* HttpServletRequest.CLIENT_CERT_AUTH, authType));
* }
* }
* </code>
*/
// Extract CommonName
// The format is defined in RFC 2253.
// Example:
// CN=Steve Kille,O=Isode Limited,C=GB
Certificate[] certs = authData.getTlsCertificates();
if (null == certs) {
errorCode = ErrorCode.INVALID_CERTS;
throw new AuthenticationException("Failed to get TLS certificates from client");
}
String distinguishedName = ((X509Certificate) certs[0]).getSubjectX500Principal().getName();
for (String keyValueStr : distinguishedName.split(",")) {
String[] keyValue = keyValueStr.split("=", 2);
if (keyValue.length == 2 && "CN".equals(keyValue[0]) && !keyValue[1].isEmpty()) {
commonName = keyValue[1];
break;
}
}
}
if (commonName == null) {
errorCode = ErrorCode.INVALID_CN;
throw new AuthenticationException("Client unable to authenticate with TLS certificate");
}
authenticationMetrics.recordSuccess();
} catch (AuthenticationException exception) {
incrementFailureMetric(errorCode);View on GitHub (pinned to 820761864e)
Solutions
- Configure the client with a valid TLS key/cert (keystore and keyStorePassword) so mutual TLS presents a certificate chain
- Verify the broker advertises TLS and requires client certificates (tlsRequireValidClientCertificate=true)
- Check any proxy in front of the broker forwards the client certificate (e.g. proxyProtocol / forward TLS)
Example fix
// client.conf before webSocketServiceUrl= # no TLS config // after useTls=true tlsKeyFilePath=/path/client.key.pem tlsCertificateFilePath=/path/client-cert.pem tlsTrustCertsFilePath=/path/ca-cert.pem
Defensive patterns
Strategy: validation
Validate before calling
Certificate[] certs = authData.getTlsCertificates();
if (certs == null || certs.length == 0) {
throw new AuthenticationException("Client did not present a TLS certificate");
} Type guard
boolean hasTlsCerts(AuthenticationDataSource d) {
try { return d.getTlsCertificates() != null && d.getTlsCertificates().length > 0; }
catch (Exception e) { return false; }
} Try / catch
try {
role = provider.authenticate(authData);
} catch (AuthenticationException e) {
log.warn("TLS auth failed: no client certificate; check client keystore", e);
} Prevention
- Configure client keystore/cert files and verify mTLS handshake succeeds
- Set tlsRequireValidClientCertificate=true on the broker so bad connections fail early at handshake
- Test with: openssl s_client -connect broker:6651 -cert client.pem -key client.key
When it happens
Trigger: Calling authenticate(AuthenticationDataSource) where authData.getTlsCertificates() returns null — the TLS handshake had no client cert or the data source does not carry certificates.
Common situations: Client not configured with a keystore/truststore for mutual TLS; the `tlsRequireValidClientCertificate` / `authProviders` mismatch where TLS auth is enabled but the client connects without mTLS; certificate not propagated through an intermediate proxy.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Client unable to authenticate with TLS certificate
- certFilePath must not be null
- keyFilePath must not be null
- certStream provider or stream must not be null
- keyStream provider or stream must not be null
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/18e836e25bbe789e.
Report an issue: GitHub.