Categories
Apache Browser Keycloak Linux SSO Ubuntu Webserver

Keycloak theming with minimal effort

I’ve been using Keycloak for quite some time now, and I was looking forward to the new 26.4.0 release – now with official passkey support.

Till now I was experimenting with edumfa (a clone of privacyIDEA) in order to get my Yubikey supported for multi factor authentication (MFA). This however required an extra connector (and that also required some tweaking to make it work within my environment).

Unfortunately with the update this connector refused to work, so I decided to go all in for keycloak.

On the way there I also wanted to go for some (minor) changes in the appearance of keycloak. There’s quite some docs and tools (like keycloakify) out there to ease that process, however they all still seem to be quite heavy if all you need is a nice logo somewhere on the login page and your favorite background image. They seem to be designed for professional environments where more effort can be spent on corporate design.

However for this post I’ll try to keep the time spent on that to the very minimum.

Starting point

I assume you’re already running keycloak, but with one of the default themes (keycloak.v2 in my case). As I’m running my keycloak in docker, some steps will be related to that.

As I mentioned before, what I want to achieve is:

  • Adding a logo to the login page
  • Changing the background image of the login page
  • Adding a favicon

In order to do so, we first need to create a new theme. Themes are kept in /opt/keycloak/themes in the default docker image. For now we’ll prepare the required files that we’ll later mount upon restart of the docker container.

First of all let’s get the latest themes from the keycloak installation (as you might guess from the following commands my container is named “keycloak“):

linux # docker exec -ti keycloak find / -xdev -name "*themes*jar"
/opt/keycloak/lib/lib/main/org.keycloak.keycloak-themes-26.4.0.jar
/opt/keycloak/lib/lib/main/org.keycloak.keycloak-themes-vendor-26.4.0.jar
linux # docker cp keycloak:/opt/keycloak/lib/lib/main/org.keycloak.keycloak-themes-26.4.0.jar /tmp/
Successfully copied 988kB to /tmp/

The provided .jar files are basically ZIP files, so we can extract them using unzip:

linux # unzip /tmp/org.keycloak.keycloak-themes-26.4.0.jar -d /tmp/themes
Archive:  /tmp/org.keycloak.keycloak-themes-26.4.0.jar
  inflating: /tmp/themes/META-INF/MANIFEST.MF
   creating: /tmp/themes/theme/
<...>
linux # find /tmp/themes/ -type d
/tmp/themes/
/tmp/themes/META-INF
/tmp/themes/META-INF/maven
/tmp/themes/META-INF/maven/org.keycloak
/tmp/themes/META-INF/maven/org.keycloak/keycloak-themes
/tmp/themes/theme
/tmp/themes/theme/keycloak
/tmp/themes/theme/keycloak/welcome
/tmp/themes/theme/keycloak/welcome/resources
/tmp/themes/theme/keycloak/welcome/resources/css
/tmp/themes/theme/keycloak/login
/tmp/themes/theme/keycloak/login/resources
/tmp/themes/theme/keycloak/login/resources/img
/tmp/themes/theme/keycloak/login/resources/css
/tmp/themes/theme/keycloak/common
/tmp/themes/theme/keycloak/common/resources
/tmp/themes/theme/keycloak/common/resources/img
/tmp/themes/theme/keycloak/common/resources/lib
/tmp/themes/theme/keycloak/common/resources/lib/pficon
/tmp/themes/theme/keycloak/email
/tmp/themes/theme/base
/tmp/themes/theme/base/account
/tmp/themes/theme/base/account/messages
/tmp/themes/theme/base/login
/tmp/themes/theme/base/login/messages
/tmp/themes/theme/base/login/resources
/tmp/themes/theme/base/login/resources/js
/tmp/themes/theme/base/admin
/tmp/themes/theme/base/admin/messages
/tmp/themes/theme/base/email
/tmp/themes/theme/base/email/messages
/tmp/themes/theme/base/email/text
/tmp/themes/theme/base/email/html
/tmp/themes/theme/keycloak.v2
/tmp/themes/theme/keycloak.v2/login
/tmp/themes/theme/keycloak.v2/login/resources
/tmp/themes/theme/keycloak.v2/login/resources/js
/tmp/themes/theme/keycloak.v2/login/resources/css
/tmp/themes/theme/keycloak.v2/login/resources/img

If you ever changed your theme in keycloak, you might recall some of the directory names: “keycloak”, “keycloak.v2”, “base” are all default themes.

The directory name after that specifies the dialogs that are affected by the themes (something like “welcome”, “login”, “email” or “account”). As I’m aiming for the login related dialogs we’ll go for “keycloak.v2/login/“.

Prepare directory structure:

linux # mkdir mytheme
linux # mkdir mytheme/resources
linux # mkdir mytheme/resources/css

Create a basic theme (inherited from keycloak.v2 theme):

linux # vi mytheme/login/theme.properties
parent=keycloak.v2

styles=css/login_mytheme.css

logosvg_url=https://www.mydomain.de/ci/mydomain-logo.svg
favicon_url=https://www.mydomain.de/ci/icons/favicon.ico

Preparing CSS:

linux # vi mytheme/login/resources/css/login_mytheme.css
/* Patternfly CSS places a "bg-login.jpg" as the background on this ".login-pf" class.
   This clashes with the "keycloak-bg.png' background defined on the body below.
   Therefore the Patternfly background must be set to none. */
.login-pf {
    background: none;
}

.login-pf body {
    /* MR mod */
    background: url(https://www.mydomain/ci/mytheme-bg.webp) no-repeat center center fixed;
    background-size: cover;
    height: 100%;
}

And now we need to do some basic changes to the login template to get background and logo:

linux # cp /tmp/themes/theme/keycloak.v2/login/template.ftl mytheme/login/template.ftl

Now we modify the template a little:

linux # vi mytheme/login/template.ftl
<...>
<!-- link rel="icon" href="${url.resourcesPath}/img/favicon.ico" / -->
<link rel="icon" href="${properties.favicon_url}" />
<...>
<!-- div id="kc-header-wrapper"
>               class="pf-v5-c-brand">${kcSanitize(msg("loginTitleHtml",(realm.displayNameHtml!'')))?no_esc}</div -->
<div id="kc-header-wrapper" align=center
>              class="pf-v5-c-brand"><img src=${properties.logosvg_url} width=50%/></div>
<...>

Now we only need to mount our theme to the right place while restarting the docker container:

linux # docker run -v $(PWD)/mytheme:/opt/keycloak/themes/mytheme quay.io/keycloak/keycloak:latest

Now all we need to do is select our newly provided theme.

Leave a Reply

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