Fixes for UsernameIDNHomographValidator
closes #26564 Signed-off-by: mposolda <mposolda@gmail.com>
This commit is contained in:
parent
5373f3c97a
commit
1213556eff
2 changed files with 70 additions and 6 deletions
|
@ -16,13 +16,15 @@
|
|||
*/
|
||||
package org.keycloak.userprofile.validator;
|
||||
|
||||
import org.keycloak.services.messages.Messages;
|
||||
import org.keycloak.provider.ConfiguredProvider;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
import org.keycloak.services.validation.Validation;
|
||||
import org.keycloak.validate.SimpleValidator;
|
||||
import org.keycloak.validate.ValidationContext;
|
||||
import org.keycloak.validate.ValidationError;
|
||||
import org.keycloak.validate.ValidatorConfig;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -31,10 +33,26 @@ import java.util.List;
|
|||
* @author Vlastimil Elias <velias@redhat.com>
|
||||
*
|
||||
*/
|
||||
public class UsernameIDNHomographValidator implements SimpleValidator {
|
||||
public class UsernameIDNHomographValidator implements SimpleValidator, ConfiguredProvider {
|
||||
|
||||
public static final String ID = "up-username-not-idn-homograph";
|
||||
|
||||
public static final String CFG_ERROR_MESSAGE = "error-message";
|
||||
|
||||
public static final String MESSAGE_NO_MATCH = "error-username-invalid-character";
|
||||
|
||||
private static final List<ProviderConfigProperty> configProperties = new ArrayList<>();
|
||||
|
||||
static {
|
||||
ProviderConfigProperty property;
|
||||
property = new ProviderConfigProperty();
|
||||
property.setName(CFG_ERROR_MESSAGE);
|
||||
property.setLabel("Error message key");
|
||||
property.setHelpText("Key of the error message in i18n bundle. Dafault message key is " + MESSAGE_NO_MATCH);
|
||||
property.setType(ProviderConfigProperty.STRING_TYPE);
|
||||
configProperties.add(property);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return ID;
|
||||
|
@ -52,10 +70,24 @@ public class UsernameIDNHomographValidator implements SimpleValidator {
|
|||
}
|
||||
|
||||
if (!Validation.isBlank(value) && !Validation.isUsernameValid(value)) {
|
||||
context.addError(new ValidationError(ID, value, Messages.INVALID_USERNAME));
|
||||
context.addError(new ValidationError(ID, inputHint, getErrorMessageKey(inputHint, config)));
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
protected String getErrorMessageKey(String inputHint, ValidatorConfig config) {
|
||||
String cfg = config.getString(CFG_ERROR_MESSAGE);
|
||||
return (cfg != null && !cfg.isBlank()) ? cfg : MESSAGE_NO_MATCH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpText() {
|
||||
return "The field can contain only latin characters and common unicode characters. Useful for the fields, which can be subject of IDN homograph attacks (typically username).";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProviderConfigProperty> getConfigProperties() {
|
||||
return configProperties;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,6 @@ import java.util.Set;
|
|||
import java.util.function.Consumer;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.common.Profile.Feature;
|
||||
|
@ -65,7 +64,6 @@ import org.keycloak.services.messages.Messages;
|
|||
import org.keycloak.testsuite.arquillian.annotation.EnableFeature;
|
||||
import org.keycloak.testsuite.arquillian.annotation.ModelTest;
|
||||
import org.keycloak.testsuite.runonserver.RunOnServer;
|
||||
import org.keycloak.testsuite.util.LDAPRule;
|
||||
import org.keycloak.userprofile.AttributeGroupMetadata;
|
||||
import org.keycloak.representations.userprofile.config.UPAttribute;
|
||||
import org.keycloak.representations.userprofile.config.UPAttributePermissions;
|
||||
|
@ -943,7 +941,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
|
|||
profile.validate();
|
||||
fail("Should fail validation");
|
||||
} catch (ValidationException ve) {
|
||||
assertTrue(ve.hasError(Messages.INVALID_USERNAME));
|
||||
assertTrue(ve.hasError(UsernameIDNHomographValidator.MESSAGE_NO_MATCH));
|
||||
}
|
||||
|
||||
UPConfig config = provider.getConfiguration();
|
||||
|
@ -962,6 +960,40 @@ public class UserProfileTest extends AbstractUserProfileTest {
|
|||
profile.validate();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHomographValidator() {
|
||||
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testHomographValidator);
|
||||
}
|
||||
|
||||
private static void testHomographValidator(KeycloakSession session) {
|
||||
UserProfileProvider provider = getUserProfileProvider(session);
|
||||
UPConfig config = parseDefaultConfig();
|
||||
|
||||
UPAttribute attribute = config.getAttribute(UserModel.LAST_NAME);
|
||||
attribute.addValidation(UsernameIDNHomographValidator.ID, Map.of(UsernameIDNHomographValidator.CFG_ERROR_MESSAGE, "error-something"));
|
||||
provider.setConfiguration(config);
|
||||
try {
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
|
||||
attributes.put(UserModel.USERNAME, "abc");
|
||||
attributes.put(UserModel.EMAIL, "test@keycloak.org");
|
||||
attributes.put(UserModel.FIRST_NAME, "Foo");
|
||||
attributes.put(UserModel.LAST_NAME, "你好世界");
|
||||
|
||||
UserProfile profile = provider.create(UserProfileContext.UPDATE_PROFILE, attributes);
|
||||
|
||||
try {
|
||||
profile.validate();
|
||||
fail("Should fail validation");
|
||||
} catch (ValidationException ve) {
|
||||
assertTrue(ve.hasError("error-something"));
|
||||
}
|
||||
} finally {
|
||||
attribute.getValidations().remove(UsernameIDNHomographValidator.ID);
|
||||
provider.setConfiguration(config);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOptionalAttributes() {
|
||||
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testOptionalAttributes);
|
||||
|
|
Loading…
Reference in a new issue