hi.
i created a simple custom provider
public class CustomAuthenticator implements Authenticator {
@Override
public void authenticate(AuthenticationFlowContext context) {
MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
String username = formData.getFirst("username");
String password = formData.getFirst("password");
UserModel user = FindUser(context, username); //stub, here we are actually looking for a user in keycloak itself
context.setUser(user);
context.success();
}
}
the problem is that when I add this custom provider to the browser flow, the call does not reach it. Because the Username Password Form step searches for a user inside keycloak and if it does not find it, it terminates the flow with an error “Invalid username or password.”
My search led me to the fact that it is possible to integrate into the login password verification form by implementing:
org.keycloak.authentication.FormAction: MyFormAction.CustomFormAuthenticatorFactory
public class CustomFormAuthenticatorFactory implements FormActionFactory {
private static final String PROVIDER_ID = "custom-form-authenticator";
public CustomFormAuthenticatorFactory() {
System.out.println("CustomFormAuthenticatorFactory initialized!");
}
@Override
public String getDisplayType() {
return "Custom Password Validator";
}
@Override
public String getReferenceCategory() {
return null;
}
@Override
public boolean isConfigurable() {
return false;
}
@Override
public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
return new AuthenticationExecutionModel.Requirement[]{
AuthenticationExecutionModel.Requirement.REQUIRED,
AuthenticationExecutionModel.Requirement.DISABLED
};
}
@Override
public String getHelpText() {
return "";
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return Collections.emptyList();
}
@Override
public FormAction create(KeycloakSession session) {
return new CustomFormAuthenticator();
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public boolean isUserSetupAllowed() {
return false;
}
@Override
public void init(org.keycloak.Config.Scope config) {
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
@Override
public void close() {
}
}
public class CustomFormAuthenticator implements FormAction {
@Override
public void buildPage(FormContext context, LoginFormsProvider form) {
}
@Override
public void validate(ValidationContext context) {
MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
String username = formData.getFirst("username");
String password = formData.getFirst("password");
context.success();
}
@Override
public void success(FormContext context) {
}
@Override
public boolean requiresUser() {
return false;
}
@Override
public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
return true;
}
@Override
public void setRequiredActions(KeycloakSession keycloakSession, RealmModel realmModel, UserModel userModel) {
}
@Override
public void close() {
}
}
However, after I register this provider, I don’t understand how to integrate it into the login and password check form.
My ultimate goal is to implement user verification in my system and also create a JWT token with a few extra fields.