Add User Authentication to Applications with a Scalable Keycloak Deployment on Kubernetes
Introduction
Keycloak is an open source application for centralized identity and access management. It allows users to authenticate themselves across multiple applications and supports many popular protocols (such as OpenID Connect, OAuth 2.0, LDAP and SAML 2.0) and social networks (such as Google, Twitter and Facebook). Keycloak also provides integration libraries for common programming languages and server applications, including Java, Node.js, Apache, Tomcat and Wildfly.
For developers looking to quickly add authentication and identity management to their applications, Keycloak provides a powerful and flexible set of features. The quickest way to get started with it is with Bitnami's Keycloak Helm chart. This chart deploys the most recent and secure version of Keycloak on a Kubernetes cluster using the Helm package manager. Once deployed, Keycloak can be easily configured as an authentication service provider for other applications.
This article walks you through the process of deploying Keycloak on Kubernetes using the Bitnami Keycloak Helm chart. It also shows you how to configure a Keycloak realm, user and client and walks you through the process of developing a simple Express application that integrates with the Keycloak deployment for authentication.
Assumptions and prerequisites
This article assumes that:
- You have a working Node.js development environment, or you have Docker installed and configured. Learn more about installing Docker.
- You have a Kubernetes cluster running with Helm v3.x and kubectl installed. Learn more about getting started with Kubernetes and Helm using different cloud providers.
Step 1: Deploy Keycloak on Kubernetes
Follow the steps below to deploy Keycloak on Kubernetes with Bitnami's Keycloak Helm chart:
Add the Bitnami chart repository to Helm:
helm repo add bitnami https://charts.bitnami.com/bitnami
Execute the following command to deploy Keycloak. Replace the ADMIN-PASSWORD placeholder with a custom password for the Keycloak administrator account.
helm install keycloak bitnami/keycloak \ --set auth.adminPassword=ADMIN-PASSWORD
Wait for a few minutes until the chart is deployed. You can also use the command below to check the status of the deployment:
kubectl rollout status sts keycloak
By default, a load balancer service is created for the Keycloak deployment. Obtain the public URL for the deployment using the commands shown in the deployment notes. Exmple commands are provided below.
export SERVICE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].port}" services keycloak) export SERVICE_IP=$(kubectl get svc --namespace default keycloak -o jsonpath='{.status.loadBalancer.ingress[0].ip}') echo "http://${SERVICE_IP}:${SERVICE_PORT}/auth"
Step 2: Create a Keycloak realm and user
The next step is to create a Keycloak realm. Follow these steps:
- Browse to the Keycloak URL obtained at the end of the previous step. This displays the Keycloak welcome page, as shown below:

- Click the link for the "Administration Console". This displays the Keycloak login page, as shown below:

- Log in to Keycloak with the username user and the password defined in the ADMIN-PASSWORD placeholder in the previous step.
- Navigate to the "Master -> Add Realm" page.
- Enter a name for the new realm.
- Click "Create" once done.

The new realm is created.
Next, create at least one user account within the new realm, as follows:
- Ensure that the new realm is the active realm, by selecting it in the top left corner of the navigation bar.
- Navigate to the "Manage -> Users" page.
- Click the "Add user" button.
- Enter a username for the new user.
- Click "Save" to save the record.

The new user is created.
- On the resulting user details page, select the "Credentials" tab.
- Configure the credentials as follows:
- Enter a password for the user account.
- Repeat the password entry to confirm it.
- Set the "Temporary" slider to "Off".
- Click "Set Password" once done to save the new password. Confirm the operation when prompted.

The password for the new user account is now configured.
Learn more about configuring realms and users in Keycloak.
Step 3: Create a Keycloak client
Every application that uses Keycloak for authentication must use a registered Keycloak client. Fortunately, creating and registering a new Keycloak client is simple.
Follow the steps below to create a client for the Express example application:
- In the Keycloak administration console, ensure that the correct realm is selected.
- Navigate to the "Manage -> Clients" page.
- Click the "Create" button.
- Create a new client using the following parameters:
- Client ID: node
- Client Protocol: openid-connect
- Root URL: http://localhost:3000. If the application is running on a different host, replace localhost with the IP address of the host
- Click "Save" to save the record.

- On the resulting client details page, select the "Installation" tab.
- Select the "Keycloak OIDC JSON" format.
- Note the JSON block displayed on the screen, as you will need it in Step 4.

Learn more about configuring clients in Keycloak.
Step 4: Integrate an Express application with Keycloak
Keycloak comes with client adapters for many popular programming languages, including Java, Python, Node.js, C# and Android. This tutorial uses the Node.js client adapter and creates a skeleton Express application with a single endpoint. Access to that endpoint will be protected with Keycloak authentication.
This article will use the Bitnami Node.js container image to create the Express application. However, if you already have a Node.js development environment, you can use that instead and skip the Docker commands below.
Begin by creating a directory for your application and making it the current working directory:
mkdir myapp cd myapp
Use the following Docker commands to create and start a Bitnami Node.js container on your host:
docker create -v $(pwd):/app -t --net="host" --name node -p 3000:3000 bitnami/node:14 docker start node
The -v argument to the first command tells Docker to mount the host's current directory into the container's /app path, so that the effects of commands run in the container are seen on the host. The --net="host" parameter tells Docker to use the host's network stack for the container. The container is named node. The -p 3000:3000 parameter maps container port 3000 to host port 3000, so that it is easier to access the application from the Docker host.
Once the container is running, connect to the container console with the command below. This will give you a command shell and allow you to use the Node.js tools available in the image for subsequent tasks.
docker exec -it node /bin/bash
Install Express, the Keycloak adapter for Node.js and the Express session manager:
npm install --save express keycloak-connect express-session
Create a new file named server.js and fill it with the following code for a skeleton Express application:
var express = require('express'); var app = express(); app.get('/', function(req, res){ res.send("Secure page"); }); app.listen(3000);
Update the skeleton application with additional code to integrate the Keycloak Node.js adapter. The revised server.js file looks like this. Replace the CLIENT-JSON-BLOCK placeholder with the JSON block (including curly braces) obtained at the end of Step 3.
var express = require('express'); var session = require('express-session'); var Keycloak = require('keycloak-connect'); var memoryStore = new session.MemoryStore(); var app = express(); var config = CLIENT-JSON-BLOCK app.use(session({ secret: 'guessme', resave: false, saveUninitialized: true, store: memoryStore })); var keycloak = new Keycloak({ store: memoryStore }, config); app.use(keycloak.middleware()); app.get('/', keycloak.protect(), function(req, res){ res.send("Secure page"); }); app.listen(3000);
These changes add the Keycloak adapter to the Express application as middleware and use its protect() method to secure the root URL of the application.
Step 5: Test the Keycloak integration
You can now proceed to test the integration with Keycloak, by starting the Node.js application and attempting to access the protected URL.
Start the application:
node server.js
Browse to the application root URL on the Docker host, such as http://localhost:3000. If the application is running on a different host, replace localhost with the IP address of the host. You are redirected to a Keycloak login page. This page displays the name of your custom realm.

- Log in with the user credentials created in Step 2 to see the contents of the protected URL.
This demonstrates that the Keycloak service is running and able to authenticate requests from registered clients.
Security improvements
It is important to note that the approach outlined in this tutorial is illustrative and not recommended for production environments. The steps described above take various liberties with application and cluster security, in the interests of creating a simpler and more focused tutorial. For example:
- The Keycloak service is exposed at a public IP address.
- A non-HTTPS connection is permitted between the Express application and the Keycloak service.
To improve security, the following enhancements are recommended in production environments:
- The Keycloak service should only be available at a cluster IP address (exposed using a ClusterIP service).
- The Keycloak service endpoints should be secured with HTTPS.
- Client connections should only be permitted over HTTPS.
- Client access should only be permitted from "known good" web origins.
- Applications wishing to use the Keycloak service for authentication should be deployed within the cluster using immutable container images. If these applications are public-facing, a LoadBalancer service can be used to expose them using public IP addresses.
Useful links
To learn more about the topics discussed in this article, use the links below: