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

  1. Configure the client with a valid TLS key/cert (keystore and keyStorePassword) so mutual TLS presents a certificate chain
  2. Verify the broker advertises TLS and requires client certificates (tlsRequireValidClientCertificate=true)
  3. 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

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

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/18e836e25bbe789e. Report an issue: GitHub.