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

acosentino pushed a commit to branch keycloak-perms-new
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 53094c739005cc669ac37d0bdb24c4e79218bfd6
Author: Andrea Cosentino <[email protected]>
AuthorDate: Mon Sep 29 09:52:50 2025 +0200

    CAMEL-22459 - Camel-Keycloak: Support permission based policies
    
    Signed-off-by: Andrea Cosentino <[email protected]>
---
 .../camel-keycloak/src/main/docs/keycloak.adoc     | 181 +++++++++++++++++++++
 .../keycloak/security/KeycloakSecurityHelper.java  |  24 +++
 .../security/KeycloakSecurityProcessor.java        |  35 ++++
 .../security/KeycloakSecurityHelperTest.java       |  71 ++++++++
 .../keycloak/security/KeycloakSecurityIT.java      | 165 +++++++++++++++++++
 5 files changed, 476 insertions(+)

diff --git a/components/camel-keycloak/src/main/docs/keycloak.adoc 
b/components/camel-keycloak/src/main/docs/keycloak.adoc
index ce70d21939d..d0342c3a1f5 100644
--- a/components/camel-keycloak/src/main/docs/keycloak.adoc
+++ b/components/camel-keycloak/src/main/docs/keycloak.adoc
@@ -819,6 +819,16 @@ beans:
 
 The component includes integration tests that require a running Keycloak 
instance. These tests are disabled by default and only run when specific system 
properties are provided.
 
+The integration tests include comprehensive testing for:
+* Role-based authorization with different role requirements
+* Permission-based authorization using custom claims and scopes
+* Public key verification with JWKS endpoint integration
+* Combined roles and permissions validation
+* Token parsing with and without public key verification
+* Different authorization header formats (Bearer token, custom header)
+* Token expiration and validity checks
+* Error handling for invalid tokens and insufficient privileges
+
 === Starting Keycloak with Docker
 
 ==== 1. Start Keycloak Container
@@ -898,6 +908,7 @@ Create three test users with the following configuration:
 
 ==== 7. Execute Tests with Maven
 
+**Run All Integration Tests:**
 [source,bash]
 ----
 # Run integration tests with required properties
@@ -908,6 +919,31 @@ mvn test -Dtest=KeycloakSecurityIT \
   -Dkeycloak.client.secret=YOUR_CLIENT_SECRET
 ----
 
+**Run Specific Test Categories:**
+[source,bash]
+----
+# Test only role-based authorization
+mvn test 
-Dtest=KeycloakSecurityIT#testKeycloakSecurityPolicyWithValidAdminToken,testKeycloakSecurityPolicyWithValidUserToken,testKeycloakSecurityPolicyUserCannotAccessAdminRoute
 \
+  -Dkeycloak.server.url=http://localhost:8080 \
+  -Dkeycloak.realm=test-realm \
+  -Dkeycloak.client.id=test-client \
+  -Dkeycloak.client.secret=YOUR_CLIENT_SECRET
+
+# Test only permissions-based authorization
+mvn test 
-Dtest=KeycloakSecurityIT#testKeycloakSecurityPolicyWithPermissions,testKeycloakSecurityPolicyWithScopeBasedPermissions,testKeycloakSecurityPolicyWithCombinedRolesAndPermissions
 \
+  -Dkeycloak.server.url=http://localhost:8080 \
+  -Dkeycloak.realm=test-realm \
+  -Dkeycloak.client.id=test-client \
+  -Dkeycloak.client.secret=YOUR_CLIENT_SECRET
+
+# Test only public key verification
+mvn test 
-Dtest=KeycloakSecurityIT#testKeycloakSecurityPolicyWithPublicKeyVerification,testParseTokenDirectlyWithPublicKey
 \
+  -Dkeycloak.server.url=http://localhost:8080 \
+  -Dkeycloak.realm=test-realm \
+  -Dkeycloak.client.id=test-client \
+  -Dkeycloak.client.secret=YOUR_CLIENT_SECRET
+----
+
 Replace `YOUR_CLIENT_SECRET` with the actual client secret from step 4.
 
 ==== 8. Alternative: Set Environment Variables
@@ -939,3 +975,148 @@ mvn test -Dtest=KeycloakSecurityIT \
 **Connection refused**: Ensure Keycloak is running and accessible at the 
specified URL.
 
 **Token validation errors**: Verify the realm name and client configuration 
match exactly.
+
+=== Setting up Permissions in Keycloak
+
+For permissions-based authorization, you have several options to include 
permissions in tokens:
+
+==== Option 1: Custom Claims Mapper
+
+1. In your realm, go to **Client Scopes** → **roles** → **Mappers** → **Create 
mapper**
+2. Set the following:
+   - Mapper Type: `User Attribute`
+   - Name: `permissions-mapper`
+   - User Attribute: `permissions`
+   - Token Claim Name: `permissions`
+   - Claim JSON Type: `JSON`
+   - Add to ID token: `ON`
+   - Add to access token: `ON`
+
+3. Add the `permissions` attribute to users:
+   - Go to **Users** → Select user → **Attributes** tab
+   - Add attribute: `permissions` with value like `["read:documents", 
"write:documents"]`
+
+==== Option 2: Scope-based Permissions
+
+1. Configure client scopes:
+   - Go to **Client Scopes** → **Create client scope**
+   - Scope Name: `documents`
+   - Protocol: `openid-connect`
+
+2. Add scope to client:
+   - Go to **Clients** → Your client → **Client Scopes** tab
+   - Add the scope as **Default** or **Optional**
+
+3. In your application code, you can then use scopes as permissions:
+
+[source,java]
+----
+KeycloakSecurityPolicy policy = new KeycloakSecurityPolicy();
+policy.setRequiredPermissions(Arrays.asList("documents", "users", "admin"));
+policy.setAllPermissionsRequired(false); // ANY permission
+----
+
+==== Option 3: Authorization Services (Advanced)
+
+For complex permission models, enable Keycloak Authorization Services:
+
+1. Go to **Clients** → Your client → **Settings** → **Authorization Enabled**: 
`ON`
+2. Configure Resources, Scopes, and Policies in the **Authorization** tab
+3. Enable **Authorization** on the client
+
+Note: Full Authorization Services integration requires additional setup and is 
more complex than the simple approaches above.
+
+=== Combined Roles and Permissions Example
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+// Create a policy that requires BOTH roles AND permissions
+KeycloakSecurityPolicy strictPolicy = new KeycloakSecurityPolicy();
+strictPolicy.setServerUrl("{{keycloak.server-url}}");
+strictPolicy.setRealm("{{keycloak.realm}}");
+strictPolicy.setClientId("{{keycloak.client-id}}");
+strictPolicy.setClientSecret("{{keycloak.client-secret}}");
+
+// User must have admin role AND document permissions
+strictPolicy.setRequiredRoles(Arrays.asList("admin"));
+strictPolicy.setRequiredPermissions(Arrays.asList("read:documents", 
"write:documents"));
+strictPolicy.setAllRolesRequired(true);
+strictPolicy.setAllPermissionsRequired(false); // ANY permission
+
+// Create a policy that requires EITHER roles OR permissions
+KeycloakSecurityPolicy flexiblePolicy = new KeycloakSecurityPolicy();
+flexiblePolicy.setServerUrl("{{keycloak.server-url}}");
+flexiblePolicy.setRealm("{{keycloak.realm}}");
+flexiblePolicy.setClientId("{{keycloak.client-id}}");
+flexiblePolicy.setClientSecret("{{keycloak.client-secret}}");
+
+// Apply different policies to different routes
+from("direct:admin-documents")
+    .policy(strictPolicy)
+    .to("bean:documentService?method=adminOperations");
+
+from("direct:flexible-access")
+    .policy(flexiblePolicy)
+    .to("bean:documentService?method=flexibleOperations");
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+    from:
+      uri: direct:admin-documents
+      steps:
+        - policy:
+            ref: strictPolicy
+        - to:
+            uri: bean:documentService?method=adminOperations
+
+- route:
+    from:
+      uri: direct:flexible-access
+      steps:
+        - policy:
+            ref: flexiblePolicy
+        - to:
+            uri: bean:documentService?method=flexibleOperations
+
+# Bean definitions
+beans:
+  - name: strictPolicy
+    type: org.apache.camel.component.keycloak.security.KeycloakSecurityPolicy
+    properties:
+      serverUrl: "{{keycloak.server-url}}"
+      realm: "{{keycloak.realm}}"
+      clientId: "{{keycloak.client-id}}"
+      clientSecret: "{{keycloak.client-secret}}"
+      requiredRoles:
+        - "admin"
+      requiredPermissions:
+        - "read:documents"
+        - "write:documents"
+      allRolesRequired: true
+      allPermissionsRequired: false
+
+  - name: flexiblePolicy
+    type: org.apache.camel.component.keycloak.security.KeycloakSecurityPolicy
+    properties:
+      serverUrl: "{{keycloak.server-url}}"
+      realm: "{{keycloak.realm}}"
+      clientId: "{{keycloak.client-id}}"
+      clientSecret: "{{keycloak.client-secret}}"
+      requiredRoles:
+        - "admin"
+        - "manager"
+      requiredPermissions:
+        - "read:documents"
+        - "emergency:access"
+      allRolesRequired: false
+      allPermissionsRequired: false
+----
+====
diff --git 
a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/security/KeycloakSecurityHelper.java
 
b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/security/KeycloakSecurityHelper.java
index c845ada2eca..dfa8c081c90 100644
--- 
a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/security/KeycloakSecurityHelper.java
+++ 
b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/security/KeycloakSecurityHelper.java
@@ -17,6 +17,7 @@
 package org.apache.camel.component.keycloak.security;
 
 import java.security.PublicKey;
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
@@ -121,4 +122,27 @@ public final class KeycloakSecurityHelper {
 
         return true;
     }
+
+    public static Set<String> extractPermissions(AccessToken token) {
+        Set<String> permissions = new HashSet<>();
+
+        // Extract permissions from custom claims (primary approach for simple 
setups)
+        Object permissionsClaim = token.getOtherClaims().get("permissions");
+        if (permissionsClaim instanceof java.util.Collection<?>) {
+            @SuppressWarnings("unchecked")
+            java.util.Collection<String> permissionsCollection = 
(java.util.Collection<String>) permissionsClaim;
+            permissions.addAll(permissionsCollection);
+        }
+
+        // Also check for scope-based permissions
+        Object scopesClaim = token.getOtherClaims().get("scope");
+        if (scopesClaim instanceof String) {
+            String scopesString = (String) scopesClaim;
+            if (!scopesString.isEmpty()) {
+                
permissions.addAll(java.util.Arrays.asList(scopesString.split(" ")));
+            }
+        }
+
+        return permissions;
+    }
 }
diff --git 
a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/security/KeycloakSecurityProcessor.java
 
b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/security/KeycloakSecurityProcessor.java
index 2338c3b66df..a47868f00f7 100644
--- 
a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/security/KeycloakSecurityProcessor.java
+++ 
b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/security/KeycloakSecurityProcessor.java
@@ -55,6 +55,10 @@ public class KeycloakSecurityProcessor extends 
DelegateProcessor {
                 validateRoles(accessToken, exchange);
             }
 
+            if (!policy.getRequiredPermissions().isEmpty()) {
+                validatePermissions(accessToken, exchange);
+            }
+
         } catch (Exception e) {
             
exchange.getIn().setHeader(Exchange.AUTHENTICATION_FAILURE_POLICY_ID,
                     policy.getClass().getSimpleName());
@@ -116,4 +120,35 @@ public class KeycloakSecurityProcessor extends 
DelegateProcessor {
         }
     }
 
+    private void validatePermissions(String accessToken, Exchange exchange) 
throws Exception {
+        try {
+            AccessToken token;
+            if (ObjectHelper.isEmpty(policy.getPublicKey())) {
+                token = KeycloakSecurityHelper.parseAccessToken(accessToken);
+            } else {
+                token = KeycloakSecurityHelper.parseAccessToken(accessToken, 
policy.getPublicKey());
+            }
+            Set<String> userPermissions = 
KeycloakSecurityHelper.extractPermissions(token);
+
+            boolean hasRequiredPermissions = policy.isAllPermissionsRequired()
+                    ? 
userPermissions.containsAll(policy.getRequiredPermissions())
+                    : 
policy.getRequiredPermissions().stream().anyMatch(userPermissions::contains);
+
+            if (!hasRequiredPermissions) {
+                String message = String.format("User does not have required 
permissions. Required: %s, User has: %s",
+                        policy.getRequiredPermissions(), userPermissions);
+                LOG.debug(message);
+                throw new CamelAuthorizationException(message, exchange);
+            }
+
+            LOG.debug("Permission validation successful for user with 
permissions: {}", userPermissions);
+
+        } catch (Exception e) {
+            if (e instanceof CamelAuthorizationException) {
+                throw e;
+            }
+            throw new CamelAuthorizationException("Failed to validate 
permissions", exchange, e);
+        }
+    }
+
 }
diff --git 
a/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/security/KeycloakSecurityHelperTest.java
 
b/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/security/KeycloakSecurityHelperTest.java
index 718123c9dce..50372227fdc 100644
--- 
a/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/security/KeycloakSecurityHelperTest.java
+++ 
b/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/security/KeycloakSecurityHelperTest.java
@@ -160,4 +160,75 @@ public class KeycloakSecurityHelperTest {
         });
     }
 
+    @Test
+    void testExtractPermissions() {
+        AccessToken token = Mockito.mock(AccessToken.class);
+
+        // Mock authorization (simple approach without specific permission 
structure)
+        AccessToken.Authorization authorization = 
Mockito.mock(AccessToken.Authorization.class);
+        when(token.getAuthorization()).thenReturn(authorization);
+
+        // Test permissions extraction from custom claims
+        java.util.Map<String, Object> otherClaims = new java.util.HashMap<>();
+        otherClaims.put("permissions", 
java.util.Arrays.asList("read:documents", "write:documents", "admin:users"));
+
+        when(token.getOtherClaims()).thenReturn(otherClaims);
+
+        java.util.Set<String> permissions = 
KeycloakSecurityHelper.extractPermissions(token);
+
+        assertEquals(3, permissions.size());
+        assertTrue(permissions.contains("read:documents"));
+        assertTrue(permissions.contains("write:documents"));
+        assertTrue(permissions.contains("admin:users"));
+    }
+
+    @Test
+    void testExtractPermissionsFromCustomClaims() {
+        AccessToken token = Mockito.mock(AccessToken.class);
+
+        // Mock other claims with permissions
+        java.util.Map<String, Object> otherClaims = new java.util.HashMap<>();
+        otherClaims.put("permissions", java.util.Arrays.asList("read:files", 
"write:files", "delete:files"));
+
+        when(token.getOtherClaims()).thenReturn(otherClaims);
+        when(token.getAuthorization()).thenReturn(null);
+
+        java.util.Set<String> permissions = 
KeycloakSecurityHelper.extractPermissions(token);
+
+        assertEquals(3, permissions.size());
+        assertTrue(permissions.contains("read:files"));
+        assertTrue(permissions.contains("write:files"));
+        assertTrue(permissions.contains("delete:files"));
+    }
+
+    @Test
+    void testExtractPermissionsFromScopes() {
+        AccessToken token = Mockito.mock(AccessToken.class);
+
+        // Mock other claims with scope-based permissions
+        java.util.Map<String, Object> otherClaims = new java.util.HashMap<>();
+        otherClaims.put("scope", "read write admin");
+
+        when(token.getOtherClaims()).thenReturn(otherClaims);
+        when(token.getAuthorization()).thenReturn(null);
+
+        java.util.Set<String> permissions = 
KeycloakSecurityHelper.extractPermissions(token);
+
+        assertEquals(3, permissions.size());
+        assertTrue(permissions.contains("read"));
+        assertTrue(permissions.contains("write"));
+        assertTrue(permissions.contains("admin"));
+    }
+
+    @Test
+    void testExtractPermissionsEmpty() {
+        AccessToken token = Mockito.mock(AccessToken.class);
+        when(token.getAuthorization()).thenReturn(null);
+        when(token.getOtherClaims()).thenReturn(java.util.Map.of());
+
+        java.util.Set<String> permissions = 
KeycloakSecurityHelper.extractPermissions(token);
+
+        assertTrue(permissions.isEmpty());
+    }
+
 }
diff --git 
a/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/security/KeycloakSecurityIT.java
 
b/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/security/KeycloakSecurityIT.java
index 05169c82b4a..ea315ba2e0d 100644
--- 
a/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/security/KeycloakSecurityIT.java
+++ 
b/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/security/KeycloakSecurityIT.java
@@ -260,6 +260,111 @@ public class KeycloakSecurityIT extends CamelTestSupport {
         assertTrue(ex.getMessage().contains("signature") || 
ex.getMessage().contains("verification"));
     }
 
+    @Test
+    void testKeycloakSecurityPolicyWithPermissions() {
+        // Test permissions-based authorization
+        String adminToken = getAccessToken("myuser", "pippo123");
+        assertNotNull(adminToken);
+
+        // Test with permissions policy route - this will test the permissions 
extraction
+        try {
+            String result = 
template.requestBodyAndHeader("direct:permissions-protected", "test message",
+                    KeycloakSecurityConstants.ACCESS_TOKEN_HEADER, adminToken, 
String.class);
+            assertEquals("Permissions access granted", result);
+        } catch (CamelExecutionException ex) {
+            // This might fail if permissions are not configured in the token
+            // which is expected in a basic Keycloak setup
+            assertTrue(ex.getCause() instanceof CamelAuthorizationException);
+        }
+    }
+
+    @Test
+    void testKeycloakSecurityPolicyWithInsufficientPermissions() {
+        // Test that users without required permissions are rejected
+        String userToken = getAccessToken("test-user", "user123");
+        assertNotNull(userToken);
+
+        CamelExecutionException ex = 
assertThrows(CamelExecutionException.class, () -> {
+            template.sendBodyAndHeader("direct:permissions-protected", "test 
message",
+                    KeycloakSecurityConstants.ACCESS_TOKEN_HEADER, userToken);
+        });
+        assertTrue(ex.getCause() instanceof CamelAuthorizationException);
+    }
+
+    @Test
+    void testKeycloakSecurityPolicyWithScopeBasedPermissions() {
+        // Test scope-based permissions (using standard OAuth2 scopes)
+        String adminToken = getAccessToken("myuser", "pippo123");
+        assertNotNull(adminToken);
+
+        // Test with scope-based permissions policy route
+        try {
+            String result = 
template.requestBodyAndHeader("direct:scope-permissions-protected", "test 
message",
+                    KeycloakSecurityConstants.ACCESS_TOKEN_HEADER, adminToken, 
String.class);
+            assertEquals("Scope permissions access granted", result);
+        } catch (CamelExecutionException ex) {
+            // This might fail if the token doesn't contain the expected scopes
+            // which is expected in basic Keycloak setup without custom scope 
configuration
+            assertTrue(ex.getCause() instanceof CamelAuthorizationException);
+        }
+    }
+
+    @Test
+    void testKeycloakSecurityPolicyWithCombinedRolesAndPermissions() {
+        // Test combined roles and permissions validation
+        String adminToken = getAccessToken("myuser", "pippo123");
+        assertNotNull(adminToken);
+
+        // Test with combined policy route (requires BOTH admin role AND 
permissions)
+        try {
+            String result = 
template.requestBodyAndHeader("direct:combined-protected", "test message",
+                    KeycloakSecurityConstants.ACCESS_TOKEN_HEADER, adminToken, 
String.class);
+            assertEquals("Combined access granted", result);
+        } catch (CamelExecutionException ex) {
+            // This will fail if either role or permissions are missing
+            assertTrue(ex.getCause() instanceof CamelAuthorizationException);
+        }
+    }
+
+    @Test
+    void testKeycloakSecurityPolicyWithFlexiblePermissions() {
+        // Test flexible permissions (ANY permission required)
+        String userToken = getAccessToken("test-user", "user123");
+        assertNotNull(userToken);
+
+        // Test with flexible permissions policy (requires ANY of the 
specified permissions)
+        try {
+            String result = 
template.requestBodyAndHeader("direct:flexible-permissions-protected", "test 
message",
+                    KeycloakSecurityConstants.ACCESS_TOKEN_HEADER, userToken, 
String.class);
+            assertEquals("Flexible permissions access granted", result);
+        } catch (CamelExecutionException ex) {
+            // This will fail if the user doesn't have any of the required 
permissions
+            assertTrue(ex.getCause() instanceof CamelAuthorizationException);
+        }
+    }
+
+    @Test
+    void testPermissionsExtractionFromToken() {
+        // Test direct permissions extraction from token for debugging
+        String adminToken = getAccessToken("myuser", "pippo123");
+        assertNotNull(adminToken);
+
+        try {
+            // Parse token and extract permissions directly
+            org.keycloak.representations.AccessToken token = 
KeycloakSecurityHelper.parseAccessToken(adminToken);
+            java.util.Set<String> permissions = 
KeycloakSecurityHelper.extractPermissions(token);
+
+            // Log the permissions found for debugging
+            System.out.println("Permissions found in token: " + permissions);
+
+            // Permissions might be empty in a basic setup, which is expected
+            assertNotNull(permissions);
+
+        } catch (Exception e) {
+            fail("Should be able to parse token and extract permissions: " + 
e.getMessage());
+        }
+    }
+
     /**
      * Helper method to get public key from Keycloak JWKS endpoint for token 
verification. Tries to find the key with
      * "sig" usage or the first RSA key available.
@@ -451,6 +556,66 @@ public class KeycloakSecurityIT extends CamelTestSupport {
                         .policy(wrongPublicKeyPolicy)
                         .transform().constant("Should not reach here")
                         .to("mock:wrong-key-result");
+
+                // Permissions-based policy
+                KeycloakSecurityPolicy permissionsPolicy = new 
KeycloakSecurityPolicy();
+                permissionsPolicy.setServerUrl(keycloakUrl);
+                permissionsPolicy.setRealm(realm);
+                permissionsPolicy.setClientId(clientId);
+                permissionsPolicy.setClientSecret(clientSecret);
+                
permissionsPolicy.setRequiredPermissions(java.util.Arrays.asList("read:documents",
 "write:documents"));
+                permissionsPolicy.setAllPermissionsRequired(false); // ANY 
permission
+
+                from("direct:permissions-protected")
+                        .policy(permissionsPolicy)
+                        .transform().constant("Permissions access granted")
+                        .to("mock:permissions-result");
+
+                // Scope-based permissions policy (using OAuth2 scopes)
+                KeycloakSecurityPolicy scopePermissionsPolicy = new 
KeycloakSecurityPolicy();
+                scopePermissionsPolicy.setServerUrl(keycloakUrl);
+                scopePermissionsPolicy.setRealm(realm);
+                scopePermissionsPolicy.setClientId(clientId);
+                scopePermissionsPolicy.setClientSecret(clientSecret);
+                
scopePermissionsPolicy.setRequiredPermissions(java.util.Arrays.asList("profile",
 "email", "openid"));
+                scopePermissionsPolicy.setAllPermissionsRequired(false); // 
ANY scope
+
+                from("direct:scope-permissions-protected")
+                        .policy(scopePermissionsPolicy)
+                        .transform().constant("Scope permissions access 
granted")
+                        .to("mock:scope-permissions-result");
+
+                // Combined roles and permissions policy
+                KeycloakSecurityPolicy combinedPolicy = new 
KeycloakSecurityPolicy();
+                combinedPolicy.setServerUrl(keycloakUrl);
+                combinedPolicy.setRealm(realm);
+                combinedPolicy.setClientId(clientId);
+                combinedPolicy.setClientSecret(clientSecret);
+                
combinedPolicy.setRequiredRoles(java.util.Arrays.asList("admin-role"));
+                
combinedPolicy.setRequiredPermissions(java.util.Arrays.asList("read:documents", 
"admin:system"));
+                combinedPolicy.setAllRolesRequired(true); // Must have ALL 
roles
+                combinedPolicy.setAllPermissionsRequired(true); // Any 
permission
+
+                from("direct:combined-protected")
+                        .policy(combinedPolicy)
+                        .transform().constant("Combined access granted")
+                        .to("mock:combined-result");
+
+                // Flexible permissions policy (ANY permission)
+                KeycloakSecurityPolicy flexiblePermissionsPolicy = new 
KeycloakSecurityPolicy();
+                flexiblePermissionsPolicy.setServerUrl(keycloakUrl);
+                flexiblePermissionsPolicy.setRealm(realm);
+                flexiblePermissionsPolicy.setClientId(clientId);
+                flexiblePermissionsPolicy.setClientSecret(clientSecret);
+                flexiblePermissionsPolicy
+                        
.setRequiredPermissions(java.util.Arrays.asList("profile", "email", 
"user:basic", "read:public"));
+                flexiblePermissionsPolicy.setAllPermissionsRequired(false); // 
ANY permission
+
+                from("direct:flexible-permissions-protected")
+                        .policy(flexiblePermissionsPolicy)
+                        .transform().constant("Flexible permissions access 
granted")
+                        .to("mock:flexible-permissions-result");
+
             }
         };
     }

Reply via email to