Make sure operations on a organization are based on realm they belong to

Closes #28841

Signed-off-by: Martin Kanis <mkanis@redhat.com>
This commit is contained in:
Martin Kanis 2024-05-14 14:16:59 +02:00 committed by Pedro Igor
parent f14f4805d6
commit 3985157f9f
3 changed files with 67 additions and 1 deletions

View file

@ -54,7 +54,6 @@ import org.keycloak.models.jpa.entities.GroupAttributeEntity;
import org.keycloak.models.jpa.entities.GroupEntity;
import org.keycloak.models.jpa.entities.OrganizationDomainEntity;
import org.keycloak.models.jpa.entities.OrganizationEntity;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.organization.OrganizationProvider;
import org.keycloak.utils.StringUtil;
@ -150,6 +149,11 @@ public class JpaOrganizationProvider implements OrganizationProvider {
OrganizationEntity entity = getEntity(organization.getId());
OrganizationModel current = (OrganizationModel) session.getAttribute(OrganizationModel.class.getName());
// check the user and the organization belongs to the same realm
if (session.users().getUserById(session.realms().getRealm(entity.getRealmId()), user.getId()) == null) {
return false;
}
if (current == null) {
session.setAttribute(OrganizationModel.class.getName(), organization);
}
@ -283,6 +287,12 @@ public class JpaOrganizationProvider implements OrganizationProvider {
throwExceptionIfObjectIsNull(identityProvider, "Identity provider");
OrganizationEntity organizationEntity = getEntity(organization.getId());
// check the identity provider and the organization belongs to the same realm
if (!checkOrgIdpAndRealm(organizationEntity, identityProvider)) {
return false;
}
String orgId = identityProvider.getOrganizationId();
if (organizationEntity.getId().equals(orgId)) {
@ -455,4 +465,12 @@ public class JpaOrganizationProvider implements OrganizationProvider {
return null;
}
}
// return true only if the organization realm and the identity provider realm is the same
private boolean checkOrgIdpAndRealm(OrganizationEntity orgEntity, IdentityProviderModel idp) {
RealmModel orgRealm = session.realms().getRealm(orgEntity.getRealmId());
IdentityProviderModel orgIdpByAlias = orgRealm.getIdentityProviderByAlias(idp.getAlias());
return orgIdpByAlias != null && orgIdpByAlias.getInternalId().equals(idp.getInternalId());
}
}

View file

@ -19,6 +19,7 @@ package org.keycloak.testsuite.organization.admin;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertFalse;
import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.NotFoundException;
@ -30,7 +31,10 @@ import org.keycloak.admin.client.resource.IdentityProviderResource;
import org.keycloak.admin.client.resource.OrganizationIdentityProviderResource;
import org.keycloak.admin.client.resource.OrganizationResource;
import org.keycloak.common.Profile.Feature;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.OrganizationModel;
import org.keycloak.models.RealmModel;
import org.keycloak.organization.OrganizationProvider;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.keycloak.representations.idm.OrganizationRepresentation;
import org.keycloak.testsuite.arquillian.annotation.EnableFeature;
@ -195,6 +199,27 @@ public class OrganizationIdentityProviderTest extends AbstractOrganizationTest {
}
}
@Test
public void testAddIdpFromDifferentRealm() {
String orgId = createOrganization().getId();
IdentityProviderRepresentation idpRepresentation = createRep("master-identity-provider", "oidc");
adminClient.realm("master").identityProviders().create(idpRepresentation).close();
getTestingClient().server(TEST_REALM_NAME).run(session -> {
OrganizationProvider provider = session.getProvider(OrganizationProvider.class);
OrganizationModel organization = provider.getById(orgId);
RealmModel realm = session.realms().getRealmByName("master");
IdentityProviderModel idp = realm.getIdentityProviderByAlias("master-identity-provider");
try {
assertFalse(provider.addIdentityProvider(organization, idp));
} finally {
realm.removeIdentityProviderByAlias("master-identity-provider");
}
});
}
private IdentityProviderRepresentation createRep(String alias, String providerId) {
IdentityProviderRepresentation idp = new IdentityProviderRepresentation();

View file

@ -45,7 +45,11 @@ import org.keycloak.admin.client.resource.OrganizationMemberResource;
import org.keycloak.admin.client.resource.OrganizationResource;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.common.Profile.Feature;
import org.keycloak.models.OrganizationModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.organization.OrganizationProvider;
import org.keycloak.representations.idm.ErrorRepresentation;
import org.keycloak.representations.idm.OrganizationRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
@ -390,4 +394,23 @@ public class OrganizationMemberTest extends AbstractOrganizationTest {
assertThat(existing.get(1).getUsername(), is(equalTo("thejoker@neworg.org")));
}
@Test
public void testAddMemberFromDifferentRealm() {
String orgId = createOrganization().getId();
getTestingClient().server(TEST_REALM_NAME).run(session -> {
OrganizationProvider provider = session.getProvider(OrganizationProvider.class);
OrganizationModel organization = provider.getById(orgId);
RealmModel realm = session.realms().getRealmByName("master");
session.users().addUser(realm, "master-test-user");
UserModel user = null;
try {
user = session.users().getUserByUsername(realm, "master-test-user");
assertFalse(provider.addMember(organization, user));
} finally {
session.users().removeUser(realm, user);
}
});
}
}