keycloak-uncached

[KEYCLOAK-8823] - PathMatcher doesn't prefer overloaded

11/15/2018 8:10:30 AM

Details

diff --git a/common/src/main/java/org/keycloak/common/util/PathMatcher.java b/common/src/main/java/org/keycloak/common/util/PathMatcher.java
index 6e0423f..302c255 100644
--- a/common/src/main/java/org/keycloak/common/util/PathMatcher.java
+++ b/common/src/main/java/org/keycloak/common/util/PathMatcher.java
@@ -28,6 +28,7 @@ public abstract class PathMatcher<P> {
 
     public P matches(final String targetUri) {
         int patternCount = 0;
+        int bracketsPatternCount = 0;
         P matchingPath = null;
         P matchingAnyPath = null;
         P matchingAnySuffixPath = null;
@@ -50,8 +51,9 @@ public abstract class PathMatcher<P> {
 
                 if (templateUri != null) {
                     int length = expectedUri.split("\\/").length;
+                    int bracketsLength = expectedUri.split("\\{").length;
 
-                    if (exactMatch(expectedUri, targetUri, templateUri) && (patternCount == 0 || length > patternCount)) {
+                    if (exactMatch(expectedUri, targetUri, templateUri) && (patternCount == 0 || length > patternCount || bracketsLength < bracketsPatternCount)) {
                         matchingUri = templateUri;
                         P resolved = resolvePathConfig(entry, targetUri);
 
@@ -60,6 +62,7 @@ public abstract class PathMatcher<P> {
                         }
 
                         patternCount = length;
+                        bracketsPatternCount = bracketsLength;
                     }
                 }
             }
diff --git a/testsuite/integration-arquillian/test-apps/servlet-policy-enforcer/servlet-policy-enforcer-authz-realm.json b/testsuite/integration-arquillian/test-apps/servlet-policy-enforcer/servlet-policy-enforcer-authz-realm.json
index d4c64aa..7ddadae 100644
--- a/testsuite/integration-arquillian/test-apps/servlet-policy-enforcer/servlet-policy-enforcer-authz-realm.json
+++ b/testsuite/integration-arquillian/test-apps/servlet-policy-enforcer/servlet-policy-enforcer-authz-realm.json
@@ -124,6 +124,14 @@
                     {
                         "name": "Pattern 16",
                         "uris": ["/keycloak-7269/sub-resource1", "/keycloak-7269/sub-resource2/*", "/keycloak-7269/sub-resource1/{test-pattern}/specialSuffix"]
+                    },
+                    {
+                        "name": "Pattern 17",
+                        "uris": ["/keycloak-8823/resource/{version}/subresource/{id}/{other}"]
+                    },
+                    {
+                        "name": "Pattern 17 Entities",
+                        "uris": ["/keycloak-8823/resource/{version}/subresource/{id}/entities"]
                     }
                 ],
                 "policies": [
@@ -316,6 +324,26 @@
                             "resources": "[\"Pattern 16\"]",
                             "applyPolicies": "[\"Default Policy\"]"
                         }
+                    },
+                    {
+                        "name": "Pattern 17 Permission",
+                        "type": "resource",
+                        "logic": "POSITIVE",
+                        "decisionStrategy": "UNANIMOUS",
+                        "config": {
+                            "resources": "[\"Pattern 17\"]",
+                            "applyPolicies": "[\"Default Policy\"]"
+                        }
+                    },
+                    {
+                        "name": "Pattern 17 Entities Permission",
+                        "type": "resource",
+                        "logic": "POSITIVE",
+                        "decisionStrategy": "UNANIMOUS",
+                        "config": {
+                            "resources": "[\"Pattern 17 Entities\"]",
+                            "applyPolicies": "[\"Default Policy\"]"
+                        }
                     }
                 ],
                 "scopes": []
diff --git a/testsuite/integration-arquillian/test-apps/servlet-policy-enforcer/src/main/webapp/WEB-INF/keycloak.json b/testsuite/integration-arquillian/test-apps/servlet-policy-enforcer/src/main/webapp/WEB-INF/keycloak.json
index aeab19c..b628949 100644
--- a/testsuite/integration-arquillian/test-apps/servlet-policy-enforcer/src/main/webapp/WEB-INF/keycloak.json
+++ b/testsuite/integration-arquillian/test-apps/servlet-policy-enforcer/src/main/webapp/WEB-INF/keycloak.json
@@ -85,6 +85,14 @@
             {
                 "name": "Pattern 16",
                 "path": "/keycloak-7269/sub-resource1/{test-pattern}/specialSuffix"
+            },
+            {
+                "name": "Pattern 17",
+                "path": "/keycloak-8823/resource/{version}/subresource/{id}/{other}"
+            },
+            {
+                "name": "Pattern 17 Entities",
+                "path": "/keycloak-8823/resource/{version}/subresource/{id}/entities"
             }
         ]
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/ServletPolicyEnforcerTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/ServletPolicyEnforcerTest.java
index 6707f9e..1f05e25 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/ServletPolicyEnforcerTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/ServletPolicyEnforcerTest.java
@@ -487,6 +487,41 @@ public class ServletPolicyEnforcerTest extends AbstractExampleAdapterTest {
         });
     }
 
+    @Test
+    public void testOverloadedTemplateUri() {
+        performTests(() -> {
+            login("alice", "alice");
+            navigateTo("/keycloak-8823/resource/v1/subresource/123/entities");
+            assertFalse(wasDenied());
+            navigateTo("/keycloak-8823/resource/v1/subresource/123/someother");
+            assertFalse(wasDenied());
+            
+            updatePermissionPolicies("Pattern 17 Entities Permission", "Deny Policy");
+            
+            login("alice", "alice");
+            navigateTo("/keycloak-8823/resource/v1/subresource/123/entities");
+            assertTrue(wasDenied());
+            navigateTo("/keycloak-8823/resource/v1/subresource/123/someother");
+            assertFalse(wasDenied());
+            
+            updatePermissionPolicies("Pattern 17 Entities Permission", "Default Policy");
+            updatePermissionPolicies("Pattern 17 Permission", "Deny Policy");
+            login("alice", "alice");
+            navigateTo("/keycloak-8823/resource/v1/subresource/123/entities");
+            assertFalse(wasDenied());
+            navigateTo("/keycloak-8823/resource/v1/subresource/123/someother");
+            assertTrue(wasDenied());
+            
+            updatePermissionPolicies("Pattern 17 Entities Permission", "Default Policy");
+            updatePermissionPolicies("Pattern 17 Permission", "Default Policy");
+            login("alice", "alice");
+            navigateTo("/keycloak-8823/resource/v1/subresource/123/entities");
+            assertFalse(wasDenied());
+            navigateTo("/keycloak-8823/resource/v1/subresource/123/someother");
+            assertFalse(wasDenied());
+        });
+    }
+
     private void navigateTo(String path) {
         this.driver.navigate().to(getResourceServerUrl() + path);
     }