{"record":{"id":"5da3caddb0ce4372","repo":"apache/pulsar","slug":"no-client","errorCode":"NO_CLIENT","errorMessage":"Authentication data source does not have a client address","messagePattern":"Authentication data source does not have a client address","errorType":"exception","errorClass":"AuthenticationException","httpStatus":null,"severity":"error","filePath":"pulsar-broker-auth-athenz/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationProviderAthenz.java","lineNumber":116,"sourceCode":"    }\n\n    @Override\n    public void incrementFailureMetric(Enum<?> errorCode) {\n        authenticationMetrics.recordFailure(errorCode);\n    }\n\n    @Override\n    public String authenticate(AuthenticationDataSource authData) throws AuthenticationException {\n        SocketAddress clientAddress;\n        String roleToken;\n        ErrorCode errorCode = ErrorCode.UNKNOWN;\n        try {\n\n            if (authData.hasDataFromPeer()) {\n                clientAddress = authData.getPeerAddress();\n            } else {\n                errorCode = ErrorCode.NO_CLIENT;\n                throw new AuthenticationException(\"Authentication data source does not have a client address\");\n            }\n\n            if (authData.hasDataFromCommand()) {\n                roleToken = authData.getCommandData();\n            } else if (authData.hasDataFromHttp()) {\n                roleToken = authData.getHttpHeader(AuthZpeClient.ZPE_TOKEN_HDR);\n            } else {\n                errorCode = ErrorCode.NO_TOKEN;\n                throw new AuthenticationException(\"Authentication data source does not have a role token\");\n            }\n\n            if (roleToken == null) {\n                errorCode = ErrorCode.NO_TOKEN;\n                throw new AuthenticationException(\"Athenz token is null, can't authenticate\");\n            }\n            if (roleToken.isEmpty()) {\n                errorCode = ErrorCode.NO_TOKEN;\n                throw new AuthenticationException(\"Athenz RoleToken is empty, Server is Using Athenz Authentication\");","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker-auth-athenz/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationProviderAthenz.java#L98-L134","documentation":"authenticate() needs the client's peer address to validate Athenz role tokens (tokens are IP-bound). When the AuthenticationDataSource carries no peer data (hasDataFromPeer() false), the provider records errorCode NO_CLIENT and throws this AuthenticationException — it cannot verify the token against a client IP.","triggerScenarios":"Calling AuthenticationProviderAthenz.authenticate(authData) with a data source constructed without peer address (e.g. command-data-only source, test stub, or transport path that doesn't populate peer address).","commonSituations":"Custom protocol handler or proxy feeding authentication data without the remote address; unit tests passing new AuthenticationDataSource(){} with only command data; internal broker-to-broker calls lacking peer info.","solutions":["Populate the peer address in the AuthenticationDataSource at the transport layer before calling authenticate().","If behind a proxy, forward the real client address (e.g. PROXY protocol / X-Forwarded-For) and ensure Pulsar is configured to trust it.","In tests, use an AuthenticationDataSource implementation that returns a peer address from hasDataFromPeer()/getPeerAddress()."],"exampleFix":"// before\nAuthenticationData authData = new AuthenticationDataCommand(authToken);\nprovider.authenticate(authData);\n// after\nAuthenticationData authData = new AuthenticationDataSource() {\n    public boolean hasDataFromPeer() { return true; }\n    public String getPeerAddress() { return clientIp; }\n    public boolean hasDataFromCommand() { return true; }\n    public String getCommandData() { return authToken; }\n};\nprovider.authenticate(authData);","handlingStrategy":"validation","validationCode":"// before calling authenticate\nif (!authData.hasDataFromPeer() || authData.getPeerAddress() == null) {\n    throw new IllegalArgumentException(\"AuthenticationDataSource must carry peer address for athenz\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    principal = provider.authenticate(authData);\n} catch (AuthenticationException e) {\n    // NO_CLIENT: attach peer address at transport layer and retry\n    throw new AuthenticationException(\"peer address missing: \" + e.getMessage(), e);\n}","preventionTips":["Always populate peer address when constructing AuthenticationDataSource in custom handlers.","Configure proxies to forward the real client IP.","Use data sources with peer info in tests."],"tags":["athenz","authentication","peer-address","validation"],"backgroundTag":"missing-client-address","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}