Keycloak custom fields validation

Standard
Spread the love

Keycloak is without a doubt most feature rich product when it comes to Enterprise security implementation. Recently I had to add custom fields in the Keycloak signup form with a set of rules to validate the data. To my surprise, the implementation was pretty easy. Keycloak out of the box supports customization and validation of forms with the help of FormAction and FormActionFactory.

This article extends the feature of adding custom attributes to signup form. We will learn how to implement validation for the custom fields.

Java Project

Create a Java project with Maven a build tool. The quickest way is to use maven CLI to generate one. Refer following command

mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4

If you have maven on PATH environment variable above command should work and it will prompt you for project details. Enter group id (com.carbonrider.keycloak), artifact id(form-extension), package name (com.carbonrider.keycloak), version(1.0-SNAPSHOT), etc and a skeleton will be generated. The generated folder structure should look like following

Maven Dependency

To use Keycloak interfaces or APIs we must add the appropriate dependencies to pom.xml. First, add a property to properties tag and also change maven.compiler.source and maven.compiler.target to 1.8. Refer to the following snippet


<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<keycloak.version>4.8.3.Final</keycloak.version>
</properties>

Next, you should add keycloak dependency to dependencies section.


<dependencies>
  <dependency>
  	<groupId>junit</groupId>
  	<artifactId>junit</artifactId>
  	<version>4.11</version>
  	<scope>test</scope>
  </dependency>
  <dependency>
  	<groupId>org.keycloak</groupId>
  	<artifactId>keycloak-core</artifactId>
  	<version>${keycloak.version}</version>
  	<scope>provided</scope>
  </dependency>
  <dependency>
  	<groupId>org.keycloak</groupId>
  	<artifactId>keycloak-server-spi</artifactId>
  	<version>${keycloak.version}</version>
  	<scope>provided</scope>
  </dependency>
  <dependency>
  	<groupId>org.keycloak</groupId>
  	<artifactId>keycloak-services</artifactId>
  	<version>${keycloak.version}</version>
  	<scope>provided</scope>
  </dependency>
  <dependency>
  	<groupId>org.keycloak</groupId>
  	<artifactId>keycloak-server-spi-private</artifactId>
  	<version>${keycloak.version}</version>
  	<scope>provided</scope>
  </dependency>


  <dependency>
  	<groupId>org.jboss.spec.javax.transaction</groupId>
  	<artifactId>jboss-transaction-api_1.2_spec</artifactId>
  	<scope>provided</scope>
  	<version>${jboss-transaction-api_1.2_spec}</version>
  </dependency>
  <dependency>
  	<groupId>org.jboss.resteasy</groupId>
  	<artifactId>resteasy-jaxrs</artifactId>
  	<scope>provided</scope>
  	<version>${resteasy.version}</version>
  </dependency>
  <dependency>
  	<groupId>org.bouncycastle</groupId>
  	<artifactId>bcprov-jdk15on</artifactId>
  	<scope>provided</scope>
  	<version>${bouncycastle.version}</version>
  </dependency>
  <dependency>
  	<groupId>org.bouncycastle</groupId>
  	<artifactId>bcpkix-jdk15on</artifactId>
  	<scope>provided</scope>
  	<version>${bouncycastle.version}</version>
  </dependency>
  <dependency>
  	<groupId>org.jboss.logging</groupId>
  	<artifactId>jboss-logging</artifactId>
  	<scope>provided</scope>
  	<version>${jboss.logging.version}</version>
  </dependency>
  <dependency>
  	<groupId>org.apache.httpcomponents</groupId>
  	<artifactId>httpclient</artifactId>
  	<scope>provided</scope>
  	<version>${apache.httpcomponents.version}</version>
  </dependency>
</dependencies>

Note that the keycloak.version is referenced from the property that we have defined earlier. Import the project into Eclipse (or IDE of your choice) and then make sure the IDE has imported all the required dependencies.

FormAction

Assuming that the Eclipse project is in stable state, we should proceed with creation of FormAction class. Create a new class inside a package ‘com.carbonrider.keycloak.form’ as ‘SignupFormAction’.

Also import FormAction and FormActionFactory interfaces. Refer below screenshot for details.

FormAction interface is quite interesting. It gives you the ability to customize the form when it is being generated. The callback methods are invoked, which can be used to set attributes to customize form. Recaptcha is an example of FormAction implementation.

Default Implementation

Well, in our case we will be using FormAction to add the validation to the custom form.

To begin with add two constants to SignupFormAction


private static final String PROVIDER_ID = "signup-field-validation-action";

private static Requirement[] REQUIREMENT_CHOICES = { Requirement.REQUIRED, Requirement.DISABLED };

The first constant assigns Unique ID for our Form action, while the second constant indicates that the action can be marked as required or disabled. You can make it optional too. Make sure that you return the id from getId method. Also, the REQUIREMENT_CHOICES should be returned from getRequirementChoices method.

Return a meaningful text from getDisplayType and getHelpText method. The text will be displayed while configuring form action in admin panel.

Validation

Let me skip a few methods and quickly jump to Validation. The validation for the form can be applied using the validate method. Refer below snippet


MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
	List<FormMessage> errors = new ArrayList<>();
	String eventError = Errors.INVALID_REGISTRATION;

You can refer to the http request parameters using the context object. The context object is very useful and provides lot of details about the execution environment (realm, client details etc). You can customize the logic based on your application requirements.

Next we add the logic to check whether the custom fields have valid values.


	if (isBlank(formData.getFirst("user.attributes.aliasName"))) {
	  errors.add(new FormMessage("user.attributes.aliasName", "missingAliasNameMessage"));
	}

	if (isBlank(formData.getFirst("user.attributes.twitterURL"))) {
	  errors.add(new FormMessage("user.attributes.twitterURL", "missingTwitterURLMessage"));
	}

In the above code snippet, we are just checking if the values are blank. If so, an error message is added to the collection. Note the first argument is the name of the field while the second argument is a key in properties file containing an error message. The property file is present in the current theme that you have selected and should be available at THEME_NAME\login\messages\messages_en.properties. Add the above properties and an appropriate message will be displayed at runtime.

Building JAR and deployment

Since the validation logic is complete, we must deploy it in keycloak to bring it in action. Refer to below steps

  • Execute `mvn package` command to build the jar. The JAR must avoid bundling packages that come with Keycloak. You will notice that most of the dependencies in our pom.xml are marked as provided.
  • Copy the generated JAR file to KEYCLOAK_INSTALLATION_FOLDER\standalone\deployments
  • Make sure that you have copied or updated the properties file in Keycloak Themes. The Theme (customized) folder must be placed in KEYCLOAK_INSTALLATION_FOLDER\themes. If you are using pre-configured themes, make sure that the appropriate file is updated.
  • Restart Keycloak server to take the effect of newly deployed JAR.

Form Action Configuration

This is the final configuration and it is pretty easy. Login to Keycloak admin website and select the appropriate Realm for which you wish to apply the FormAction.

  • Click Authentication menu from the left sidebar.
  • In the Flows tab, select the Appropriate Flow for which the action has to be configured. The multiple AuthTypes will be listed in the grid below the flows.
  • From the context menu “Actions” of Registration Form, select “Add Execution”.
  • You should now see a dropdown with a list of providers. Select the Signup form action that we just developed and save the configuration.

Hurray!!! we are all done. Your Sign up form should be able to validate custom fields and display appropriate error messages. The source code for custom form action is available at – https://github.com/carbonrider/keycloak_form_action

One thought on “Keycloak custom fields validation

  1. Phillip

    Hey I am trying this for keycloak 7.0.0. I did everything that you said here but I don’t see the context menu you are talking about in the Form Action Configuration section.

Leave a Reply

Your email address will not be published. Required fields are marked *