What is Keycloak? How to use it — an example with nodejs? (Part 2)

Nirabhra Tapaswi
theoptimaltechnologist
9 min readSep 13, 2020

Welcome back to our two part series on configuring and using Keycloak in real world. In this part I will focus more on using the Keycloak setup that we configured back in Part 1 in a nodejs express application.

Now, I have been with javascript for a long time, since I was introduced to web development, which is the reason I found it easy to integrate with a nodejs application. On the other side, there are lots of easy to use Java adapters(framework specific) that you will find here

And for other programming languages, there are unofficial libraries that provide easy integration with basic Keycloak features, but I would recommend using Keycloak Gatekeeper

Also, its fairly easy to implement the apis of Keycloak and develop a custom keycloak service in any programming language. I shall create a api tutorial later for ease of integration with other programming languages or bash via http(s) protocol. Just remember, with increasing proficiency in programming languages and technology concepts, your dependency on external libraries decreases as you understand implementation specifics better. Not that using libraries are bad(as I mentioned before, don’t reinvent unless necessary), but if the 3rd party libraries with unreliable maintainers, better rewrite it so that improvements on it become easy.

Okay, enough talk, lets start building our nodejs express application. First of all, you will need nodejs and npm installed in your system. Firstly, create a folder to work on, and run a few getting ready commands —

$ mkdir keycloak-express
$ cd keycloak-express
$ npm init
$ npm install express ejs express-session keycloak-connect serve-favicon --save

The directory structure will finally look like —

directory structure

We will get to know all of these during the tutorial, lets begin with index.js. It is the entry-point to our expressjs server. We will be using ejs(embedded javascript) format for html embedded javascript coding(ejs its an old pattern but its quite easy to use and feels just like javascript).

Lets begin with writing the basic express server code —

index.js

I won’t be explaining in depth the express framework or how nodejs http server works, that is out out of the scope of this article, but only some logical parts of the code which is necessary for understanding. Observe that we have two GET routes at paths “/” and “/home” respectively. Our ultimate goal will be to show an authenticated user the home page with his name and some details on this screen. Lets look at the initial version of our home.ejs(think of it like html only, with abilities to include javascript within it). This is how home.ejs should look like —

home.ejs (note, the github gist is .html because ejs does not have color encoded support)

In the home.ejs file, we are simply checking for the presence of a user object, and in case it is absent, we want the user to login. We have not yet included the login logic yet. You can run the server at this point —

# node index.js

Visit http://127.0.0.1:3000/home to see the name ‘John’ being printed.

Browser

Well, that is not impressive.. But have a bit of patience, we will get to the awesome parts. Before we proceed, let us get the client adapter configuration file from Keycloak. Go to the client(my-product), click on Installation tab and select Keycloak OIDC JSON option.

keycloak.json

Save this as keycloak.json adjacent to our index.js server file(refer directory structure).

Before we proceed to introduce keycloak code for our express app, I would like to briefly tell you about the tokens that Keycloak returns when logging in a user —

  • Access Token: Contains claims about the user and it’s roles, permissions, groups etc. This is the actual token which is evaluated for granting access to protected resources.
  • Refresh Token: Think of it as a session token(Keycloak does). This token is responsible to issuing new access tokens(which are short lived by convention) till this itself expires, which will lead to a re-login scenario.
  • ID Token: This is a token containing claims about the user’s details. By default it has the same amount of user’s details claims as the access token, but as new user details are added, ID Token is supposed to have them by convention.

Lets edit our index.js file to include keycloak login and authentication functions —

Let us go over this file, firstly, we import keycloak-connect, which is our keycloak client adapter. Then we initialize a memory store(memoryStore), which is used by keycloak-connect for internal token caching. Finally, what we are interested is in the middlewares introduced in routes “/home” and “/login”. This route internally redirects the user to Keycloak’s my-product realm’s login page, with a redirect to the the actual url that we requested(in this case “http://127.0.0.1:3000/login” or “http://127.0.0.1:3000/home” whichever we called first. The keycloak.protect() function makes sure we have a valid token from Keycloak before we access the actual function backing that route. Note, here “/login” is just a formality for frontend convenience, as keycloak.protect() would redirect unauthenticated requests to any of “/login” or “/home” to “my-product” login page. Before we go ahead and change our home.ejs template, lets try this new piece of code out. Restart the server with ctrl + c and running ($ node index.js) again(explore nodemon or yarn tools for auto-restarting servers). Open http://127.0.0.1:3000/login, we immidiately get redirected to Keycloak’s “my-product” realm, enter credentials and see if the outputs match —

my-product login

NOTE: My keycloak is hosted on a different server in my network, not my localhost hence the URL is what you see above, it should come 127.0.0.1/localhost for you if you have installed it in the same machine.

Now, after this you would ideally expect to get logged in, and see the home.ejs page from earlier(because if you see index.js login route function, we see redirect to home on successful login). Lets see what we get —

access denied

If you are quite new to Keycloak, by this time you will be confused. Don’t worry it is expected. Are you wondering where we went wrong? Maybe the nodejs code? Or some Keycloak configuration? Afterall we have gone through alot of setup, something may have gone wrong. But the real reason is a very useful security concept that Keycloak implements called audience checking. Refer to the following article for in-depth clarity —

The overall idea is that the way clients verify tokens is configurable to include audience verification. This mitigates the possibility of unwanted access to applications even with correct roles(such as unintended server to server communication). The tokens will be evaulated to deny if the it does not have that particular client as an audience. In our case, we have to add a scope to our “my-application” client which adds itself as an intended audience when undergoing a login process. Read more about protocol-mappers, scopes and claims on the official Keycloak website to understand these very important concepts in depth.

Navigate to the Client Scopes page in Keycloak, click on Create button and add a new client scope “my-application-scope” —

Client Scope Create

Then select Mappers from the tab bar, click on Create button, and create a mapper with name “my-application-audience-protocol-mapper” —

Audience Protocol Mapper Create

In the above select Mapper Type Audience, so that Keycloak knows in which field of the encoded tokens to add the audience values. You can disable add to ID token switch if you want, I am just going to leave it as it is. Lastly go to Clients page, select “my-application”, click on Client Scopes, and add this newly added client scope to it —

Client Scopes Add

Now we are ready to test our nodejs code again. First hit “http://127.0.0.1:3000/logout” to clear the current session token with no audience parameters. Then go to “http://127.0.0.1:3000/login” again and login to Keycloak’s login page. Now you should see the following page after a successful login —

audience verify success, login success

We have accomplished a major feat with Keycloak and nodejs. But we still have a few features to test out. We have logged in yes, and our routes are authentication protected, but what about authorization? Remember that we already have an authorization framework ready in our Keycloak(and we already tested it with Evaluate tab in Authorization under Client). Lets edit our code to look at how we can protect some routes to specifically demand permissions. Here is our final index.js —

We have added 2 additional routes(GET “/asset01”, GET “/asset01/update”) to showcase the authorization check feature of Keycloak. Ideally the second route, i.e. “asset01/update” should have been a POST request, but here we are using GET route because it simplifies our frontend request from UI. You can see in the keycloak.enforcer middleware funtion that the resource and scope are passed as a “:” concatenated string(a demand of the library, not keycloak itself). This ensures whatever function lies at the end of the route path is accessed by only users with the required scope access on the resource. In our case, our “/asset01” endpoint requires a read scope permission on asset-01 resource, and “/asset01/update” endpoint requires a write scope permission on asset-01 resource. If you remember, we had granted our user John Halpert a user role, which we saw in our permissions tab that is allowed to access only the read scope of asset-01 resource, not write. Also, I have modified the “/home” route slightly to take the name, email and username from the id token or the access token, with the help of a simple parseToken function which converts the base64 encoded jwt’s payload to a JSON parsed object(you can console.log the payload to introspect the token’s content). Lets modify home.ejs a bit to capture the new information we are sending —

Lets see it in action, first logout(“http://127.0.0.1:3000/logout”), followed by a automated redirect to Keycloak’s login page, where you should log in. You should be redirected to “/home” on successful login, where you can see —

home

Then we can go to the url “http://127.0.0.1:3000/asset01” and we should find a success response —

asset01 read success

And the path “http://127.0.0.1:3000/asset01/update” should give an access denied —

asset01 write access denied

So there we go, all done. We have successfully integrated a full fledged IAM software with our application. There are a lot of more things that Keycloak can do, so tweak it, study it, explore it in depth to secure you application the best way possible.

Thank you for staying this long, hope this series helped you.

--

--