Disable username prohibited chars validator when email as username is… (#31140)
* Disable username prohibited chars validator when email as the username is set Closes #25339 Signed-off-by: Martin Kanis <mkanis@redhat.com> Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Co-authored-by: Pedro Igor <pigor.craveiro@gmail.com>
This commit is contained in:
parent
d475833361
commit
922eaa9fc8
3 changed files with 51 additions and 14 deletions
|
@ -285,6 +285,7 @@ The list below provides a list of all the built-in validators:
|
||||||
|
|
||||||
|username-prohibited-characters
|
|username-prohibited-characters
|
||||||
| Check if the value is a valid username as an additional barrier for attacks such as script injection. The validation is based on a default RegEx pattern that blocks characters not common in usernames.
|
| Check if the value is a valid username as an additional barrier for attacks such as script injection. The validation is based on a default RegEx pattern that blocks characters not common in usernames.
|
||||||
|
When the realm setting `Email as username` is enabled, this validator is skipped to allow email values.
|
||||||
|
|
|
|
||||||
|
|
||||||
*error-message*: the key of the error message in i18n bundle. If not set a generic message is used.
|
*error-message*: the key of the error message in i18n bundle. If not set a generic message is used.
|
||||||
|
|
|
@ -20,6 +20,8 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.provider.ConfiguredProvider;
|
import org.keycloak.provider.ConfiguredProvider;
|
||||||
import org.keycloak.provider.ProviderConfigProperty;
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
import org.keycloak.validate.AbstractStringValidator;
|
import org.keycloak.validate.AbstractStringValidator;
|
||||||
|
@ -64,6 +66,16 @@ public class UsernameProhibitedCharactersValidator extends AbstractStringValidat
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doValidate(String value, String inputHint, ValidationContext context, ValidatorConfig config) {
|
protected void doValidate(String value, String inputHint, ValidationContext context, ValidatorConfig config) {
|
||||||
|
KeycloakSession session = context.getSession();
|
||||||
|
|
||||||
|
if (session != null) {
|
||||||
|
RealmModel realm = session.getContext().getRealm();
|
||||||
|
|
||||||
|
if (realm.isRegistrationEmailAsUsername()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!PATTERN.matcher(value).matches()) {
|
if (!PATTERN.matcher(value).matches()) {
|
||||||
context.addError(new ValidationError(ID, inputHint, config.getStringOrDefault(CFG_ERROR_MESSAGE, MESSAGE_NO_MATCH)));
|
context.addError(new ValidationError(ID, inputHint, config.getStringOrDefault(CFG_ERROR_MESSAGE, MESSAGE_NO_MATCH)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -321,6 +321,7 @@ public class UserProfileTest extends AbstractUserProfileTest {
|
||||||
public void testValidation() {
|
public void testValidation() {
|
||||||
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::failValidationWhenEmptyAttributes);
|
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::failValidationWhenEmptyAttributes);
|
||||||
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testAttributeValidation);
|
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testAttributeValidation);
|
||||||
|
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testEmailAsUsernameValidation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void failValidationWhenEmptyAttributes(KeycloakSession session) {
|
private static void failValidationWhenEmptyAttributes(KeycloakSession session) {
|
||||||
|
@ -399,6 +400,29 @@ public class UserProfileTest extends AbstractUserProfileTest {
|
||||||
assertTrue(containsErrorMessage(errors, EmailValidator.MESSAGE_INVALID_EMAIL));
|
assertTrue(containsErrorMessage(errors, EmailValidator.MESSAGE_INVALID_EMAIL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void testEmailAsUsernameValidation(KeycloakSession session) {
|
||||||
|
Map<String, Object> attributes = new HashMap<>();
|
||||||
|
UserProfileProvider provider = session.getProvider(UserProfileProvider.class);
|
||||||
|
provider.setConfiguration(null);
|
||||||
|
UserProfile profile;
|
||||||
|
RealmModel realm = session.getContext().getRealm();
|
||||||
|
|
||||||
|
try {
|
||||||
|
realm.setRegistrationEmailAsUsername(true);
|
||||||
|
attributes.clear();
|
||||||
|
attributes.put(UserModel.FIRST_NAME, "Joe");
|
||||||
|
attributes.put(UserModel.LAST_NAME, "Doe");
|
||||||
|
// valid email but invalid as username
|
||||||
|
attributes.put(UserModel.EMAIL, "foo%bar@example.com");
|
||||||
|
profile = provider.create(UserProfileContext.UPDATE_PROFILE, attributes);
|
||||||
|
profile.validate();
|
||||||
|
} catch (ValidationException ve) {
|
||||||
|
Assert.fail("Should be OK email as username");
|
||||||
|
} finally {
|
||||||
|
realm.setRegistrationEmailAsUsername(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean containsErrorMessage(List<ValidationError> errors, String message){
|
private static boolean containsErrorMessage(List<ValidationError> errors, String message){
|
||||||
for(ValidationError err : errors) {
|
for(ValidationError err : errors) {
|
||||||
if(err.getMessage().equals(message)) {
|
if(err.getMessage().equals(message)) {
|
||||||
|
|
Loading…
Reference in a new issue