Hello!
I’m novice in keycloak. Sorry if I ask stupid question
I have an existing application. In this app each user has several companies (user has one login/pass for all his companies). When user login it needs to enter three fields LOGIN/COMPANY_LOGIN/PASS to enter to the necessary company. Customer don’t want to use the second login page, like in example with secretQuestion (Server Developer Guide).
1)Is it possible to override logic to use custom login page with three fields?
I downloaded keycloak code, but cant find controller method with URI /auth. I suppose that if I read code from the beginning (/auth) I’ll understand flow.
You’ll have to create a custom Authenticator like the UsernamePasswordForm (keycloak/UsernamePasswordForm.java at master · keycloak/keycloak · GitHub) that takes your three fields and validates them. The “secret question” example you cited gives you information on how you can build and deploy a custom Authenticator.
Then using maven comands clean/compile/install i got keycloak-authenticator-1.0-SNAPSHOT.jar
I started keycloak server locally and put .jar file into directory keycloak-12.0.4\standalone\deployments.
And got:
ERROR [org.jboss.as.controller.management-operation] (DeploymentScanner-threads - 1) WFLYCTL0013: Operation (“deploy”) failed - address: ([(“deployment” => “keycloak-authenticator-1.0-SNAPSHOT.jar”)]) - failure description: {“WFLYCTL0080: Failed services” => {“jboss.deployment.unit.“keycloak-authenticator-1.0-SNAPSHOT.jar”.POST_MODULE” => “WFLYSRV0153: Failed to process phase POST_MODULE of deployment “keycloak-authenticator-1.0-SNAPSHOT.jar”
Caused by: java.util.ServiceConfigurationError: org.keycloak.authentication.AuthenticatorFactory: Provider com.sid.keycloakauthenticator.UsernameCompanyPasswordFormFactory could not be instantiated
Caused by: java.lang.NoClassDefFoundError: Failed to link com/sid/keycloakauthenticator/UsernameCompanyPasswordForm (Module “deployment.keycloak-authenticator-1.0-SNAPSHOT.jar” from Service Module Loader): org/keycloak/authentication/authenticators/browser/UsernamePasswordForm”}}
16:57:39,625 INFO [org.jboss.as.server] (DeploymentScanner-threads - 1) WFLYSRV0010: Deployed “keycloak-authenticator-1.0-SNAPSHOT.jar” (runtime-name : “keycloak-authenticator-1.0-SNAPSHOT.jar”)
16:57:39,626 INFO [org.jboss.as.controller] (DeploymentScanner-threads - 1) WFLYCTL0183: Service status report
WFLYCTL0186: Services which failed to start: service jboss.deployment.unit.“keycloak-authenticator-1.0-SNAPSHOT.jar”.POST_MODULE: WFLYSRV0153: Failed to process phase POST_MODULE of deployment “keycloak-authenticator-1.0-SNAPSHOT.jar”
I excluded ‘UsernamePasswordForm’ form ‘public class UsernameCompanyPasswordForm extends UsernamePasswordForm implements Authenticator’. So it looks like ‘public class UsernameCompanyPasswordForm implements Authenticator’.
Copied to ‘UsernameCompanyPasswordForm’ all methods from ‘AbstractUsernameFormAuthenticator’ (with body). Not good but I got .jar.deployed
I added this code to login.ftl (deleted first unsafe string)
You now need to update your Authentication flow with your new form. See Server Administration Guide for more information. The easiest way is usually just to copy the “Browser” flow and then update it with your form.
Without knowing exactly what you’ve implemented in your UsernameCompanyPasswordForm I can’t say exactly how you cause the login.ftl to be rendered. If you didn’t change how the existing class loads the template, and you’ve selected the theme you created, you might not have to do anything to get it to render your login.ftl.
I will ask by the other way. How (where) login.ftl connects with “UsernamePasswordForm”?
As I understand it use:
public static final String PROVIDER_ID = “auth-username-password-form”;
But I can’t find where this two files connect?
I did manipulations with Authentication flow added “Copy of browser” and found overriding string in this method “getDisplayType()” at Provider list.
And I made .ftl page that looks like on the picture.
if you follow this line in UsernamePasswordForm you’ll eventually get to where it uses the login.ftl template.
return forms.createLoginUsernamePassword();
Have you created a custom login theme with your login.ftl template? If you have, then you should only need to seelct your theme in the Realm Settings, and the UsernamePasswordForm you have built should automatically use your login.ftl assuming you are still calling the return forms.createLoginUsernamePassword() at the end of your challenge method. This is the way I would recommend it, as calling that does a lot of necessary setup to the template scope in order to render the .ftl properly.