{"record":{"id":"18e836e25bbe789e","repo":"apache/pulsar","slug":"failed-to-get-tls-certificates-from-client","errorCode":null,"errorMessage":"Failed to get TLS certificates from client","messagePattern":"Failed to get TLS certificates from client","errorType":"exception","errorClass":"AuthenticationException","httpStatus":null,"severity":"error","filePath":"pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationProviderTls.java","lineNumber":97,"sourceCode":"                 * if (authData.hasDataFromHttp()) {\n                 *     String authType = authData.getHttpAuthType();\n                 *     if (!HttpServletRequest.CLIENT_CERT_AUTH.equals(authType)) {\n                 *         throw new AuthenticationException(\n                 *              String.format( \"Authentication type mismatch, Expected: %s, Found: %s\",\n                 *                       HttpServletRequest.CLIENT_CERT_AUTH, authType));\n                 *     }\n                 * }\n                 * </code>\n                 */\n\n                // Extract CommonName\n                // The format is defined in RFC 2253.\n                // Example:\n                // CN=Steve Kille,O=Isode Limited,C=GB\n                Certificate[] certs = authData.getTlsCertificates();\n                if (null == certs) {\n                    errorCode = ErrorCode.INVALID_CERTS;\n                    throw new AuthenticationException(\"Failed to get TLS certificates from client\");\n                }\n                String distinguishedName = ((X509Certificate) certs[0]).getSubjectX500Principal().getName();\n                for (String keyValueStr : distinguishedName.split(\",\")) {\n                    String[] keyValue = keyValueStr.split(\"=\", 2);\n                    if (keyValue.length == 2 && \"CN\".equals(keyValue[0]) && !keyValue[1].isEmpty()) {\n                        commonName = keyValue[1];\n                        break;\n                    }\n                }\n            }\n\n            if (commonName == null) {\n                errorCode = ErrorCode.INVALID_CN;\n                throw new AuthenticationException(\"Client unable to authenticate with TLS certificate\");\n            }\n            authenticationMetrics.recordSuccess();\n        } catch (AuthenticationException exception) {\n            incrementFailureMetric(errorCode);","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationProviderTls.java#L79-L115","documentation":"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.","triggerScenarios":"Calling authenticate(AuthenticationDataSource) where authData.getTlsCertificates() returns null — the TLS handshake had no client cert or the data source does not carry certificates.","commonSituations":"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.","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)"],"exampleFix":"// client.conf before\nwebSocketServiceUrl=\n# no TLS config\n// after\nuseTls=true\ntlsKeyFilePath=/path/client.key.pem\ntlsCertificateFilePath=/path/client-cert.pem\ntlsTrustCertsFilePath=/path/ca-cert.pem","handlingStrategy":"validation","validationCode":"Certificate[] certs = authData.getTlsCertificates();\nif (certs == null || certs.length == 0) {\n    throw new AuthenticationException(\"Client did not present a TLS certificate\");\n}","typeGuard":"boolean hasTlsCerts(AuthenticationDataSource d) {\n    try { return d.getTlsCertificates() != null && d.getTlsCertificates().length > 0; }\n    catch (Exception e) { return false; }\n}","tryCatchPattern":"try {\n    role = provider.authenticate(authData);\n} catch (AuthenticationException e) {\n    log.warn(\"TLS auth failed: no client certificate; check client keystore\", e);\n}","preventionTips":["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"],"tags":["tls","authentication","certificate"],"backgroundTag":"missing-client-certificate","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}