diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java index 84a63d285e5..863af3bddf4 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java @@ -17,6 +17,7 @@ package org.keycloak.models.jpa; +import org.keycloak.authorization.AdminPermissionsSchema; import org.keycloak.authorization.jpa.entities.ResourceEntity; import org.keycloak.common.util.Time; import org.keycloak.component.ComponentModel; @@ -1078,7 +1079,14 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore { List subs = new ArrayList<>(); Expression groupId = from.get("groupId"); - subs.add(cb.like(from1.get("name"), cb.concat("group.resource.", groupId))); + + RealmModel realm = session.getContext().getRealm(); + + if (AdminPermissionsSchema.SCHEMA.isAdminPermissionsEnabled(realm)) { + subs.add(cb.like(from1.get("name"), groupId)); + } else { + subs.add(cb.like(from1.get("name"), cb.concat("group.resource.", groupId))); + } subquery1.where(subs.toArray(Predicate[]::new)); diff --git a/rest/admin-ui-ext/src/main/java/org/keycloak/admin/ui/rest/AvailableRoleMappingResource.java b/rest/admin-ui-ext/src/main/java/org/keycloak/admin/ui/rest/AvailableRoleMappingResource.java index 81264d67d0f..7512aa8abb1 100644 --- a/rest/admin-ui-ext/src/main/java/org/keycloak/admin/ui/rest/AvailableRoleMappingResource.java +++ b/rest/admin-ui-ext/src/main/java/org/keycloak/admin/ui/rest/AvailableRoleMappingResource.java @@ -225,8 +225,8 @@ public class AvailableRoleMappingResource extends RoleMappingResource { } private Set getRoleIdsWithPermissions(String roleResourceScope, String clientResourceScope) { - Set roleIds = this.auth.roles().getRolesWithPermission(roleResourceScope); - Set clientIds = this.auth.clients().getClientsWithPermission(clientResourceScope); + Set roleIds = this.auth.roles().getRoleIdsWithViewPermission(roleResourceScope); + Set clientIds = this.auth.clients().getClientIdsWithViewPermission(clientResourceScope); clientIds.stream().flatMap(cid -> realm.getClientById(cid).getRolesStream()).forEach(role -> roleIds.add(role.getId())); return roleIds; } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionEvaluator.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionEvaluator.java index c5fbe70f962..3770d82705a 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionEvaluator.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionEvaluator.java @@ -191,5 +191,11 @@ public interface ClientPermissionEvaluator { Map getAccess(ClientModel client); - Set getClientsWithPermission(String scope); + /** + * Returns the IDs of the clients that the current user can view.. + * + * @return Stream of IDs of clients with view permission. + */ + + Set getClientIdsWithViewPermission(String scope); } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissions.java index 603c5cbadaa..fdeea5d1651 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissions.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissions.java @@ -26,6 +26,7 @@ import org.keycloak.authorization.model.ResourceServer; import org.keycloak.authorization.model.Scope; import org.keycloak.authorization.permission.ResourcePermission; import org.keycloak.authorization.policy.evaluation.EvaluationContext; +import org.keycloak.authorization.store.PolicyStore; import org.keycloak.authorization.store.ResourceStore; import org.keycloak.models.AdminRoles; import org.keycloak.models.ClientModel; @@ -63,6 +64,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionM protected final AuthorizationProvider authz; protected final MgmtPermissions root; protected final ResourceStore resourceStore; + protected final PolicyStore policyStore; private static final String RESOURCE_NAME_PREFIX = "client.resource."; @@ -73,8 +75,10 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionM this.root = root; if (authz != null) { resourceStore = authz.getStoreFactory().getResourceStore(); + policyStore = authz.getStoreFactory().getPolicyStore(); } else { resourceStore = null; + policyStore = null; } } @@ -664,7 +668,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionM } @Override - public Set getClientsWithPermission(String scope) { + public Set getClientIdsWithViewPermission(String scope) { if (!root.isAdminSameRealm()) { return Collections.emptySet(); } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionsV2.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionsV2.java index a751293df73..9341bffba84 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionsV2.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionsV2.java @@ -42,6 +42,8 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Function; +import java.util.stream.Stream; import static org.keycloak.services.resources.admin.permissions.AdminPermissionManagement.TOKEN_EXCHANGE; @@ -122,7 +124,7 @@ public class ClientPermissionsV2 extends ClientPermissions { } @Override - public Set getClientsWithPermission(String scope) { + public Set getClientIdsWithViewPermission(String scope) { if (!root.isAdminSameRealm()) { return Collections.emptySet(); } @@ -135,11 +137,13 @@ public class ClientPermissionsV2 extends ClientPermissions { Set granted = new HashSet<>(); - resourceStore.findByType(server, AdminPermissionsSchema.CLIENTS_RESOURCE_TYPE, resource -> { - if (hasGrantedPermission(resource, scope)) { - granted.add(resource.getName()); - } - }); + policyStore.findByResourceType(server, AdminPermissionsSchema.CLIENTS_RESOURCE_TYPE).stream() + .flatMap((Function>) policy -> policy.getResources().stream()) + .forEach(resource -> { + if (hasGrantedPermission(resource, scope)) { + granted.add(resource.getName()); + } + }); return granted; } @@ -224,9 +228,11 @@ public class ClientPermissionsV2 extends ClientPermissions { Collection permissions = root.evaluatePermission(new ResourcePermission(resource, resource.getScopes(), server), server); List expectedScopes = Arrays.asList(scope); for (Permission permission : permissions) { - for (String s : permission.getScopes()) { - if (expectedScopes.contains(s)) { - return true; + if (permission.getResourceId().equals(resource.getId())) { + for (String s : permission.getScopes()) { + if (expectedScopes.contains(s)) { + return true; + } } } } @@ -259,25 +265,15 @@ public class ClientPermissionsV2 extends ClientPermissions { return false; } - private EvaluationContext getEvaluationContext(ClientModel authorizedClient, AccessToken token) { - ClientModelIdentity identity = new ClientModelIdentity(session, authorizedClient, token); - return new DefaultEvaluationContext(identity, session) { - @Override - public Map> getBaseAttributes() { - Map> attributes = super.getBaseAttributes(); - attributes.put("kc.client.id", List.of(authorizedClient.getClientId())); - return attributes; - } - }; - } - private boolean hasGrantedPermission(Resource resource, String scope) { ResourceServer server = root.realmResourceServer(); Collection permissions = root.evaluatePermission(new ResourcePermission(resource, resource.getScopes(), server), server); for (Permission permission : permissions) { - for (String s : permission.getScopes()) { - if (scope.equals(s)) { - return true; + if (permission.getResourceId().equals(resource.getId())) { + for (String s : permission.getScopes()) { + if (scope.equals(s)) { + return true; + } } } } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionsV2.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionsV2.java index 82035684add..70bfb432a30 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionsV2.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionsV2.java @@ -23,6 +23,9 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Function; +import java.util.stream.Stream; + import org.keycloak.authorization.AdminPermissionsSchema; import org.keycloak.authorization.AuthorizationProvider; import org.keycloak.authorization.model.Policy; @@ -118,9 +121,11 @@ class GroupPermissionsV2 extends GroupPermissions { Set granted = new HashSet<>(); - resourceStore.findByType(server, AdminPermissionsSchema.GROUPS_RESOURCE_TYPE, groupResource -> { - if (hasPermission(groupResource.getId(), AdminPermissionsSchema.VIEW_MEMBERS, AdminPermissionsSchema.MANAGE_MEMBERS)) { - granted.add(groupResource.getId()); + policyStore.findByResourceType(server, AdminPermissionsSchema.GROUPS_RESOURCE_TYPE).stream() + .flatMap((Function>) policy -> policy.getResources().stream()) + .forEach(gr -> { + if (hasPermission(gr.getName(), AdminPermissionsSchema.VIEW_MEMBERS, AdminPermissionsSchema.MANAGE_MEMBERS)) { + granted.add(gr.getName()); } }); @@ -154,9 +159,11 @@ class GroupPermissionsV2 extends GroupPermissions { List expectedScopes = Arrays.asList(scopes); for (Permission permission : permissions) { - for (String scope : permission.getScopes()) { - if (expectedScopes.contains(scope)) { - return true; + if (permission.getResourceId().equals(resource.getId())) { + for (String scope : permission.getScopes()) { + if (expectedScopes.contains(scope)) { + return true; + } } } } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissionEvaluator.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissionEvaluator.java index 833db1d9b49..b9ba658b44a 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissionEvaluator.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissionEvaluator.java @@ -141,5 +141,10 @@ public interface RolePermissionEvaluator { */ void requireView(RoleContainerModel container); - Set getRolesWithPermission(String scope); + /** + * Returns the IDs of the roles that the current user can view.. + * + * @return Stream of IDs of roles with view permission. + */ + Set getRoleIdsWithViewPermission(String scope); } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissions.java index e87075b9d31..77eba0864d1 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissions.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissions.java @@ -24,6 +24,7 @@ import org.keycloak.authorization.model.Resource; import org.keycloak.authorization.model.ResourceServer; import org.keycloak.authorization.model.Scope; import org.keycloak.authorization.permission.ResourcePermission; +import org.keycloak.authorization.store.PolicyStore; import org.keycloak.authorization.store.ResourceStore; import org.keycloak.models.AdminRoles; import org.keycloak.models.ClientModel; @@ -55,6 +56,7 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme protected final AuthorizationProvider authz; protected final MgmtPermissions root; protected final ResourceStore resourceStore; + protected final PolicyStore policyStore; private static final String RESOURCE_NAME_PREFIX = "role.resource."; public RolePermissions(KeycloakSession session, RealmModel realm, AuthorizationProvider authz, MgmtPermissions root) { @@ -64,8 +66,10 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme this.root = root; if (authz != null) { resourceStore = authz.getStoreFactory().getResourceStore(); + policyStore = authz.getStoreFactory().getPolicyStore(); } else { resourceStore = null; + policyStore = null; } } @@ -540,7 +544,7 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme } @Override - public Set getRolesWithPermission(String scope) { + public Set getRoleIdsWithViewPermission(String scope) { if (!root.isAdminSameRealm()) { return Collections.emptySet(); } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissionsV2.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissionsV2.java index cfbb93d1b4c..8947c83cd21 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissionsV2.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissionsV2.java @@ -35,6 +35,8 @@ import java.util.Collections; import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.function.Function; +import java.util.stream.Stream; public class RolePermissionsV2 extends RolePermissions { @@ -76,7 +78,7 @@ public class RolePermissionsV2 extends RolePermissions { } @Override - public Set getRolesWithPermission(String scope) { + public Set getRoleIdsWithViewPermission(String scope) { if (!root.isAdminSameRealm()) { return Collections.emptySet(); } @@ -89,11 +91,13 @@ public class RolePermissionsV2 extends RolePermissions { Set granted = new HashSet<>(); - resourceStore.findByType(server, AdminPermissionsSchema.ROLES_RESOURCE_TYPE, resource -> { - if (hasGrantedPermission(server, resource, scope)) { - granted.add(resource.getName()); - } - }); + policyStore.findByResourceType(server, AdminPermissionsSchema.ROLES_RESOURCE_TYPE).stream() + .flatMap((Function>) policy -> policy.getResources().stream()) + .forEach(gr -> { + if (hasGrantedPermission(server, gr, scope)) { + granted.add(gr.getName()); + } + }); return granted; } @@ -121,11 +125,13 @@ public class RolePermissionsV2 extends RolePermissions { private boolean hasGrantedPermission(ResourceServer server, Resource resource, String scope) { Collection permissions = root.evaluatePermission(new ResourcePermission(resource, resource.getScopes(), server), server); for (Permission permission : permissions) { - for (String s : permission.getScopes()) { - if (scope.equals(s)) { - return true; + if (permission.getResourceId().equals(resource.getId())) { + for (String s : permission.getScopes()) { + if (scope.equals(s)) { + return true; + } } - } + }; } return false;