I have added a custom attribute in login-update-profile.ftl
named organization
, it is able to save the input from user into Keycloak.
<div class="${properties.kcFormGroupClass!}">
<div class="${properties.kcLabelWrapperClass!}">
<label for="user.attributes.organization" class="${properties.kcLabelClass!}">${msg("organization")}</label>
</div>
<div class="${properties.kcInputWrapperClass!}">
<div class="${properties.kcInputWrapperClass!}">
<input type="text" id="user.attributes.organization" name="user.attributes.organization" value="${(user.attributes.organization!'')}" class="${properties.kcInputClass!}" aria-invalid="<#if messagesPerField.existsError('organization')>true</#if>"
/>
</div>
<#if messagesPerField.existsError('organization')>
<span id="input-error-organization" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
${kcSanitize(messagesPerField.get('organization'))?no_esc}
</span>
</#if>
</div>
</div>
How to add validation for this field? I need to make it an obligatory field and meet certain condition (for example the length of the string). If the input is invalid, the error message is expected to be shown (like what we see in email or username field)
I found out the solution by creating a custom implementation of service provider Review Profile
in First Broker Login
flow. Here is the steps:
Review Profile
. At the time of writing this answer (keycloak v15.0.2), we need 3 files: AbstractIdpAuthenticator.java, IdpReviewProfileAuthenticatorFactory.java, and IdpReviewProfileAuthenticator.java.jar
using those filesIdpReviewProfileAuthenticator.java
and add this function: public List<FormMessage> getCustomAttributeError(String organization) {
List<FormMessage> errors = new ArrayList<>();
// You can add more conditions & parameters to be validated
if(Validation.isBlank(organization)){
errors.add(new FormMessage("organization", "missingOrganizationMessage"));
}
return errors;
}
actionImpl
function and add this lines between profile.update((attributeName, userModel)
and catch (ValidationException pve)
: if(getCustomAttributeError(profile.getAttributes().getFirstValue("organization")).size() > 0){
throw new ValidationException();
}
catch (ValidationException pve)
after List<FormMessage> errors
: List<FormMessage> extraErrors = getCustomAttributeErrors(profile.getAttributes().getFirstValue("organization"));
for(FormMessage error : extraErrors) {
errors.add(error);
}
IdpReviewProfileAuthenticatorFactory.java
go to getDisplayType()
function and change the return value into "Custom Review Profile"
.jar
, deploy it into keycloak, create a copy of First Broker Login
flow we name Custom First Broker Login
, and in Custom First Broker Login
we replace Review Profile
with Custom Review Profile
Custom Review Profile
by clicking its action button, give it an alias, and turn Update Profile on First Login
into on
Custom First Broker Login