Missing and incorrect permission checks on organization invitation endpoints

Closes #49069

Signed-off-by: vramik <vramik@redhat.com>
This commit is contained in:
vramik
2026-05-18 16:08:39 +02:00
committed by Pedro Igor
parent 6ef5a79876
commit 87160a4e84
2 changed files with 34 additions and 3 deletions
@@ -265,6 +265,7 @@ public class OrganizationInvitationResource {
@QueryParam("search") String search,
@QueryParam("firstName") String firstName,
@QueryParam("lastName") String lastName) {
auth.orgs().requireManage(organization);
OrganizationProvider provider = session.getProvider(OrganizationProvider.class);
Map<Filter, String> filters = new HashMap<>();
@@ -305,6 +306,7 @@ public class OrganizationInvitationResource {
@APIResponse(responseCode = "404", description = "Not Found")
})
public OrganizationInvitationRepresentation getInvitation(@PathParam("id") String id) {
auth.orgs().requireManage(organization);
OrganizationProvider provider = session.getProvider(OrganizationProvider.class);
InvitationManager invitationManager = provider.getInvitationManager();
@@ -320,7 +322,7 @@ public class OrganizationInvitationResource {
@APIResponse(responseCode = "404", description = "Not Found")
})
public Response deleteInvitation(@PathParam("id") String id) {
auth.orgs().requireManage();
auth.orgs().requireManage(organization);
OrganizationProvider provider = session.getProvider(OrganizationProvider.class);
InvitationManager invitationManager = provider.getInvitationManager();
@@ -340,7 +342,7 @@ public class OrganizationInvitationResource {
@APIResponse(responseCode = "404", description = "Not Found")
})
public Response resendInvitation(@PathParam("id") String id) {
auth.orgs().requireManage();
auth.orgs().requireManage(organization);
if (!organization.isEnabled()) {
throw ErrorResponse.error("Organization is disabled", Status.BAD_REQUEST);
@@ -680,15 +680,44 @@ public class OrganizationAdminRolesPermissionsTest extends AbstractOrganizationT
}
invitationId = manageOrgsResource.organizations().get(orgId).invitations().list().get(0).getId();
assertThat(manageOrgsResource.organizations().get(orgId).invitations().get(invitationId), Matchers.notNullValue());
}
// view-orgs-manage-users-admin cannot delete or resend invitations
// view-orgs-admin (view-organizations only) cannot list or get invitations
try (
Keycloak viewOrgsClient = adminClientFactory.create()
.realm(realm.getName()).username("view-orgs-admin").password("password").clientId(Constants.ADMIN_CLI_CLIENT_ID).build()
) {
RealmResource viewOrgsResource = viewOrgsClient.realm(realm.getName());
try {
viewOrgsResource.organizations().get(orgId).invitations().list();
fail("Expected ForbiddenException");
} catch (ForbiddenException expected) {}
try {
viewOrgsResource.organizations().get(orgId).invitations().get(invitationId);
fail("Expected ForbiddenException");
} catch (ForbiddenException expected) {}
}
// view-orgs-manage-users-admin cannot list, get, delete, or resend invitations
try (
Keycloak viewOrgsManageUsersClient = adminClientFactory.create()
.realm(realm.getName()).username("view-orgs-manage-users-admin").password("password").clientId(Constants.ADMIN_CLI_CLIENT_ID).build()
) {
RealmResource viewOrgsManageUsersResource = viewOrgsManageUsersClient.realm(realm.getName());
try {
viewOrgsManageUsersResource.organizations().get(orgId).invitations().list();
fail("Expected ForbiddenException");
} catch (ForbiddenException expected) {}
try {
viewOrgsManageUsersResource.organizations().get(orgId).invitations().get(invitationId);
fail("Expected ForbiddenException");
} catch (ForbiddenException expected) {}
try (Response response = viewOrgsManageUsersResource.organizations().get(orgId).invitations().delete(invitationId)) {
assertThat(response.getStatus(), equalTo(Status.FORBIDDEN.getStatusCode()));
}