Ensure get organizations by member id requires managing realm

Closes #47062

Signed-off-by: vramik <vramik@redhat.com>
This commit is contained in:
vramik 2026-03-16 10:58:51 +01:00 committed by Pedro Igor
parent a712d01234
commit 529c1a9009
2 changed files with 41 additions and 1 deletions

View file

@ -227,7 +227,11 @@ public class OrganizationsResource {
public Stream<OrganizationRepresentation> getOrganizations(
@PathParam("member-id") String memberId,
@Parameter(description = "if false, return the full representation. Otherwise, only the basic fields are returned.")
@QueryParam("briefRepresentation") @DefaultValue("true") boolean briefRepresentation) {
@QueryParam("briefRepresentation") @DefaultValue("true") boolean briefRepresentation
) {
auth.realm().requireManageRealm();
Organizations.checkEnabled(provider);
return new OrganizationMemberResource(session, null, adminEvent).getOrganizations(memberId, briefRepresentation);
}
}

View file

@ -24,13 +24,16 @@ import java.util.List;
import java.util.stream.Stream;
import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.resource.OrganizationMemberResource;
import org.keycloak.admin.client.resource.OrganizationResource;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.models.Constants;
import org.keycloak.models.OrganizationModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
@ -49,6 +52,7 @@ import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.organization.admin.AbstractOrganizationTest;
import org.keycloak.testsuite.pages.AppPage;
import org.keycloak.testsuite.updaters.RealmAttributeUpdater;
import org.keycloak.testsuite.util.AdminClientUtil;
import org.keycloak.testsuite.util.UserBuilder;
import org.hamcrest.Matchers;
@ -705,6 +709,38 @@ public class OrganizationMemberTest extends AbstractOrganizationTest {
fullOrgsGlobal.get(0).getAttributes().containsKey("testAttribute"));
}
@Test
public void testGetMemberOrganizationsForbiddenForNonAdminUser() throws Exception {
// create 2 orgs
OrganizationRepresentation orgA = createOrganization("orga");
OrganizationRepresentation orgB = createOrganization("orgb");
// create userA and add as member of both orgs
OrganizationResource orgAResource = testRealm().organizations().get(orgA.getId());
OrganizationResource orgBResource = testRealm().organizations().get(orgB.getId());
UserRepresentation userA = addMember(orgAResource, "usera@orga.org");
orgBResource.members().addMember(userA.getId()).close();
// create userB (non-admin user)
UserRepresentation userB = UserBuilder.create()
.username("userb")
.password("password")
.enabled(true)
.build();
try (Response response = testRealm().users().create(userB)) {
userB.setId(ApiUtil.getCreatedId(response));
}
getCleanup().addCleanup(() -> testRealm().users().get(userB.getId()).remove());
// send request as userB to OrganizationsResource.getOrganizations with member-id = userA
try (Keycloak userBClient = AdminClientUtil.createAdminClient(suiteContext.isAdapterCompatTesting(),
TEST_REALM_NAME, "userb", "password", Constants.ADMIN_CLI_CLIENT_ID, null)) {
userBClient.realm(TEST_REALM_NAME).organizations().members().getOrganizations(userA.getId(), true);
fail("Expected ForbiddenException");
} catch (ForbiddenException expected) {
}
}
private void loginViaNonOrgIdP(String idpAlias) {
oauth.clientId("broker-app");
loginPage.open(bc.consumerRealmName());