keycloak-memoizeit

[KEYCLOAK-8172] - Evaluation not considering scopes inherited

10/23/2018 6:37:15 PM

Details

diff --git a/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/DecisionPermissionCollector.java b/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/DecisionPermissionCollector.java
index 6265026..ecf2cd3 100644
--- a/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/DecisionPermissionCollector.java
+++ b/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/DecisionPermissionCollector.java
@@ -76,6 +76,11 @@ public class DecisionPermissionCollector extends AbstractDecisionCollector {
                         for (Scope scope : requestedScopes) {
                             if (policyScopes.contains(scope)) {
                                 grantedScopes.add(scope);
+                                // we need to grant any scope granted by a permission in case it is not explicitly
+                                // associated with the resource. For instance, resources inheriting scopes from parent resources.
+                                if (!resource.getScopes().contains(scope)) {
+                                    deniedScopes.remove(scope);
+                                }
                             }
                         }
                     } else if (isResourcePermission(policy)) {
diff --git a/services/src/main/java/org/keycloak/authorization/util/Permissions.java b/services/src/main/java/org/keycloak/authorization/util/Permissions.java
index ecb9def..5824b94 100644
--- a/services/src/main/java/org/keycloak/authorization/util/Permissions.java
+++ b/services/src/main/java/org/keycloak/authorization/util/Permissions.java
@@ -118,7 +118,7 @@ public final class Permissions {
         if (requestedScopes.isEmpty()) {
             scopes = populateTypedScopes(resource, authorization);
         } else {
-            scopes = requestedScopes.stream().filter(scope -> resource.getScopes().contains(scope)).collect(Collectors.toList());
+            scopes = populateTypedScopes(resource, requestedScopes.stream().filter(scope -> resource.getScopes().contains(scope)).collect(Collectors.toList()), authorization);
         }
 
         return new ResourcePermission(resource, scopes, resource.getResourceServer(), request.getClaims());
@@ -135,25 +135,32 @@ public final class Permissions {
     }
 
     private static List<Scope> populateTypedScopes(Resource resource, AuthorizationProvider authorization) {
-        List<Scope> scopes = new LinkedList<>(resource.getScopes());
+        return populateTypedScopes(resource, resource.getScopes(), authorization);
+    }
+
+    private static List<Scope> populateTypedScopes(Resource resource, List<Scope> defaultScopes, AuthorizationProvider authorization) {
         String type = resource.getType();
         ResourceServer resourceServer = resource.getResourceServer();
 
+        if (type == null || resource.getOwner().equals(resourceServer.getId())) {
+            return new ArrayList<>(defaultScopes);
+        }
+
+        List<Scope> scopes = new ArrayList<>(defaultScopes);
+
         // check if there is a typed resource whose scopes are inherited by the resource being requested. In this case, we assume that parent resource
         // is owned by the resource server itself
-        if (type != null && !resource.getOwner().equals(resourceServer.getId())) {
-            StoreFactory storeFactory = authorization.getStoreFactory();
-            ResourceStore resourceStore = storeFactory.getResourceStore();
-            resourceStore.findByType(type, resourceServer.getId(), resource1 -> {
-                if (resource1.getOwner().equals(resourceServer.getId())) {
-                    for (Scope typeScope : resource1.getScopes()) {
-                        if (!scopes.contains(typeScope)) {
-                            scopes.add(typeScope);
-                        }
+        StoreFactory storeFactory = authorization.getStoreFactory();
+        ResourceStore resourceStore = storeFactory.getResourceStore();
+        resourceStore.findByType(type, resourceServer.getId(), resource1 -> {
+            if (resource1.getOwner().equals(resourceServer.getId())) {
+                for (Scope typeScope : resource1.getScopes()) {
+                    if (!scopes.contains(typeScope)) {
+                        scopes.add(typeScope);
                     }
                 }
-            });
-        }
+            }
+        });
 
         return scopes;
     }