Hello everyone,
I am trying to return a custom message for account temporarily disabled in keycloak. I have provided my classes below.
I also provided org.keycloak.authentication.AuthenticatorFactory file where I put the "CustomAuthenticatorFactory" class refrence in src/main/resources/META-INF/services directory.
Then created jar and put it to providers directory of keycloak.
My jar is executed and ran. I added the execution to a new browser flow and bind it to the flow but the overriden methods are not being called.
added custom message file in location: themes\adminlte\login\messages\messages_en.properties
and put message
"accountTemporarilyDisabledMessage=Account is temporarily disabled, contact admin or try again later". Later from admin console selected the theme. But nothing changed the response of "Invalid user credential" for temporarily disabed account.
Can you tell me where I am doing it wrong?
public class CustomAuthenticatorFactory implements AuthenticatorFactory {
public static final String PROVIDER_ID = "custom-authenticator";
private static final CustomAuthenticator SINGLETON = new CustomAuthenticator();
@Override
public String getDisplayType() {
return "Custom authenticator";
}
@Override
public String getReferenceCategory() {
return null;
}
@Override
public boolean isConfigurable() {
return false;
}
@Override
public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
return new AuthenticationExecutionModel.Requirement[] { AuthenticationExecutionModel.Requirement.REQUIRED };
}
@Override
public boolean isUserSetupAllowed() {
return false;
}
@Override
public String getHelpText() {
return null;
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return null;
}
@Override
public Authenticator create(KeycloakSession keycloakSession) {
return SINGLETON;
}
@Override
public void init(Config.Scope scope) {
}
@Override
public void postInit(KeycloakSessionFactory keycloakSessionFactory) {
}
@Override
public void close() {
}
@Override
public String getId() {
return PROVIDER_ID;
}
}
public class CustomAuthenticator extends UsernamePasswordForm {
private static final Logger logger = Logger.getLogger(CustomAuthenticator.class);
@Override
protected String disabledByBruteForceError() {
return Messages.ACCOUNT_TEMPORARILY_DISABLED;
}
@Override
public void authenticate(AuthenticationFlowContext context) {
logger.info("Some log to check if this method is invoked!!!!");
MultivaluedMap<String, String> formData = new MultivaluedMapImpl();
String loginHint = context.getAuthenticationSession().getClientNote("login_hint");
String rememberMeUsername = AuthenticationManager.getRememberMeUsername(context.getRealm(), context.getHttpRequest().getHttpHeaders());
if (context.getUser() != null) {
LoginFormsProvider form = context.form();
form.setAttribute("usernameHidden", true);
form.setAttribute("registrationDisabled", true);
context.getAuthenticationSession().setAuthNote("USER_SET_BEFORE_USERNAME_PASSWORD_AUTH", "true");
} else {
context.getAuthenticationSession().removeAuthNote("USER_SET_BEFORE_USERNAME_PASSWORD_AUTH");
if (loginHint != null || rememberMeUsername != null) {
if (loginHint != null) {
formData.add("username", loginHint);
} else {
formData.add("username", rememberMeUsername);
formData.add("rememberMe", "on");
}
}
}
Response challengeResponse = super.challenge(context, formData);
context.challenge(challengeResponse);
}
@Override
protected Response challenge(AuthenticationFlowContext context, String error, String field) {
logger.info("************** some log to check this method invoked ******************************");
LoginFormsProvider form = context.form().setExecution(context.getExecution().getId());
if (error != null) {
if (field != null) {
form.addError(new FormMessage(field, error));
} else {
form.setError(error, new Object[0]);
}
}
return super.createLoginForm(form);
}
}