You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pulsar.apache.org by "urdogan0000 (via GitHub)" <gi...@apache.org> on 2024/09/09 08:41:08 UTC
[D] Custome authentication Plugin Not Working [pulsar]
GitHub user urdogan0000 created a discussion: Custome authentication Plugin Not Working
I create my customAuthenticationPlugin for broker and client.My pulsar container run and up with this custom AuthenticationPlugin when ı try to connect with client it gives an error like,
//
Caused by: org.apache.pulsar.client.api.PulsarClientException$UnsupportedAuthenticationException: org.apache.pulsar.client.api.PulsarClientException$UnsupportedAuthenticationException: java.lang.NullPointerException: Cannot invoke "com.google.gson.JsonObject.has(String)" because "params" is null
at org.apache.pulsar.client.api.AuthenticationFactory.create(AuthenticationFactory.java:92) ~[org.apache.pulsar-pulsar-client-api-3.2.3.jar:3.2.3]
((
My custom plugin
public class BasicAuthProvider implements AuthenticationProvider {
static final String HTTP_HEADER_NAME = "Authorization";
static final String HTTP_HEADER_VALUE_PREFIX = "Basic";
private static final Logger log = LoggerFactory.getLogger(BasicAuthProvider.class);
private String apiEndpoint;
private OkHttpClient httpClient;
@Override
public void initialize(ServiceConfiguration config) throws PulsarServerException {
httpClient = new OkHttpClient();
// Initialize the REST client and read configuration
this.apiEndpoint = (String) config.getProperties().getOrDefault("authRestApiEndpoint", "http://localhost:8081/pulsar/send");
log.info("BasicAuthProvider initialized with endpoint: {}", apiEndpoint);
}
@Override
public String getAuthMethodName() {
return "customAuth";
}
@Override
public String authenticate(AuthenticationDataSource authData) throws AuthenticationException {
String credentials = getUserCredentials(authData);
// Log the incoming request and Authorization header
log.info("Authentication request to endpoint: {}", apiEndpoint);
log.info("Authorization header: {}", credentials);
// Create a GET request with Basic Authentication header using OkHttp
Request request = new Request.Builder()
.url(apiEndpoint)
.addHeader(HTTP_HEADER_NAME, credentials) // The credentials already contain "Basic <encoded>"
.build();
try (Response response = httpClient.newCall(request).execute()) {
if (response.isSuccessful()) {
assert response.body() != null;
String responseBody = response.body().string();
log.info("Authentication successful: {}", responseBody);
// You can further parse the response if needed to determine success
return responseBody; // Return the result as per your application's requirements
} else {
if (log.isWarnEnabled()) {
log.warn("Authentication failed. HTTP status code: {}, Response: {}",
response.code(),
response.body().string());
}
throw new AuthenticationException("Authentication failed. Invalid username or password.");
}
} catch (IOException e) {
log.error("Error during authentication: ", e);
throw new AuthenticationException("Authentication process encountered an error.");
}
}
public static String getUserCredentials(AuthenticationDataSource authData) throws AuthenticationException {
if (authData.hasDataFromCommand()) {
String commandData = authData.getCommandData();
log.info("Extracted command data: {}", commandData);
return validateUserCredentials(commandData);
} else if (authData.hasDataFromHttp()) {
String httpHeaderValue = authData.getHttpHeader(HTTP_HEADER_NAME);
log.info("Extracted HTTP header value: {}", httpHeaderValue);
if (httpHeaderValue == null) {
log.error("Extracted HTTP header value: {}", httpHeaderValue);
throw new AuthenticationException("Invalid HTTP Authorization header");
}
return validateUserCredentials(httpHeaderValue);
} else {
log.error("Extracted HTTP header value: {}");
throw new AuthenticationException("No user credentials passed");
}
}
private static String validateUserCredentials(final String userCredentials) throws AuthenticationException {
if (StringUtils.isNotBlank(userCredentials) ) {
return userCredentials;
} else {
log.error("Extracted HTTP header value: {}",HTTP_HEADER_VALUE_PREFIX);
log.error(userCredentials);
log.error("test");
throw new AuthenticationException("Invalid or blank user credentials found");
}
}
@Override
public void close() {
// Cleanup resources if needed
if (httpClient != null) {
httpClient.connectionPool().evictAll(); // Close all connections in the pool
}
}
}
public class AuthenticationBasicAuth implements Authentication, EncodedAuthenticationParameterSupport {
private static final Logger log = LoggerFactory.getLogger(AuthenticationBasicAuth.class);
private String userId;
private String password;
// Default constructor
public AuthenticationBasicAuth() {
// No initialization here, config will be called
}
public AuthenticationBasicAuth(String userId, String password) {
this.userId = userId;
this.password = password;
}
@Override
public void close() throws IOException {
// No-op
}
@Override
public String getAuthMethodName() {
return "customAuth";
}
@Override
public CustomDataBasic getAuthData() throws PulsarClientException {
if (userId == null || password == null) {
throw new PulsarClientException.InvalidConfigurationException("userId or password is not set");
}
return new CustomDataBasic(userId, password);
}
@Override
public void configure(Map<String, String> authParams) {
// Configure using a Map
configure(new Gson().toJson(authParams)); // Convert map to JSON string and delegate to the other configure method
}
@Override
public void configure(String encodedAuthParamString) {
// Configure using an encoded JSON string
try {
JsonObject params = new Gson().fromJson(encodedAuthParamString, JsonObject.class);
this.userId = params.has("userId") ? params.get("userId").getAsString() : null;
this.password = params.has("password") ? params.get("password").getAsString() : null;
// Log the received parameters for debugging
log.debug("Configured with userId: {}, password: {}", userId, password != null ? "[PROTECTED]" : "null");
// Validate the parameters
if (userId == null || password == null) {
throw new IllegalArgumentException("userId and password must be provided in the authentication parameters.");
}
} catch (com.google.gson.JsonSyntaxException e) {
log.error("Invalid JSON format for authentication parameters: {}", encodedAuthParamString, e);
throw new IllegalArgumentException("Invalid JSON format for authentication parameters.", e);
}
}
@Override
public void start() throws PulsarClientException {
// No-op
}
}
public class CustomDataBasic implements AuthenticationDataProvider {
private static final String HTTP_HEADER_NAME = "Authorization";
private final String commandAuthToken;
private final Map<String, String> headers;
public CustomDataBasic(String userId, String password) {
// Base64 encode the credentials
String credentials = userId + ":" + password;
// String base64Credentials = Base64.getEncoder().encodeToString(credentials.getBytes());
this.commandAuthToken = "Basic " + userId+":"+password;
// Initialize headers
this.headers = Collections.unmodifiableMap(new HashMap<String, String>(){
{
this.put(HTTP_HEADER_NAME, commandAuthToken);
this.put(PULSAR_AUTH_METHOD_NAME, "customAuth");
}
});
}
@Override
public boolean hasDataForHttp() {
return true;
}
@Override
public Set<Map.Entry<String, String>> getHttpHeaders() {
return this.headers.entrySet();
}
@Override
public boolean hasDataFromCommand() {
return true;
}
@Override
public String getCommandData() {
return this.commandAuthToken;
}
}
GitHub link: https://github.com/apache/pulsar/discussions/23270
----
This is an automatically sent email for commits@pulsar.apache.org.
To unsubscribe, please send an email to: commits-unsubscribe@pulsar.apache.org