Sitemap
Nishada Liyanage

Nishada Liyanage

Securing a JavaScript App Using Keycloak

7 min readAug 13, 2024

--

In this post I am going to explain how to secure a Vanilla JS (pure JavaScript) application using Keycloak identity & access management system.

Press enter or click to view image in full size
Keycloak — JS Integration: js app

I will be explaining all the configuration and development tasks you need to do for this integration under three main sections.

  1. Keycloak configuration
  2. Js app configuration
  3. Running the app ( demonstration )

Let’s get started.

1. Keycloak Configuration

As the first step you need to have running Keycloak server. I am using a Keycloak server running locally in my PC on the url http://localhost:8080

You can use a locally running Keycloak instance or a hosted one in a remote server as you prefer.

As the initial step, we need to create a new client in the Keycloak server in order to connect the JS application. To do that, you need to visit the admin web console and select clients section as I have shown below.

Press enter or click to view image in full size
Keycloak admin web console

Once visited the clients page, click on Create client button.

Press enter or click to view image in full size
Clients Page

Once Create client button is clicked, a new window will appear and there you need to provide client details including theclient id (which should be unique for the realm). I have provided my client id as js-client

Press enter or click to view image in full size
Client config: General Settings

Once you provided the client id ,click Next button, then below page will appear and there you need to provide the authentication flow of the client. Here I have enabled standard flow which is OpenID Connect Authorization Code Grant type.

Nothing to worry if you are not familiar with authentication flows /OIDC grant types. You can learn them later, for the moment just follow the instructions.

PS: You should learn authentication flows later if you are expecting to become an expert in identity & access management :-)

Press enter or click to view image in full size
Client configuration: Capability config

Client authentication switch is disabled for this client since this is a HTML/JS application which is supposed to be loaded on user’s web browser. Therefore there is no point of enabling client authentication for public clients.

Enabling client authentication gives you a client secret to use in addition to the client id , since the application is loaded on the web browser client secret can simply be read by inspecting HTML and JS content

After enabling standard flow click Next. After that you can configure login settings for the client as shown below. Two important URLs need to be added here.

Press enter or click to view image in full size
Client configuration: Login settings

First one is a valid redirect URI. Once the user is successfully authenticated, she will be redirected back to the JS application. JS application’s URL should be added to the valid redirect URIs section.

If you prefer, you can set * (any url) as a valid redirect URI for testing purpose. But never use that in a production setup.

After setting redirect URIs you need to set web origins. JS application communicates with the Keycloak server directly for different reasons such as token refreshes, etc.

If the web origin property is not properly set, browser console will show CORS (Cross Origin Resource Sharing) related errors.

Once those fields are updated, click Save. Then you will be redirected to the configuration page of the js-client

Press enter or click to view image in full size
js-client config page

This is all we need to do as Keycloak level configurations. Let’s visit the JavaScript application.

2. JavaScript App Configuration

Source code of the application is already available on Github and it will be easier for you to understand the code if you can open it in a code editor.

https://github.com/hexadefence/keycloak-js-example

Let me take you through the important sections of the code.

Get Nishada Liyanage’s stories in your inbox

Join Medium for free to get updates from this writer.

I have implemented the whole code in two files (index.html & main.js) so it will make easier for you to understand.

Section 1 : HTML Code

index.html file is very simple for understanding.

<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">  
<script src="https://cdn.jsdelivr.net/npm/keycloak-js@22.0.3/dist/keycloak.min.js"></script>
<script type="text/javascript" src="./main.js"></script>

Above are the scripts and stylesheets I have imported to my code.

  • Bootstrap css file is used to add styles.
  • Keycloak SDK is imported by using the Keycloak javascript adapter dependency keycloak.min.js. When you import this file you need to make sure the version is matching to the Keycloak server version.
  • Third import is the main.js file ( will be going through this shortly)

I dont think you need any explanation to the below code component. Which contains all the buttons and text area I have used to demonstrate the application.

<div class="container">
<div class="jumbotron mt-4">
<h1 class="display-4">Keycloak - Javascript Integration</h1>
<p class="lead">A pure javascript web app</p>
<div class="mt-4">
<button id="loginBtn" class="btn btn-primary">Login</button>
<button id="logoutBtn" class="btn btn-secondary">Logout</button>
<button id="isLoggedInBtn" class="btn btn-info">Is Logged In</button>
<button id="accessTokenBtn" class="btn btn-warning">Access Token</button>
<button id="showParsedTokenBtn" class="btn btn-dark">Show Parsed Access Token</button>
<button id="callApiBtn" class="btn btn-success">Call API</button>
</div>
<div class="mt-4">
<textarea id="output" class="form-control" rows="5" placeholder="Output will be displayed here..."></textarea>
</div>
</div>
</div>

Section 2: JavaScript Code

Let’s begin from the Keycloak object constructor

const keycloak = new Keycloak({
url: 'http://localhost:8080',
realm: 'master',
clientId: 'js-client'
});

This is where the keycloak object is created. This object is used to communicate with the Keycloak server. Three arguments are provided to the constructor.

  • url : Keycloak server url is provided as the url property
  • realm: We are using the master realm for this demonstration
  • clientId : this is the id of the client we created earlier.
keycloak.init({ 
onLoad: 'check-sso' // 'check-sso', 'login-required'
}).then(function(authenticated) {
....
})

Keycloak init function is used to initialize the Keycloak client object created above. init function accepts a json object as an argument and that json object may have multiple properties.

  • onLoad : This property determines the behaviour of the JS application when a user tries to access. with check-sso value, JS application can be accessed even without having a valid session ( without signing into Keycloak). If user must have a valid session before accessing this application, login-required value can be provided. with login-required value, if the user does not have a valid session she will be redirected to the Keycloak login page
  • flow : You can provide which OpenID Connect grant type should be used with flow property. By defult it is using Authorization Code grant type
  • pkceMethod : Proof key for code exchange method. By default it is using SHA256 based PKCE

Above mentioned are a few of the important parameters and you can find all the init parameters by visiting the Keycloak documentation. https://www.keycloak.org/docs/latest/securing_apps/#methods

Rest of the JS code contains few buttons and a text area I have created to demonstrate the functionalities of the keycloak-js SDK.

By inspecting the code you can understand things like how to login, logout, fetch the access token, etc. Full api documentation is available in the below link.

https://www.keycloak.org/docs/latest/securing_apps/#api-reference

Calling an API

Below code component can be used to call an external API with the access token from the JavaScript application.

fetch('https://4b215443be964e33.api.mockbin.io/', {
headers: {
'Authorization': 'Bearer ' + keycloak.token
}
})
.then(response => response.json())
.then(data => {
logToTextarea('API call successful: ' + JSON.stringify(data));
console.log(data);
})

Rest of the code is easy to understand just by looking at the code. Please put a comment if you need any clarification regarding the code.

Let’s go to the demonstration.

3. Running the application

My keycloak server is already running locally on http://localhost:8080

I need to server my JS application using a static file server. Here I am using a simple python http server.

You can use any server as you prefer for serving static files (nginx, apache, S3 bucket etc.)

Since python is already installed into my pc I start the http server by a single command.


python3 -m http.server 3000 #serve file of the current directory on port 3000

Now my JavaScript application is available on http://localhost:3000

Once visited the JS App, we can see the below landing page.

Press enter or click to view image in full size

Buttons can be used to test and see different functionalities of the application. I have only added few functionalities and rest of the supported functionalities can be found in the documentation ( See the reference).

I believe now you got a clear idea about the Keycloak — JS App integration and if you have any question please put a comment.

Thank you . . .

Source Code

https://github.com/hexadefence/keycloak-js-example

Reference

https://www.keycloak.org/docs/latest/securing_apps/#_javascript_adapter

--