1. Overview
Keycloak is a third-party authorization server used to manage our web or mobile applications' authentication and authorization requirements. It uses a default login page to sign-in users on our app's behalf.
In this tutorial, we'll focus on how we can customize the login page for our Keycloak server so that we can have a different look and feel for it. We'll see this for both standalone as well as embedded servers.
We'll build on top of customizing themes for the Keycloak tutorial to do that.
2. Customizing a Standalone Keycloak Server
Continuing with our example of the custom theme, let's see the standalone server first.
2.1. Admin Console Settings
To start the server, let's navigate to the directory where our Keycloak distribution is kept, and run this command from its bin folder:
./standalone.sh -Djboss.socket.binding.port-offset=100
Once the server is started, we only need to refresh the page to see our changes reflected, thanks to the modifications we previously made to the standalone.xml.
Now let's create a new folder, named login, inside the themes/custom directory. To keep things simple, we'll first copy all the contents of the themes/keycloak/login directory here. This is the default login page theme.
Then, we'll go to the admin console, key-in the initial1/zaq1!QAZ credentials and go to the Themes tab for our realm:
We'll select custom for the Login Theme and save our changes.
With that set, we can now try some customizations. But before that, let's have a look at the default login page:
2.2. Adding Customizations
Now let's say we need to change the background. For that, we'll open login/resources/css/login.css and change the class definition:
.login-pf body {
background: #39a5dc;
background-size: cover;
height: 100%;
}
To see the effect, let's refresh the page:
Next, let's try to change the labels for the username and password.
To achieve that, we need to create a new file, messages_en.properties in the theme/login/messages folder. This file overrides the default message bundle being used for the given properties:
usernameOrEmail=Enter Username:
password=Enter Password:
To test, again refresh the page:
Suppose we want to change the entire HTML or a part of it, we'll need to override the freemarker templates that Keycloak uses by default. The default templates for the login page are kept in the base/login directory.
Let's say we want WELCOME TO BAELDUNG to be displayed in place of SPRINGBOOTKEYCLOAK.
For that, we'll need to copy base/login/template.ftl to our custom/login folder.
In the copied file, change the line:
<div id="kc-header-wrapper" class="${properties.kcHeaderWrapperClass!}">
${kcSanitize(msg("loginTitleHtml",(realm.displayNameHtml!'')))?no_esc}
</div>
To:
<div id="kc-header-wrapper" class="${properties.kcHeaderWrapperClass!}">
WELCOME TO BAELDUNG
</div>
The login page would now display our custom message instead of the realm name.
3. Customizing an Embedded Keycloak Server
The first step here is to add all the artifacts we changed for the standalone server to the source code of our embedded authorization server.
So, let's create a new folder login inside src/main/resources/themes/custom with these contents:
Now all we need to do is to add instruction in our realm definition file, baeldung-realm.json so that custom is used for our login theme type:
"loginTheme": "custom",
We've already redirected to the custom theme directory so that our server knows from where to pick up the theme files for the login page.
For testing, let's hit the login page:
As we can see, all the customizations done earlier for the standalone server, such as the background, label names, and page title, are appearing here.
4. Bypassing Keycloak Login Page
Technically, we can completely bypass the Keycloak login page by using the password or direct access grant flow. However, it's strongly recommended that this grant type shouldn't be used at all.
In this case, there is no intermediary step of getting an authorization code, and then receiving the access token in exchange. Instead, we can directly send the user credentials via a REST API call and get the access token in response.
This effectively means that we can use our login page to collect the user's id and password, and along with the client id and secret, send it to Keycloak in a POST to its token endpoint.
But again, since Keycloak provides a rich feature set of login options – such as remember me, password reset, and MFA – to name a few, there is little reason to bypass it.
5. Conclusion
In this tutorial, we learned how to change the default login page for Keycloak and add our customizations.
We saw this for both a standalone and an embedded instance.
Lastly, we briefly went over how to bypass Keycloak's login page entirely and why not to do that.
As always, the source code is available over on GitHub.