mirror of
https://github.com/keycloak/keycloak.git
synced 2026-05-26 13:50:48 +00:00
Enforce resource server predicates if one was given despite the IS_ADMIN flag (#48385)
Closes #48324 Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com>
This commit is contained in:
+17
-14
@@ -87,24 +87,27 @@ public class JPAPermissionTicketStore implements PermissionTicketStore {
|
||||
List<Predicate> predicates = new ArrayList<>();
|
||||
KeycloakSession session = provider.getKeycloakSession();
|
||||
|
||||
if (resourceServer != null && !Boolean.parseBoolean(attributes.get(PermissionTicket.FilterOption.IS_ADMIN))) {
|
||||
if (resourceServer != null) {
|
||||
predicates.add(builder.equal(root.get("resourceServer").get("id"), resourceServer.getId()));
|
||||
ClientModel resourceServerClient = session.clients().getClientById(session.getContext().getRealm(), resourceServer.getClientId());
|
||||
UserModel currentUser = session.getContext().getUser();
|
||||
|
||||
if (resourceServerClient.isServiceAccountsEnabled()) {
|
||||
UserModel serviceAccount = session.users().getServiceAccount(resourceServerClient);
|
||||
if (!Boolean.parseBoolean(attributes.get(PermissionTicket.FilterOption.IS_ADMIN))) {
|
||||
ClientModel resourceServerClient = session.clients().getClientById(session.getContext().getRealm(), resourceServer.getClientId());
|
||||
UserModel currentUser = session.getContext().getUser();
|
||||
|
||||
if (serviceAccount != null && serviceAccount.equals(currentUser)) {
|
||||
currentUser = null;
|
||||
if (resourceServerClient.isServiceAccountsEnabled()) {
|
||||
UserModel serviceAccount = session.users().getServiceAccount(resourceServerClient);
|
||||
|
||||
if (serviceAccount != null && serviceAccount.equals(currentUser)) {
|
||||
currentUser = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (currentUser != null) {
|
||||
predicates.add(builder.or(
|
||||
builder.equal(root.get("owner"), currentUser.getId()),
|
||||
builder.equal(root.get("requester"), currentUser.getId())
|
||||
));
|
||||
if (currentUser != null) {
|
||||
predicates.add(builder.or(
|
||||
builder.equal(root.get("owner"), currentUser.getId()),
|
||||
builder.equal(root.get("requester"), currentUser.getId())
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +193,7 @@ public class JPAPermissionTicketStore implements PermissionTicketStore {
|
||||
|
||||
PermissionTicketEntity entity = entityManager.find(PermissionTicketEntity.class, id);
|
||||
|
||||
if (entity == null || !resourceServer.getId().equals(entity.getResourceServer().getId())) {
|
||||
if (entity == null || (resourceServer != null && !resourceServer.getId().equals(entity.getResourceServer().getId()))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+109
@@ -39,6 +39,7 @@ import org.keycloak.representations.idm.authorization.PermissionTicketRepresenta
|
||||
import org.keycloak.representations.idm.authorization.PermissionTicketToken;
|
||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
|
||||
import org.keycloak.testframework.realm.ClientBuilder;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -511,4 +512,112 @@ public class PermissionManagementTest extends AbstractResourceServerTest {
|
||||
Long ticketCount = getAuthzClient().protection().permission().count(resource.getId(), null, null, null, null, true);
|
||||
assertEquals(Long.valueOf(4), ticketCount, "Returned number of permissions tickets must match the amount of permission tickets.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testISAdminFilterRespectsResourceServer() {
|
||||
// create a second resource server
|
||||
getRealm().clients().create(
|
||||
ClientBuilder.create()
|
||||
.clientId("resource-server-test-2")
|
||||
.secret("secret")
|
||||
.authorizationServicesEnabled(true)
|
||||
.redirectUris("http://localhost/resource-server-test-2")
|
||||
.defaultRoles("uma_protection")
|
||||
.directAccessGrantsEnabled()
|
||||
.serviceAccountsEnabled(true)
|
||||
.build()
|
||||
).close();
|
||||
|
||||
testingClient.server().run(session -> {
|
||||
org.keycloak.models.RealmModel realm = session.realms().getRealmByName("authz-test");
|
||||
session.getContext().setRealm(realm);
|
||||
org.keycloak.authorization.AuthorizationProvider authorization =
|
||||
session.getProvider(org.keycloak.authorization.AuthorizationProvider.class);
|
||||
org.keycloak.authorization.store.StoreFactory storeFactory = authorization.getStoreFactory();
|
||||
org.keycloak.authorization.store.PermissionTicketStore ticketStore =
|
||||
storeFactory.getPermissionTicketStore();
|
||||
|
||||
org.keycloak.models.ClientModel client1 = session.clients()
|
||||
.getClientByClientId(realm, "resource-server-test");
|
||||
org.keycloak.authorization.model.ResourceServer rs1 =
|
||||
storeFactory.getResourceServerStore().findByClient(client1);
|
||||
|
||||
org.keycloak.models.ClientModel client2 = session.clients()
|
||||
.getClientByClientId(realm, "resource-server-test-2");
|
||||
org.keycloak.authorization.model.ResourceServer rs2 =
|
||||
storeFactory.getResourceServerStore().findByClient(client2);
|
||||
|
||||
org.keycloak.authorization.model.Resource resource1 =
|
||||
storeFactory.getResourceStore().create(rs1, "resource-rs1", client1.getId());
|
||||
org.keycloak.authorization.model.Resource resource2 =
|
||||
storeFactory.getResourceStore().create(rs2, "resource-rs2", client2.getId());
|
||||
|
||||
String requester = session.users().getUserByUsername(realm, "marta").getId();
|
||||
|
||||
org.keycloak.authorization.model.PermissionTicket ticket1 =
|
||||
ticketStore.create(rs1, resource1, null, requester);
|
||||
ticket1.setGrantedTimestamp(System.currentTimeMillis());
|
||||
|
||||
org.keycloak.authorization.model.PermissionTicket ticket2 =
|
||||
ticketStore.create(rs2, resource2, null, requester);
|
||||
ticket2.setGrantedTimestamp(System.currentTimeMillis());
|
||||
|
||||
java.util.Map<org.keycloak.authorization.model.PermissionTicket.FilterOption, String> filters =
|
||||
new java.util.EnumMap<>(org.keycloak.authorization.model.PermissionTicket.FilterOption.class);
|
||||
filters.put(org.keycloak.authorization.model.PermissionTicket.FilterOption.IS_ADMIN, "true");
|
||||
filters.put(org.keycloak.authorization.model.PermissionTicket.FilterOption.GRANTED, "true");
|
||||
|
||||
java.util.List<org.keycloak.authorization.model.PermissionTicket> rs1Tickets =
|
||||
ticketStore.find(rs1, filters, null, null);
|
||||
java.util.List<org.keycloak.authorization.model.PermissionTicket> rs2Tickets =
|
||||
ticketStore.find(rs2, filters, null, null);
|
||||
|
||||
assertEquals(1, rs1Tickets.size());
|
||||
assertEquals(rs1.getId(), rs1Tickets.get(0).getResourceServer().getId());
|
||||
|
||||
assertEquals(1, rs2Tickets.size());
|
||||
assertEquals(rs2.getId(), rs2Tickets.get(0).getResourceServer().getId());
|
||||
});
|
||||
|
||||
testingClient.server().run(session -> {
|
||||
org.keycloak.models.RealmModel realm = session.realms().getRealmByName("authz-test");
|
||||
session.getContext().setRealm(realm);
|
||||
org.keycloak.authorization.AuthorizationProvider authorization =
|
||||
session.getProvider(org.keycloak.authorization.AuthorizationProvider.class);
|
||||
org.keycloak.authorization.store.StoreFactory storeFactory = authorization.getStoreFactory();
|
||||
org.keycloak.authorization.store.PermissionTicketStore ticketStore =
|
||||
storeFactory.getPermissionTicketStore();
|
||||
org.keycloak.models.ClientModel client1 = session.clients()
|
||||
.getClientByClientId(realm, "resource-server-test");
|
||||
org.keycloak.authorization.model.ResourceServer rs1 =
|
||||
storeFactory.getResourceServerStore().findByClient(client1);
|
||||
|
||||
org.keycloak.models.ClientModel client2 = session.clients()
|
||||
.getClientByClientId(realm, "resource-server-test-2");
|
||||
org.keycloak.authorization.model.ResourceServer rs2 =
|
||||
storeFactory.getResourceServerStore().findByClient(client2);
|
||||
java.util.Map<org.keycloak.authorization.model.PermissionTicket.FilterOption, String> filters =
|
||||
new java.util.EnumMap<>(org.keycloak.authorization.model.PermissionTicket.FilterOption.class);
|
||||
filters.put(org.keycloak.authorization.model.PermissionTicket.FilterOption.IS_ADMIN, "true");
|
||||
filters.put(org.keycloak.authorization.model.PermissionTicket.FilterOption.GRANTED, "true");
|
||||
|
||||
java.util.List<org.keycloak.authorization.model.PermissionTicket> rs1Tickets =
|
||||
ticketStore.find(rs1, filters, null, null);
|
||||
java.util.List<org.keycloak.authorization.model.PermissionTicket> rs2Tickets =
|
||||
ticketStore.find(rs2, filters, null, null);
|
||||
|
||||
assertEquals(1, rs1Tickets.size());
|
||||
assertEquals(rs1.getId(), rs1Tickets.get(0).getResourceServer().getId());
|
||||
|
||||
assertEquals(1, rs2Tickets.size());
|
||||
assertEquals(rs2.getId(), rs2Tickets.get(0).getResourceServer().getId());
|
||||
|
||||
rs1Tickets =
|
||||
ticketStore.find(null, filters, null, null);
|
||||
assertEquals(2, rs1Tickets.size());
|
||||
rs2Tickets =
|
||||
ticketStore.find(null, filters, null, null);
|
||||
assertEquals(2, rs2Tickets.size());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user