DEV Community

David Wippel for TRIGO | We speak human and computer

Posted on • Originally published at trigodev.com

How to customize Keycloak themes

In this insight, you will learn how Keycloak Themes are structured and how to come up with your own custom theme.

Because we believe that learning is best done when putting everything into practices, we will start off by setting up a development environment. Right after, we will go over the types of themes and the folder structure. Closing with how to add customization and build your own Keycloak theme.

Before we get started with all the details, a quick recap of what Keycloak is and why we care about it.

What is Keycloak?

Keycloak is an open-source identity and access management or IAM solution, that can be used as a third-party authorization server to manage your web or mobile applications' authentication and authorization requirements.

It lifts the heavy weight of implementing a stable and secure user authorization and authentication, from the shoulders of developers.

At TRIGO, we use it for all of our projects. It saved tons of time and money. Kept us staying sane when integrating AuthN/AuthZ into an application. We love Keycloak.

Now let's dive right into it.

Setting up a development environment

You could either download Keycloak and run it natively on your machine, or spin up some container using docker or podman.

We at TRIGO are heavily into containerization. Therefore, we will use the second option for this tutorial.

To make things even simpler for you, we have prepared a fully functional setup as Git repository.

Before proceeding with this tutorial, please take your time to check out the repository and follow the instructions found in the README file. If you got any questions, please feel free to open an issue.

Theme types

With a single theme, you can provide one or more types of customization.

An overview:

Type Description Location of the demo repository
Common Files (resources) shared along all theme types themes/keycloak-provided-themes/keycloak/common
Account All things related to the Account management (self-service) area. themes/keycloak-provided-themes/base/account and themes/keycloak-provided-themes/keycloak.v2/account
Admin The admin console. Yes, the very extensive area can be customized too. themes/keycloak-provided-themes/base/admin and themes/keycloak-provided-themes/keycloak.v2/admin
Emails Everything you need to customize Emails sent by Keycloak themes/keycloak-provided-themes/base/email
Login User-facing public pages like login, password reset and so on. themes/keycloak-provided-themes/base/login and themes/keycloak-provided-themes/keycloak/login
Welcome The welcome page shown when spinning up Keycloak and opening its landing page themes/keycloak-provided-themes/keycloak/welcome

Hint: Instructions on how to configure a theme can be found in the Keycloak Documentation.

Structure of a theme folder

Every theme must consist of one or more type related subdirectories.

Image description

It's a 1:1 reference to the theme types mentioned above.

Structure of a theme type folder

Every theme type folder must have at least a theme.properties file. It contains basic instructions for Keycloak.

Furthermore, it consists of one or more of the following folders

Folder Description
messages Contains one or more messages_XX.properties files. They are part of the i18n mechanism of Keycloak
resources Every image, CSS or JavaScript file that is required to power the theme type is found here.

Note: The email type is a little different. It contains an HTML and text folder containing the email templates for HTML and text emails. All as FTL files.

Besides that, a theme type folder usually comes with many template files (.ftl file ending). They represent all the different pages Keycloak has.

All your base belongs to me. Theme Inheritance explained

You might have noticed that for most types, there are multiple places where you can find related files. That's because Keycloak themes are built with inheritance in mind. Everything is (or it can be) based on base (phun intended!). You could, theoretically, start from scratch, but we don't recommend that unless you have a special use case. It's just a lot of work to provide everything you need for a fully functional theme.

Theme type entry point: theme.properties

Let's have a look at the entry point of the login type.

Image description

This is from themes/keycloak-provided-themes/keycloak/login

The first line of theme.properties is:

parent=base
Enter fullscreen mode Exit fullscreen mode

With this, we instruct Keycloak to inherit our login type from the base theme. We can then focus on the things we like to change instead of starting from zero.

FTL - Faster than light or Freemarker

Freemarker is a template language like Pug, Mustache or EJS. If you are familiar with the primary template language of your ecosystem, you should be familiar with the core concepts of freemarker too.

I still recommend going through the “Template Author Guide”. The Keycloak Login Theme makes heavy use of the FTL inheritance features. So better be prepared to dig in deep.

Data Models for your templates

Keycloak uses numerous data models within their template files. They are - let just put it that way - not very well documented.

To get at least a basic understanding, these two files from the Keycloak Source Code are a good starting point:

For Theme Type: Login

https://github.com/keycloak/keycloak/blob/main/services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java
Enter fullscreen mode Exit fullscreen mode

For Theme Type: Account

https://github.com/keycloak/keycloak/blob/main/services/src/main/java/org/keycloak/forms/account/freemarker/FreeMarkerAccountProvider.java
Enter fullscreen mode Exit fullscreen mode

What other tech is included?

For the time of writing this insight, Keycloak 17 is the newest version available. There are announcements that the current angular1 based admin and account theme is replaced by a React-based solution anytime soon. Keycloak 15 already has an early version of that included. It can be found as keycloak.v2 theme here: themes/keycloak-provided-themes/keycloak.v2

The Login part of the theme uses an earlier version of the Patternfly Framework. Files:

themes/keycloak-provided-themes/keycloak/common/resources/web_modules/@patternfly
Enter fullscreen mode Exit fullscreen mode

Since there is no version information available, it's hard to tell which version of Patternfly it is, but all required resources are included.

v4 of Patternfly is a remarkable framework found here.

How to customize a theme type?

For all of you who, me included, are like: Ok Patternfly is cool and what not , but I want to bring my own stuff to the table. Tailwind, Vue, Svelte, Chakra, ... just a little more patience.

Before we explore how to create a custom theme with your favorite tech stack, I think it's important to understand the structure of the default theme.

For this tutorial, I will focus on the login theme type further on. I assume that that's the type most of you want to customize anyway. Also, when you understand that part of a theme, the e.g. account part is a piece of cake for you.

The first file you should examine closer is template.ftl. It contains the basic HTML page structure and all <#nested> instructions that are used in the various templates. It defines a macro that is used in pages like login, register, login-reset-password, …

Speaking of the different templates. A quick excursion on what files are the more relevant ones:

Login theme type most relevant templates

Folder Description
login.ftl Username/Password login
register.ftl User registration
login-reset-password.ftl Password Reset
login-update-password.ftl Password Update
login-otp.ftl OTP/2FA login
error.ftl Error page

Back to customizing the login theme type

Within the FTL templates various data-models are used as mentioned above. It's beyond the scope of this tutorial to explain every detail. I strongly recommend to set aside some time to go through ALL the files and explore how the various properties are used and for what purpose.

If you got any questions, please feel free to drop me an email at david@trigodev.com

CSS Classes confusion

Said that, there is one detail I like to explain a bit. How CSS classes are handled. It was a source of confusion for me when starting with Keycloak theme development. CSS Classes are set via properties that are defined in the theme.properties file of the login theme type.

Example:

Image description

I don't get the reason behind that decision. I guess the idea was to provide a way to customize the CSS classes in a central way. It was one of the first things I dropped when building the first themes for ourselves.

Included Messages for i18n

Let's assume you have added some new i18n message to one of the message_xx.properties files in the messages' folder. For example, some marketing information you want to include on the login page.

Freemarker provides a msg function to include i18n messages.

Note: It will refer to the language currently selected by the user. Keycloak uses Browser information to determine the language, but only if the language is configured.

Example:

${msg("doForgotPassword")}
Enter fullscreen mode Exit fullscreen mode

Some notes on security

All things you know about web security are relevant for Keycloak themes too. Keep in mind that you are basically building a website (or web application for the account/admin theme type).

Therefore, just a few short notes on security:

Sanitizing all user-generated content

Keycloak provides a kcSanitize function to sanitize HTML content. I highly recommend using that function when including user provided HTML content in any way.

Example:

${kcSanitize(message.summary)?no_esc}
Enter fullscreen mode Exit fullscreen mode

Code found here.

CSRF Protection

According to the OAUTH2 Specification, CSRF Protection is done via a state query parameter. Keycloak handles that for us via the url.loginAction property used as form action

<form id="kc-form-login" onsubmit="login.disabled = true; return true;" action="${url.loginAction}" method="post">
Enter fullscreen mode Exit fullscreen mode

Don't change that unless you know exactly what you are doing here.

A more detailed explanation on how the state parameter helps to prevent CSRF attacks can be found here.

Bring your own stuff

As you might have guessed, besides learning all the details about the tech stack involved and some innards about the data-model used, there is nothing special to a Keycloak theme. It's just web development. So, why not bring your well-known framework of choice to the table? The good news is that, there is no reason not to go down that road.

In fact, we do that by using Tailwind to style our themes.

I've included an example to the Git Repository. You are welcome to use that as a starting point (see themes folder).

Note: The themes are mapped into the docker-compose.yml to make them visible to Keycloak. You have to add your own theme to that by duplicating and adopt this line in the docker-compose.yml

./themes/tailwind-example/:/opt/jboss/keycloak/themes/tailwind-example/
Enter fullscreen mode Exit fullscreen mode

Recap

We have learned how Keycloak themes are structured, what files are important, how inheritance works for themes and how to get started with custom themes.

I've tried to add as many lessons learned as possible. If anything isn't super clear or missing, please point that out.

Again, if you got any questions, please reach out to me.

Top comments (1)

Collapse
 
macagua profile image
Leonardo J. Caballero G.

Here is the "tailwind-example" theme Github repository github.com/trigo-at/keycloak-theme...