Fix for empty realm name issue

Throw ModelException if name is empty when creating/updating a realm

Closes #17449

Signed-off-by: atharva kshirsagar <atharva4894@gmail.com>
Signed-off-by: Alexander Schwartz <aschwart@redhat.com>
Co-authored-by: Alexander Schwartz <aschwart@redhat.com>
This commit is contained in:
atharva kshirsagar 2024-01-01 12:23:05 +05:30 committed by Alexander Schwartz
parent 7bde7c30cc
commit d7542c9344
4 changed files with 27 additions and 9 deletions

View file

@ -97,8 +97,9 @@ import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel; import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.storage.UserStorageUtil; import org.keycloak.storage.UserStorageUtil;
import org.keycloak.storage.federated.UserFederatedStorageProvider; import org.keycloak.storage.federated.UserFederatedStorageProvider;
import org.keycloak.userprofile.UserProfileProvider;
import org.keycloak.util.JsonSerialization; import org.keycloak.util.JsonSerialization;
import org.keycloak.utils.ReservedCharValidator;
import org.keycloak.utils.StringUtil;
import org.keycloak.validation.ValidationUtil; import org.keycloak.validation.ValidationUtil;
import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.MediaType;
@ -651,7 +652,12 @@ public class LegacyExportImportManager implements ExportImportManager {
public static void renameRealm(RealmModel realm, String name) { public static void renameRealm(RealmModel realm, String name) {
if (name.equals(realm.getName())) return; if (name.equals(realm.getName())) {
return;
}
if (StringUtil.isBlank(name)) {
throw new ModelException("Realm name cannot be empty");
}
String oldName = realm.getName(); String oldName = realm.getName();

View file

@ -26,6 +26,7 @@ import org.keycloak.models.ClientModel;
import org.keycloak.models.Constants; import org.keycloak.models.Constants;
import org.keycloak.models.ImpersonationConstants; import org.keycloak.models.ImpersonationConstants;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelException;
import org.keycloak.models.OTPPolicy; import org.keycloak.models.OTPPolicy;
import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
@ -61,6 +62,7 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import org.keycloak.utils.ReservedCharValidator; import org.keycloak.utils.ReservedCharValidator;
import org.keycloak.utils.StringUtil;
/** /**
* Per request object * Per request object
@ -515,6 +517,9 @@ public class RealmManager {
} else { } else {
ReservedCharValidator.validate(id); ReservedCharValidator.validate(id);
} }
if (StringUtil.isBlank(rep.getRealm())) {
throw new ModelException("Realm name cannot be empty");
}
RealmModel realm = model.createRealm(id, rep.getRealm()); RealmModel realm = model.createRealm(id, rep.getRealm());
RealmModel currentRealm = session.getContext().getRealm(); RealmModel currentRealm = session.getContext().getRealm();

View file

@ -30,6 +30,7 @@ import org.keycloak.models.AdminRoles;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException; import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.ModelException;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.ModelToRepresentation; import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.StripSecretsUtils; import org.keycloak.models.utils.StripSecretsUtils;
@ -167,6 +168,8 @@ public class RealmsAdminResource {
logger.error("Password policy not met for user " + e.getUsername(), e); logger.error("Password policy not met for user " + e.getUsername(), e);
if (session.getTransactionManager().isActive()) session.getTransactionManager().setRollbackOnly(); if (session.getTransactionManager().isActive()) session.getTransactionManager().setRollbackOnly();
throw ErrorResponse.error("Password policy not met. See logs for details", Response.Status.BAD_REQUEST); throw ErrorResponse.error("Password policy not met. See logs for details", Response.Status.BAD_REQUEST);
} catch (ModelException e) {
throw ErrorResponse.error(e.getMessage(), Response.Status.BAD_REQUEST);
} }
} }

View file

@ -58,7 +58,6 @@ import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.auth.page.AuthRealm; import org.keycloak.testsuite.auth.page.AuthRealm;
import org.keycloak.testsuite.client.KeycloakTestingClient; import org.keycloak.testsuite.client.KeycloakTestingClient;
import org.keycloak.testsuite.events.TestEventsListenerProviderFactory; import org.keycloak.testsuite.events.TestEventsListenerProviderFactory;
import org.keycloak.testsuite.model.StoreProvider;
import org.keycloak.testsuite.runonserver.RunHelpers; import org.keycloak.testsuite.runonserver.RunHelpers;
import org.keycloak.testsuite.updaters.Creator; import org.keycloak.testsuite.updaters.Creator;
import org.keycloak.testsuite.util.AdminEventPaths; import org.keycloak.testsuite.util.AdminEventPaths;
@ -96,6 +95,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import static org.keycloak.testsuite.util.ServerURLs.getAuthServerContextRoot; import static org.keycloak.testsuite.util.ServerURLs.getAuthServerContextRoot;
@ -213,11 +213,13 @@ public class RealmTest extends AbstractAdminTest {
Assert.assertNames(adminClient.realms().findAll(), "master", AuthRealm.TEST, REALM_NAME); Assert.assertNames(adminClient.realms().findAll(), "master", AuthRealm.TEST, REALM_NAME);
} }
@Test(expected = BadRequestException.class) @Test
public void createRealmRejectReservedChar() { public void createRealmRejectReservedCharOrEmptyName() {
RealmRepresentation rep = new RealmRepresentation(); RealmRepresentation rep = new RealmRepresentation();
rep.setRealm("new-re;alm"); rep.setRealm("new-re;alm");
adminClient.realms().create(rep); assertThrows(BadRequestException.class, () -> adminClient.realms().create(rep));
rep.setRealm("");
assertThrows(BadRequestException.class, () -> adminClient.realms().create(rep));
} }
/** /**
@ -460,11 +462,13 @@ public class RealmTest extends AbstractAdminTest {
checkRealmEventsConfigRepresentation(repOrig, actual); checkRealmEventsConfigRepresentation(repOrig, actual);
} }
@Test(expected = BadRequestException.class) @Test
public void updateRealmWithReservedCharInName() { public void updateRealmWithReservedCharInNameOrEmptyName() {
RealmRepresentation rep = realm.toRepresentation(); RealmRepresentation rep = realm.toRepresentation();
rep.setRealm("fo#o"); rep.setRealm("fo#o");
realm.update(rep); assertThrows(BadRequestException.class, () -> realm.update(rep));
rep.setRealm("");
assertThrows(BadRequestException.class, () -> realm.update(rep));
} }
@Test @Test