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 6e0423f835..302c2553cc 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
{ 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
{ 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
{ } 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 d4c64aa4cf..7ddadae0db 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 aeab19c9b9..b628949900 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 6707f9ebb3..1f05e2585e 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); }