Validate organization alias for forbidden chars

Closes #32392

Signed-off-by: Martin Kanis <mkanis@redhat.com>
This commit is contained in:
Martin Kanis 2024-08-28 10:29:03 +02:00 committed by Alexander Schwartz
parent 9bbfec5cdd
commit 7e6dd682d4
3 changed files with 48 additions and 0 deletions

View file

@ -59,6 +59,7 @@ import org.keycloak.models.jpa.entities.UserGroupMembershipEntity;
import org.keycloak.organization.OrganizationProvider;
import org.keycloak.representations.idm.MembershipType;
import org.keycloak.organization.utils.Organizations;
import org.keycloak.utils.ReservedCharValidator;
import org.keycloak.utils.StringUtil;
public class JpaOrganizationProvider implements OrganizationProvider {
@ -82,6 +83,11 @@ public class JpaOrganizationProvider implements OrganizationProvider {
}
if (StringUtil.isBlank(alias)) {
try {
ReservedCharValidator.validateNoSpace(name);
} catch (ReservedCharValidator.ReservedCharException e) {
throw new ModelValidationException("Name contains a reserved character and cannot be used as alias");
}
alias = name;
}

View file

@ -49,6 +49,7 @@ import org.keycloak.services.ErrorResponse;
import org.keycloak.services.resources.KeycloakOpenAPI;
import org.keycloak.services.resources.admin.AdminEventBuilder;
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.utils.ReservedCharValidator;
import org.keycloak.utils.SearchQueryUtils;
import org.keycloak.utils.StringUtil;
@ -91,6 +92,8 @@ public class OrganizationsResource {
throw ErrorResponse.error("Organization cannot be null.", Response.Status.BAD_REQUEST);
}
ReservedCharValidator.validateNoSpace(organization.getAlias());
try {
OrganizationModel model = provider.create(organization.getName(), organization.getAlias());

View file

@ -60,6 +60,7 @@ import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.keycloak.representations.idm.OrganizationDomainRepresentation;
import org.keycloak.representations.idm.OrganizationRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.arquillian.annotation.EnableFeature;
import org.keycloak.testsuite.runonserver.RunOnServer;
import org.keycloak.testsuite.updaters.RealmAttributeUpdater;
@ -515,4 +516,42 @@ public class OrganizationTest extends AbstractOrganizationTest {
assertEquals("A organization with the same alias already exists", error.getErrorMessage());
}
}
@Test
public void testSpecialCharsAlias() {
OrganizationRepresentation org = createRepresentation("acme");
OrganizationDomainRepresentation orgDomain = new OrganizationDomainRepresentation();
orgDomain.setName("acme.com");
org.addDomain(orgDomain);
org.setAlias("acme&@#!");
try (Response response = testRealm().organizations().create(org)) {
assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
}
// blank alias will be replaced with org name, which is valid
org.setAlias("");
try (Response response = testRealm().organizations().create(org)) {
assertEquals(Status.CREATED.getStatusCode(), response.getStatus());
String id = ApiUtil.getCreatedId(response);
getCleanup().addCleanup(() -> testRealm().organizations().get(id).delete().close());
}
org.setAlias(" ");
try (Response response = testRealm().organizations().create(org)) {
assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
}
org.setAlias("\n");
try (Response response = testRealm().organizations().create(org)) {
assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
}
// when alias is empty, name is used as alias
org.setName("acme@");
org.setAlias("");
try (Response response = testRealm().organizations().create(org)) {
assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
}
}
}