Skip to content

Commit 529c1a9

Browse files
vramikpedroigor
authored andcommitted
Ensure get organizations by member id requires managing realm
Closes keycloak#47062 Signed-off-by: vramik <vramik@redhat.com>
1 parent a712d01 commit 529c1a9

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

services/src/main/java/org/keycloak/organization/admin/resource/OrganizationsResource.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,11 @@ public long getOrganizationCount(
227227
public Stream<OrganizationRepresentation> getOrganizations(
228228
@PathParam("member-id") String memberId,
229229
@Parameter(description = "if false, return the full representation. Otherwise, only the basic fields are returned.")
230-
@QueryParam("briefRepresentation") @DefaultValue("true") boolean briefRepresentation) {
230+
@QueryParam("briefRepresentation") @DefaultValue("true") boolean briefRepresentation
231+
) {
232+
auth.realm().requireManageRealm();
233+
Organizations.checkEnabled(provider);
234+
231235
return new OrganizationMemberResource(session, null, adminEvent).getOrganizations(memberId, briefRepresentation);
232236
}
233237
}

testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/member/OrganizationMemberTest.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,16 @@
2424
import java.util.stream.Stream;
2525

2626
import jakarta.ws.rs.BadRequestException;
27+
import jakarta.ws.rs.ForbiddenException;
2728
import jakarta.ws.rs.NotFoundException;
2829
import jakarta.ws.rs.core.Response;
2930
import jakarta.ws.rs.core.Response.Status;
3031

32+
import org.keycloak.admin.client.Keycloak;
3133
import org.keycloak.admin.client.resource.OrganizationMemberResource;
3234
import org.keycloak.admin.client.resource.OrganizationResource;
3335
import org.keycloak.admin.client.resource.UserResource;
36+
import org.keycloak.models.Constants;
3437
import org.keycloak.models.OrganizationModel;
3538
import org.keycloak.models.RealmModel;
3639
import org.keycloak.models.UserModel;
@@ -49,6 +52,7 @@
4952
import org.keycloak.testsuite.organization.admin.AbstractOrganizationTest;
5053
import org.keycloak.testsuite.pages.AppPage;
5154
import org.keycloak.testsuite.updaters.RealmAttributeUpdater;
55+
import org.keycloak.testsuite.util.AdminClientUtil;
5256
import org.keycloak.testsuite.util.UserBuilder;
5357

5458
import org.hamcrest.Matchers;
@@ -705,6 +709,38 @@ public void testGetMemberOrganizationsBriefVsFullRepresentation() {
705709
fullOrgsGlobal.get(0).getAttributes().containsKey("testAttribute"));
706710
}
707711

712+
@Test
713+
public void testGetMemberOrganizationsForbiddenForNonAdminUser() throws Exception {
714+
// create 2 orgs
715+
OrganizationRepresentation orgA = createOrganization("orga");
716+
OrganizationRepresentation orgB = createOrganization("orgb");
717+
718+
// create userA and add as member of both orgs
719+
OrganizationResource orgAResource = testRealm().organizations().get(orgA.getId());
720+
OrganizationResource orgBResource = testRealm().organizations().get(orgB.getId());
721+
UserRepresentation userA = addMember(orgAResource, "usera@orga.org");
722+
orgBResource.members().addMember(userA.getId()).close();
723+
724+
// create userB (non-admin user)
725+
UserRepresentation userB = UserBuilder.create()
726+
.username("userb")
727+
.password("password")
728+
.enabled(true)
729+
.build();
730+
try (Response response = testRealm().users().create(userB)) {
731+
userB.setId(ApiUtil.getCreatedId(response));
732+
}
733+
getCleanup().addCleanup(() -> testRealm().users().get(userB.getId()).remove());
734+
735+
// send request as userB to OrganizationsResource.getOrganizations with member-id = userA
736+
try (Keycloak userBClient = AdminClientUtil.createAdminClient(suiteContext.isAdapterCompatTesting(),
737+
TEST_REALM_NAME, "userb", "password", Constants.ADMIN_CLI_CLIENT_ID, null)) {
738+
userBClient.realm(TEST_REALM_NAME).organizations().members().getOrganizations(userA.getId(), true);
739+
fail("Expected ForbiddenException");
740+
} catch (ForbiddenException expected) {
741+
}
742+
}
743+
708744
private void loginViaNonOrgIdP(String idpAlias) {
709745
oauth.clientId("broker-app");
710746
loginPage.open(bc.consumerRealmName());

0 commit comments

Comments
 (0)