diff --git a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.4.0.xml b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.4.0.xml index f5f01954d9..80b246071a 100755 --- a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.4.0.xml +++ b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.4.0.xml @@ -22,6 +22,9 @@ + + + diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties index f5d211089f..4fe6ab3fcf 100755 --- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties +++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties @@ -13,7 +13,8 @@ kerberosNotConfigured=Kerberos Not Configured kerberosNotConfiguredTitle=Kerberos Not Configured bypassKerberos=Your browser is not set up for Kerberos login. Please click continue to login in through other means kerberosNotSetUp=Kerberos is not set up. You cannot login. -recaptchaFailed=Recaptcha Failed +recaptchaFailed=Invalid Recaptcha +recaptchaNotConfigured=Recaptcha is required, but not configured registerWithTitle=Registrierung bei {0} registerWithTitleHtml=Registrierung bei {0} diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties index a89272267c..3fdb91c48f 100755 --- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties +++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties @@ -30,7 +30,8 @@ codeSuccessTitle=Success code codeErrorTitle=Error code\: {0} termsTitle=Terms and Conditions termsTitleHtml=Terms and Conditions -recaptchaFailed=Recaptcha Failed +recaptchaFailed=Invalid Recaptcha +recaptchaNotConfigured=Recaptcha is required, but not configured noAccount=New user? username=Username diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_it.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_it.properties index 43d6ab4b2d..b239ecc31a 100755 --- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_it.properties +++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_it.properties @@ -13,7 +13,8 @@ bypassKerberos=Your browser is not set up for Kerberos login. Please click cont kerberosNotSetUp=Kerberos is not set up. You cannot login. kerberosNotConfigured=Kerberos Not Configured kerberosNotConfiguredTitle=Kerberos Not Configured -recaptchaFailed=Recaptcha Failed +recaptchaFailed=Invalid Recaptcha +recaptchaNotConfigured=Recaptcha is required, but not configured registerWithTitle=Registrati come {0} registerWithTitleHtml=Registrati come {0} diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_pt_BR.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_pt_BR.properties index 495480fea3..85b28fd553 100755 --- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_pt_BR.properties +++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_pt_BR.properties @@ -13,7 +13,8 @@ bypassKerberos=Your browser is not set up for Kerberos login. Please click cont kerberosNotSetUp=Kerberos is not set up. You cannot login. kerberosNotConfigured=Kerberos Not Configured kerberosNotConfiguredTitle=Kerberos Not Configured -recaptchaFailed=Recaptcha Failed +recaptchaFailed=Invalid Recaptcha +recaptchaNotConfigured=Recaptcha is required, but not configured registerWithTitle=Registre-se com {0} registerWithTitleHtml=Registre-se com {0} diff --git a/model/api/src/main/java/org/keycloak/models/entities/AuthenticationExecutionEntity.java b/model/api/src/main/java/org/keycloak/models/entities/AuthenticationExecutionEntity.java index 123e6258a5..d4b21ee4ae 100755 --- a/model/api/src/main/java/org/keycloak/models/entities/AuthenticationExecutionEntity.java +++ b/model/api/src/main/java/org/keycloak/models/entities/AuthenticationExecutionEntity.java @@ -10,6 +10,7 @@ import org.keycloak.models.AuthenticationExecutionModel; public class AuthenticationExecutionEntity { protected String id; protected String authenticator; + private String authenticatorConfig; protected String flowId; protected AuthenticationExecutionModel.Requirement requirement; protected int priority; @@ -80,4 +81,12 @@ public class AuthenticationExecutionEntity { public void setFlowId(String flowId) { this.flowId = flowId; } + + public String getAuthenticatorConfig() { + return authenticatorConfig; + } + + public void setAuthenticatorConfig(String authenticatorConfig) { + this.authenticatorConfig = authenticatorConfig; + } } diff --git a/model/api/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java b/model/api/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java index 3909efb65b..dc7a44ae85 100755 --- a/model/api/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java +++ b/model/api/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java @@ -2,8 +2,12 @@ package org.keycloak.models.utils; import org.keycloak.models.AuthenticationExecutionModel; import org.keycloak.models.AuthenticationFlowModel; +import org.keycloak.models.AuthenticatorConfigModel; import org.keycloak.models.RealmModel; +import java.util.HashMap; +import java.util.Map; + /** * @author Bill Burke * @version $Revision: 1 $ @@ -73,6 +77,13 @@ public class DefaultAuthenticationFlows { execution.setAutheticatorFlow(false); realm.addAuthenticatorExecution(execution); + //AuthenticatorConfigModel captchaConfig = new AuthenticatorConfigModel(); + //captchaConfig.setAlias("Recaptcha Config"); + //Map config = new HashMap<>(); + //config.put("site.key", "6LcFEAkTAAAAAOaY-5RJk3zIYw4AalNtqfac27Bn"); + //config.put("secret", "6LcFEAkTAAAAAM0SErEs9NlfhYpOTRj_vOVJSAMI"); + //captchaConfig.setConfig(config); + //captchaConfig = realm.addAuthenticatorConfig(captchaConfig); execution = new AuthenticationExecutionModel(); execution.setParentFlow(registrationFormFlow.getId()); execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED); @@ -80,6 +91,7 @@ public class DefaultAuthenticationFlows { execution.setPriority(60); execution.setUserSetupAllowed(false); execution.setAutheticatorFlow(false); + //execution.setAuthenticatorConfig(captchaConfig.getId()); realm.addAuthenticatorExecution(execution); diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java index 7df3f6ff13..45f3c095f0 100755 --- a/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java +++ b/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java @@ -1308,6 +1308,7 @@ public class RealmAdapter implements RealmModel { model.setParentFlow(entity.getParentFlow()); model.setFlowId(entity.getFlowId()); model.setAutheticatorFlow(entity.isAuthenticatorFlow()); + model.setAuthenticatorConfig(entity.getAuthenticatorConfig()); return model; } @@ -1339,6 +1340,7 @@ public class RealmAdapter implements RealmModel { entity.setUserSetupAllowed(model.isUserSetupAllowed()); entity.setAuthenticatorFlow(model.isAutheticatorFlow()); entity.setFlowId(model.getFlowId()); + entity.setAuthenticatorConfig(model.getAuthenticatorConfig()); AuthenticationFlowEntity flow = getFlowEntity(model.getId()); flow.getExecutions().add(entity); model.setId(entity.getId()); @@ -1362,6 +1364,7 @@ public class RealmAdapter implements RealmModel { entity.setRequirement(model.getRequirement()); entity.setFlowId(model.getFlowId()); entity.setUserSetupAllowed(model.isUserSetupAllowed()); + entity.setAuthenticatorConfig(model.getAuthenticatorConfig()); } @Override diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java index eec43ba82a..5ccf6c1f0f 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java @@ -1613,6 +1613,7 @@ public class RealmAdapter implements RealmModel { model.setFlowId(entity.getFlowId()); model.setParentFlow(entity.getParentFlow().getId()); model.setAutheticatorFlow(entity.isAutheticatorFlow()); + model.setAuthenticatorConfig(entity.getAuthenticatorConfig()); return model; } @@ -1631,6 +1632,7 @@ public class RealmAdapter implements RealmModel { entity.setPriority(model.getPriority()); entity.setFlowId(model.getFlowId()); entity.setRequirement(model.getRequirement()); + entity.setAuthenticatorConfig(model.getAuthenticatorConfig()); AuthenticationFlowEntity flow = em.find(AuthenticationFlowEntity.class, model.getParentFlow()); entity.setParentFlow(flow); flow.getExecutions().add(entity); @@ -1653,6 +1655,7 @@ public class RealmAdapter implements RealmModel { entity.setPriority(model.getPriority()); entity.setRequirement(model.getRequirement()); entity.setUserSetupAllowed(model.isUserSetupAllowed()); + entity.setAuthenticatorConfig(model.getAuthenticatorConfig()); entity.setFlowId(model.getFlowId()); em.flush(); } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationExecutionEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationExecutionEntity.java index b27659f445..c5e9019960 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationExecutionEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationExecutionEntity.java @@ -39,6 +39,9 @@ public class AuthenticationExecutionEntity { @Column(name="AUTHENTICATOR") protected String authenticator; + @Column(name="AUTH_CONFIG") + protected String authenticatorConfig; + @Column(name="AUTH_FLOW_ID") protected String flowId; @@ -125,4 +128,12 @@ public class AuthenticationExecutionEntity { public void setFlowId(String flowId) { this.flowId = flowId; } + + public String getAuthenticatorConfig() { + return authenticatorConfig; + } + + public void setAuthenticatorConfig(String authenticatorConfig) { + this.authenticatorConfig = authenticatorConfig; + } } diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java index 935746efe5..cb5cab9c68 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java @@ -1383,6 +1383,7 @@ public class RealmAdapter extends AbstractMongoAdapter impleme model.setFlowId(entity.getFlowId()); model.setParentFlow(entity.getParentFlow()); model.setAutheticatorFlow(entity.isAuthenticatorFlow()); + model.setAuthenticatorConfig(entity.getAuthenticatorConfig()); return model; } @@ -1415,6 +1416,7 @@ public class RealmAdapter extends AbstractMongoAdapter impleme entity.setAuthenticatorFlow(model.isAutheticatorFlow()); entity.setFlowId(model.getFlowId()); entity.setParentFlow(model.getParentFlow()); + entity.setAuthenticatorConfig(model.getAuthenticatorConfig()); AuthenticationFlowEntity flow = getFlowEntity(model.getParentFlow()); flow.getExecutions().add(entity); updateMongoEntity(); @@ -1439,6 +1441,7 @@ public class RealmAdapter extends AbstractMongoAdapter impleme entity.setRequirement(model.getRequirement()); entity.setFlowId(model.getFlowId()); entity.setUserSetupAllowed(model.isUserSetupAllowed()); + entity.setAuthenticatorConfig(model.getAuthenticatorConfig()); updateMongoEntity(); } 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 4236a1342f..95e75e9112 100755 --- a/services/src/main/java/org/keycloak/authentication/forms/RegistrationRecaptcha.java +++ b/services/src/main/java/org/keycloak/authentication/forms/RegistrationRecaptcha.java @@ -17,6 +17,7 @@ import org.keycloak.events.Details; import org.keycloak.events.Errors; import org.keycloak.login.LoginFormsProvider; import org.keycloak.models.AuthenticationExecutionModel; +import org.keycloak.models.AuthenticatorConfigModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.RealmModel; @@ -66,8 +67,17 @@ public class RegistrationRecaptcha implements FormAction, FormActionFactory { @Override public void buildPage(FormContext context, LoginFormsProvider form) { + AuthenticatorConfigModel captchaConfig = context.getAuthenticatorConfig(); + if (captchaConfig == null || captchaConfig.getConfig() == null + || captchaConfig.getConfig().get("site.key") == null + || captchaConfig.getConfig().get("secret") == null + ) { + form.addError(new FormMessage(null, Messages.RECAPTCHA_NOT_CONFIGURED)); + return; + } + String siteKey = captchaConfig.getConfig().get("site.key"); form.setAttribute("recaptchaRequired", true); - form.setAttribute("recaptchaSiteKey", "6LcFEAkTAAAAAOaY-5RJk3zIYw4AalNtqfac27Bn"); + form.setAttribute("recaptchaSiteKey", siteKey); List scripts = new LinkedList<>(); scripts.add("https://www.google.com/recaptcha/api.js"); form.setAttribute("scripts", scripts); @@ -81,12 +91,14 @@ public class RegistrationRecaptcha implements FormAction, FormActionFactory { context.getEvent().detail(Details.REGISTER_METHOD, "form"); String captcha = formData.getFirst(G_RECAPTCHA_RESPONSE); - if (Validation.isBlank(captcha)) { + if (!Validation.isBlank(captcha)) { + AuthenticatorConfigModel captchaConfig = context.getAuthenticatorConfig(); + String secret = captchaConfig.getConfig().get("secret"); HttpClient httpClient = context.getSession().getProvider(HttpClientProvider.class).getHttpClient(); HttpPost post = new HttpPost("https://www.google.com/recaptcha/api/siteverify"); - List formparams = new ArrayList(); - formparams.add(new BasicNameValuePair("secret", "6LcFEAkTAAAAAM0SErEs9NlfhYpOTRj_vOVJSAMI")); + List formparams = new LinkedList<>(); + formparams.add(new BasicNameValuePair("secret", secret)); formparams.add(new BasicNameValuePair("response", captcha)); formparams.add(new BasicNameValuePair("remoteip", context.getConnection().getRemoteAddr())); try { @@ -108,11 +120,7 @@ public class RegistrationRecaptcha implements FormAction, FormActionFactory { if (success) { context.success(); } else { - String usernameField = RegistrationPage.FIELD_USERNAME; - if (context.getRealm().isRegistrationEmailAsUsername()) { - usernameField = RegistrationPage.FIELD_EMAIL; - } - errors.add(new FormMessage(usernameField, Messages.RECAPTCHA_FAILED)); + errors.add(new FormMessage(null, Messages.RECAPTCHA_FAILED)); formData.remove(G_RECAPTCHA_RESPONSE); context.getEvent().error(Errors.INVALID_REGISTRATION); context.validationError(formData, errors); diff --git a/services/src/main/java/org/keycloak/services/messages/Messages.java b/services/src/main/java/org/keycloak/services/messages/Messages.java index 8df839c865..e9b7fa0304 100755 --- a/services/src/main/java/org/keycloak/services/messages/Messages.java +++ b/services/src/main/java/org/keycloak/services/messages/Messages.java @@ -58,6 +58,7 @@ public class Messages { public static final String USERNAME_EXISTS = "usernameExistsMessage"; public static final String RECAPTCHA_FAILED = "recaptchaFailed"; + public static final String RECAPTCHA_NOT_CONFIGURED = "recaptchaNotConfigured"; public static final String EMAIL_EXISTS = "emailExistsMessage";