diff --git a/server-spi-private/src/main/java/org/keycloak/authentication/ValidationContext.java b/server-spi-private/src/main/java/org/keycloak/authentication/ValidationContext.java index bfad107078..736acc3c8f 100755 --- a/server-spi-private/src/main/java/org/keycloak/authentication/ValidationContext.java +++ b/server-spi-private/src/main/java/org/keycloak/authentication/ValidationContext.java @@ -45,4 +45,11 @@ public interface ValidationContext extends FormContext { * */ void success(); + + /** + * The error messages of this current validation will take precedence over any others. Other error messages will not + * be shown. This is useful to prevent validation from leaking to an attacker. For example, the recaptcha validator + * calls this method so that usernames cannot be phished + */ + void excludeOtherErrors(); } diff --git a/services/src/main/java/org/keycloak/authentication/FormAuthenticationFlow.java b/services/src/main/java/org/keycloak/authentication/FormAuthenticationFlow.java index 0a9fc07b66..8e6df0a0ee 100755 --- a/services/src/main/java/org/keycloak/authentication/FormAuthenticationFlow.java +++ b/services/src/main/java/org/keycloak/authentication/FormAuthenticationFlow.java @@ -138,6 +138,7 @@ public class FormAuthenticationFlow implements AuthenticationFlow { private class ValidationContextImpl extends FormContextImpl implements ValidationContext { FormAction action; String error; + boolean excludeOthers; private ValidationContextImpl(AuthenticationExecutionModel executionModel, FormAction action) { super(executionModel); @@ -161,6 +162,11 @@ public class FormAuthenticationFlow implements AuthenticationFlow { public void success() { success = true; } + + @Override + public void excludeOtherErrors() { + excludeOthers = true; + } } @Override @@ -222,8 +228,17 @@ public class FormAuthenticationFlow implements AuthenticationFlow { for (ValidationContextImpl v : errors) { for (FormMessage m : v.errors) { if (!fields.contains(m.getField())) { + if (v.excludeOthers) { + fields.clear(); + messages.clear(); + } + fields.add(m.getField()); messages.add(m); + + if (v.excludeOthers) { + break; + } } } } diff --git a/services/src/main/java/org/keycloak/authentication/forms/RegistrationRecaptcha.java b/services/src/main/java/org/keycloak/authentication/forms/RegistrationRecaptcha.java index 28747e054f..8e65450ced 100755 --- a/services/src/main/java/org/keycloak/authentication/forms/RegistrationRecaptcha.java +++ b/services/src/main/java/org/keycloak/authentication/forms/RegistrationRecaptcha.java @@ -127,6 +127,7 @@ public class RegistrationRecaptcha implements FormAction, FormActionFactory, Con formData.remove(G_RECAPTCHA_RESPONSE); context.error(Errors.INVALID_REGISTRATION); context.validationError(formData, errors); + context.excludeOtherErrors(); return;