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

coheigea pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/main by this push:
     new 7516c494dde Honour deny roles with the user roles map in 
SimpleAuthorizingInterceptor (#3684)
7516c494dde is described below

commit 7516c494dde7bc5b0258de9fe22ede8160a8155a
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Thu Nov 5 12:12:31 2026 +0000

    Honour deny roles with the user roles map in SimpleAuthorizingInterceptor 
(#3684)
---
 .../security/AbstractAuthorizingInInterceptor.java |  2 +-
 .../security/SimpleAuthorizingInterceptor.java     | 23 +++++++++
 .../security/SimpleAuthorizingInterceptorTest.java | 60 ++++++++++++++++++++++
 3 files changed, 84 insertions(+), 1 deletion(-)

diff --git 
a/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java
 
b/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java
index b432258199c..ca6aafee858 100644
--- 
a/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java
+++ 
b/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java
@@ -33,8 +33,8 @@ import org.apache.cxf.security.SecurityContext;
 
 public abstract class AbstractAuthorizingInInterceptor extends 
AbstractPhaseInterceptor<Message> {
 
+    protected static final String ALL_ROLES = "*";
     private static final Logger LOG = 
LogUtils.getL7dLogger(AbstractAuthorizingInInterceptor.class);
-    private static final String ALL_ROLES = "*";
     private boolean allowAnonymousUsers = true;
 
     public AbstractAuthorizingInInterceptor() {
diff --git 
a/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java
 
b/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java
index b4b591e388e..b73c62d68c2 100644
--- 
a/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java
+++ 
b/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java
@@ -52,6 +52,11 @@ public class SimpleAuthorizingInterceptor extends 
AbstractAuthorizingInIntercept
 
     @Override
     protected boolean isUserInRole(SecurityContext sc, List<String> roles, 
boolean deny) {
+        if (deny) {
+            // The user is authorized only if they have none of the deny 
roles, whether from
+            // the security context or from the user roles map
+            return !hasAnyRole(sc, roles);
+        }
         if (!checkConfiguredRolesOnly && !super.isUserInRole(sc, roles, deny)) 
{
             return false;
         }
@@ -71,6 +76,24 @@ public class SimpleAuthorizingInterceptor extends 
AbstractAuthorizingInIntercept
         return !checkConfiguredRolesOnly;
     }
 
+    private boolean hasAnyRole(SecurityContext sc, List<String> roles) {
+        if (roles.size() == 1 && ALL_ROLES.equals(roles.get(0))) {
+            return true;
+        }
+        if (!checkConfiguredRolesOnly && super.isUserInRole(sc, roles, false)) 
{
+            return true;
+        }
+        List<String> userRoles = 
userRolesMap.get(sc.getUserPrincipal().getName());
+        if (userRoles != null) {
+            for (String role : roles) {
+                if (userRoles.contains(role)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     protected String createMethodSig(Method method) {
         StringBuilder b = new StringBuilder(method.getReturnType().getName());
         b.append(' ').append(method.getName()).append('(');
diff --git 
a/core/src/test/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptorTest.java
 
b/core/src/test/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptorTest.java
index a4252adeef3..544365cbafc 100644
--- 
a/core/src/test/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptorTest.java
+++ 
b/core/src/test/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptorTest.java
@@ -193,6 +193,66 @@ public class SimpleAuthorizingInterceptorTest {
         in.handleMessage(message);
     }
 
+    @Test(expected = AccessDeniedException.class)
+    public void testDenyWithDenyRolesFromUserRolesMap() {
+        SimpleAuthorizingInterceptor in = 
createSimpleAuthorizingInterceptorWithDenyRoles("role1");
+        in.setUserRolesMap(Collections.singletonMap("testUser", "role1"));
+        in.handleMessage(message);
+    }
+
+    @Test(expected = AccessDeniedException.class)
+    public void testDenyWithDenyRolesFromSecurityContextAndUserRolesMap() {
+        SimpleAuthorizingInterceptor in = 
createSimpleAuthorizingInterceptorWithDenyRoles("testRole");
+        in.setUserRolesMap(Collections.singletonMap("testUser", "role1"));
+        in.handleMessage(message);
+    }
+
+    @Test
+    public void testPermitWithDenyRolesAndUserRolesMap() {
+        SimpleAuthorizingInterceptor in = 
createSimpleAuthorizingInterceptorWithDenyRoles("frogs");
+        in.setUserRolesMap(Collections.singletonMap("testUser", "role1"));
+        in.handleMessage(message);
+    }
+
+    @Test
+    public void testPermitWithDenyRolesUserNotInUserRolesMap() {
+        SimpleAuthorizingInterceptor in = 
createSimpleAuthorizingInterceptorWithDenyRoles("frogs");
+        in.setUserRolesMap(Collections.singletonMap("otherUser", "role1"));
+        in.handleMessage(message);
+    }
+
+    @Test(expected = AccessDeniedException.class)
+    public void testDenyWithDenyRolesConfigurationOnly() {
+        SimpleAuthorizingInterceptor in = 
createSimpleAuthorizingInterceptorWithDenyRoles("role1");
+        in.setCheckConfiguredRolesOnly(true);
+        in.setUserRolesMap(Collections.singletonMap("testUser", "role1"));
+        in.handleMessage(message);
+    }
+
+    @Test
+    public void testPermitWithDenyRolesConfigurationOnly() {
+        // Only the configured roles are checked, so the security context's 
testRole is ignored
+        SimpleAuthorizingInterceptor in = 
createSimpleAuthorizingInterceptorWithDenyRoles("testRole");
+        in.setCheckConfiguredRolesOnly(true);
+        in.setUserRolesMap(Collections.singletonMap("testUser", "role1"));
+        in.handleMessage(message);
+    }
+
+    @Test
+    public void testPermitWithDenyRolesConfigurationOnlyNoUserRolesMap() {
+        SimpleAuthorizingInterceptor in = 
createSimpleAuthorizingInterceptorWithDenyRoles("frogs");
+        in.setCheckConfiguredRolesOnly(true);
+        in.handleMessage(message);
+    }
+
+    @Test(expected = AccessDeniedException.class)
+    public void testDenyAllConfigurationOnly() {
+        SimpleAuthorizingInterceptor in = 
createSimpleAuthorizingInterceptorWithDenyRoles("*");
+        in.setCheckConfiguredRolesOnly(true);
+        in.setUserRolesMap(Collections.singletonMap("testUser", "role1"));
+        in.handleMessage(message);
+    }
+
     @Test
     public void testMethodSignatureRoles() throws Exception {
         Method transfer = TestService.class.getMethod("transfer", 
String.class, long.class);

Reply via email to