I am following this guide and trying to create my custom registration flow in Keycloak using two forms and custom templates. Below I am providing the code of the authenticator factory for the first form. The second form uses the same code with the only changes that taking place are the PROVIDER_ID
, getDisplayType()
method and the return type of the render()
method which is form.createForm("register2.ftl");
. The Keycloak version I am using is 24.0.1.
I have:
providers
folder.ftl
template files into the themes
folderbin/kc.bat start-dev --debug
--debug
in order to expose the debug port and then use breakpoints in my applicationpublic class FirstCustomFormAuthenticatorFactory implements FormAuthenticatorFactory, FormAuthenticator {
private static final String PROVIDER_ID = "register-form1";
private static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
AuthenticationExecutionModel.Requirement.REQUIRED
};
@Override
public String getDisplayType() {
return "Registration Form 1";
}
@Override
public String getReferenceCategory() {
return "";
}
@Override
public boolean isConfigurable() {
return false;
}
@Override
public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
return REQUIREMENT_CHOICES;
}
@Override
public boolean isUserSetupAllowed() {
return false;
}
@Override
public String getHelpText() {
return "";
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return List.of();
}
@Override
public FormAuthenticator create(KeycloakSession keycloakSession) {
return this;
}
@Override
public void init(Config.Scope scope) {
}
@Override
public void postInit(KeycloakSessionFactory keycloakSessionFactory) {
}
@Override
public void close() {
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public Response render(FormContext context, LoginFormsProvider form) {
RegisterBean rb = new RegisterBean(new MultivaluedHashMap<>(), context.getSession());
form.setAttribute("register", rb);
return form.createForm("register.ftl");
}
}
Keycloak server starts without any errors. Afterwards:
When submitting the form I am getting the next error:
KC-SERVICES0013: Failed authentication: java.lang.NullPointerException: Cannot invoke "org.keycloak.authentication.FormAuthenticator.render(org.keycloak.authentication.FormContext, org.keycloak.forms.login.LoginFormsProvider)" because "this.formAuthenticator" is null
at org.keycloak.authentication.FormAuthenticationFlow.renderForm(FormAuthenticationFlow.java:307)
at org.keycloak.authentication.FormAuthenticationFlow.processFlow(FormAuthenticationFlow.java:285)
at org.keycloak.authentication.DefaultAuthenticationFlow.processSingleFlowExecutionModel(DefaultAuthenticationFlow.java:377)
at org.keycloak.authentication.DefaultAuthenticationFlow.processFlow(DefaultAuthenticationFlow.java:246)
at org.keycloak.authentication.DefaultAuthenticationFlow.processAction(DefaultAuthenticationFlow.java:133)
at org.keycloak.authentication.AuthenticationProcessor.authenticationAction(AuthenticationProcessor.java:987)
at org.keycloak.services.resources.LoginActionsService.processFlow(LoginActionsService.java:364)
at org.keycloak.services.resources.LoginActionsService.processRegistration(LoginActionsService.java:724)
at org.keycloak.services.resources.LoginActionsService.registerRequest(LoginActionsService.java:780)
at org.keycloak.services.resources.LoginActionsService.processRegister(LoginActionsService.java:758)
at org.keycloak.services.resources.LoginActionsService$quarkusrestinvoker$processRegister_707378c0de357d574c0a2e1d6056afe7606ab5ff.invoke(Unknown Source)
at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:582)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:857)
I am not entirely sure what's causing the issue, as seen in my logs. Do you have any suggestions aa what I am doing wrong?
I managed to fix my issue. For some reason the configuration properties that had to be set in my first registration form where not applied correctly. As soon as logged in the admin console, I had to do to my realm and then in the Authentication tab. I had to select my custom registration flow and go to settings of my first step.