This is an automated email from the ASF dual-hosted git repository.
lhotari pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar.git
The following commit(s) were added to refs/heads/master by this push:
new bae91734a85 [improve][broker] Add strictAuthMethod to require explicit
authentication method (#25185)
bae91734a85 is described below
commit bae91734a8584e7610c3945351d82ba52f0c9fae
Author: Omar Yasin <[email protected]>
AuthorDate: Fri Feb 6 04:46:26 2026 -0800
[improve][broker] Add strictAuthMethod to require explicit authentication
method (#25185)
Co-authored-by: Ómar K. Yasin <[email protected]>
---
.../apache/pulsar/broker/ServiceConfiguration.java | 8 ++++++
.../authentication/AuthenticationService.java | 8 ++++++
.../broker/auth/AuthenticationServiceTest.java | 30 ++++++++++++++++++++++
3 files changed, 46 insertions(+)
diff --git
a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/ServiceConfiguration.java
b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/ServiceConfiguration.java
index 8685b53c8c9..60af4d275be 100644
---
a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/ServiceConfiguration.java
+++
b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/ServiceConfiguration.java
@@ -1802,6 +1802,14 @@ public class ServiceConfiguration implements
PulsarConfiguration {
doc = "Enable authentication"
)
private boolean authenticationEnabled = false;
+
+ @FieldContext(
+ category = CATEGORY_AUTHENTICATION,
+ doc = "Strictly enforce authentication method. If specified, Pulsar
will only attempt to authenticate with "
+ + "the provided method. If no method is provided,
authentication fails."
+ )
+ private boolean strictAuthMethod = false;
+
@FieldContext(
category = CATEGORY_AUTHENTICATION,
doc = "Authentication provider name list, which is a list of class
names"
diff --git
a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationService.java
b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationService.java
index e2bf4dcc015..5b719bd6801 100644
---
a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationService.java
+++
b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationService.java
@@ -47,6 +47,7 @@ import org.slf4j.LoggerFactory;
public class AuthenticationService implements Closeable {
private static final Logger LOG =
LoggerFactory.getLogger(AuthenticationService.class);
private final String anonymousUserRole;
+ private final boolean strictAuthMethod;
private final Map<String, AuthenticationProvider> providers = new
LinkedHashMap<>();
@@ -57,6 +58,7 @@ public class AuthenticationService implements Closeable {
public AuthenticationService(ServiceConfiguration conf, OpenTelemetry
openTelemetry)
throws PulsarServerException {
anonymousUserRole = conf.getAnonymousUserRole();
+ strictAuthMethod = conf.isStrictAuthMethod();
if (conf.isAuthenticationEnabled()) {
try {
Map<String, List<AuthenticationProvider>> providerMap = new
LinkedHashMap<>();
@@ -138,6 +140,12 @@ public class AuthenticationService implements Closeable {
throw e;
}
} else {
+ if (strictAuthMethod) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("No authentication method provided while one was
is required");
+ }
+ throw new AuthenticationException("Authentication method
missing");
+ }
for (AuthenticationProvider provider : providers.values()) {
try {
return provider.authenticateHttpRequest(request, response);
diff --git
a/pulsar-broker/src/test/java/org/apache/pulsar/broker/auth/AuthenticationServiceTest.java
b/pulsar-broker/src/test/java/org/apache/pulsar/broker/auth/AuthenticationServiceTest.java
index c4e149eb1b8..3c90d573919 100644
---
a/pulsar-broker/src/test/java/org/apache/pulsar/broker/auth/AuthenticationServiceTest.java
+++
b/pulsar-broker/src/test/java/org/apache/pulsar/broker/auth/AuthenticationServiceTest.java
@@ -221,6 +221,36 @@ public class AuthenticationServiceTest {
(AuthenticationDataSource) null)).isEqualTo("role2");
}
+ @Test(timeOut = 10000)
+ public void testStrictAuthMethodEnforcement() throws Exception {
+ ServiceConfiguration config = new ServiceConfiguration();
+ Set<String> providersClassNames =
Sets.newHashSet(MockAuthenticationProvider.class.getName());
+ config.setAuthenticationProviders(providersClassNames);
+ config.setAuthenticationEnabled(true);
+ config.setStrictAuthMethod(true);
+ @Cleanup
+ AuthenticationService service = new AuthenticationService(config);
+
+ // Test: Request without auth method header should fail when
strictAuthMethod is enabled
+ HttpServletRequest requestWithoutAuthMethod =
mock(HttpServletRequest.class);
+
when(requestWithoutAuthMethod.getRemoteAddr()).thenReturn("192.168.1.1");
+ when(requestWithoutAuthMethod.getRemotePort()).thenReturn(8080);
+ // No X-Pulsar-Auth-Method-Name header set
+
+ assertThatThrownBy(() ->
service.authenticateHttpRequest(requestWithoutAuthMethod, (HttpServletResponse)
null))
+ .isInstanceOf(AuthenticationException.class)
+ .hasMessage("Authentication method missing");
+
+ // Test: Request with auth method header should still succeed
+ HttpServletRequest requestWithAuthMethod =
mock(HttpServletRequest.class);
+ when(requestWithAuthMethod.getRemoteAddr()).thenReturn("192.168.1.1");
+ when(requestWithAuthMethod.getRemotePort()).thenReturn(8080);
+
when(requestWithAuthMethod.getHeader("X-Pulsar-Auth-Method-Name")).thenReturn("auth");
+
+ boolean result =
service.authenticateHttpRequest(requestWithAuthMethod, (HttpServletResponse)
null);
+ assertTrue(result, "Authentication should succeed when auth method is
provided");
+ }
+
public static class MockHttpAuthenticationProvider implements
AuthenticationProvider {
@Override
public void close() throws IOException {