Hi, I´m trying integrate recaptcha with keycloak for login, but i’m getting this error when i do the login action
keycloak | 2024-05-10 17:29:16,474 WARN [org.keycloak.services] (executor-thread-17) KC-SERVICES0013: Failed authentication: java.lang.NullPointerException: Cannot invoke “org.keycloak.authentication.FlowStatus.ordinal()” because “status” is null
keycloak | at org.keycloak.authentication.DefaultAuthenticationFlow.processResult(DefaultAuthenticationFlow.java:484)
keycloak | at org.keycloak.authentication.DefaultAuthenticationFlow.processAction(DefaultAuthenticationFlow.java:155)
keycloak | at org.keycloak.authentication.AuthenticationProcessor.authenticationAction(AuthenticationProcessor.java:988)
keycloak | at org.keycloak.services.resources.LoginActionsService.processFlow(LoginActionsService.java:362)
keycloak | at org.keycloak.services.resources.LoginActionsService.processAuthentication(LoginActionsService.java:333)
keycloak | at org.keycloak.services.resources.LoginActionsService.authenticate(LoginActionsService.java:325)
keycloak | at org.keycloak.services.resources.LoginActionsService.authenticateForm(LoginActionsService.java:390)
keycloak | at org.keycloak.services.resources.LoginActionsService$quarkusrestinvoker$authenticateForm_32b8e198ac3110abd1d5774e83a4cf87858129f4.invoke(Unknown Source)
keycloak | at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
keycloak | at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
keycloak | at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:145)
keycloak | at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
keycloak | at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
keycloak | at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
keycloak | at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
keycloak | at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
keycloak | at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
keycloak | at java.base/java.lang.Thread.run(Thread.java:840)
Hier is my login scream, the recaptcha appears, but when i click in log in this error occurs
Hier is my Authenticator
public class RecaptchaUsernamePasswordForm extends UsernamePasswordForm implements Authenticator {
public static final String G_RECAPTCHA_RESPONSE = "g-recaptcha-response";
public static final String RECAPTCHA_REFERENCE_CATEGORY = "recaptcha";
public static final String SITE_KEY = "site.key";
public static final String SITE_SECRET = "secret";
private static final Logger logger = Logger.getLogger(RecaptchaUsernamePasswordForm.class);
private String defaultSiteKey;
private String defaultServerKey;
@Override
public void authenticate(AuthenticationFlowContext context) {
context.getEvent()
.detail(Details.AUTH_METHOD, "auth_method");
if (logger.isInfoEnabled()) {
logger.info(
"validateRecaptcha(AuthenticationFlowContext, boolean, String, String) - Before the validation");
}
AuthenticatorConfigModel captchaConfig = context.getAuthenticatorConfig();
LoginFormsProvider form = context.form();
String userLanguageTag = context.getSession()
.getContext()
.resolveLocale(context.getUser())
.toLanguageTag();
if (StringUtil.isNotBlank(defaultServerKey) && StringUtil.isNotBlank(defaultSiteKey)) {
form.setAttribute("recaptchaSiteKey", defaultSiteKey);
} else if (captchaConfig == null || captchaConfig.getConfig() == null || captchaConfig.getConfig()
.get(SITE_KEY) == null || captchaConfig.getConfig()
.get(SITE_SECRET) == null) {
form.addError(new FormMessage(null, Messages.RECAPTCHA_NOT_CONFIGURED));
return;
} else{
String siteKey = captchaConfig.getConfig()
.get(SITE_KEY);
form.setAttribute("recaptchaSiteKey", siteKey);
}
form.setAttribute("recaptchaRequired", true);
form.addScript("https://www.google.com/recaptcha/api.js?hl=" + userLanguageTag);
super.authenticate(context);
}
}
and my Factory
public class RecaptchaUsernamePasswordFormFactory extends UsernamePasswordFormFactory implements AuthenticatorFactory {
public static final String PROVIDER_ID = "recaptcha-form";
public static final RecaptchaUsernamePasswordForm SINGLETON = new RecaptchaUsernamePasswordForm();
private static final Logger logger = Logger.getLogger(RecaptchaUsernamePasswordFormFactory.class);
private String siteKey;
private String serverKey;
@Override
public void init(Config.Scope config) {
this.siteKey = config.get("siteKey");
this.serverKey = config.get("serverKey");
SINGLETON.setEnvironment(siteKey, serverKey);
}
@Override
public Authenticator create(KeycloakSession session) {
return SINGLETON;
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
@Override
public void close() {
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String getReferenceCategory() {
return UserCredentialModel.PASSWORD;
}
@Override
public boolean isConfigurable() {
return true;
}
public static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
AuthenticationExecutionModel.Requirement.REQUIRED };
@Override
public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
return REQUIREMENT_CHOICES;
}
@Override
public String getDisplayType() {
return "Recaptcha Username Password Form";
}
@Override
public String getHelpText() {
return "Validates a username and password from login form + google recaptcha";
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return null;
}
@Override
public boolean isUserSetupAllowed() {
return false;
}
}