This is an automated email from the ASF dual-hosted git repository.

lhotari pushed a commit to branch branch-4.0
in repository https://gitbox.apache.org/repos/asf/pulsar.git

commit 27e34f666d093327bf894668a286a0e037245cc0
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]>
    (cherry picked from commit bae91734a8584e7610c3945351d82ba52f0c9fae)
---
 .../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 1345f180b5c..c70ae2bb5ee 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
@@ -1794,6 +1794,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 {

Reply via email to