A practical guide to Keycloak

A practical guide to Keycloak

2025-12-31

Keycloak is an Open Source Identity and Access Management tool.

You use this sort of thing to facilitate and to make it safer to manage users, groups, roles, access to applications and more! I wrote about why you need an identity provider before.

The use case I’m covering here

Keep in mind I’d never be able to explain all about what you can do with Keycloak here. Just take a look at the server administration docs to get the idea of how big this thing actually is.

I’m describing how we overcame the challenges of our particular use case. However, I sincerely believe that this setup covers the use case for most organizations, specially small to medium ones.

Step 0: the deployment

Easiest way, specially to test it, is to use the Docker guide in the official docs.

There’s no point explaining this in detail here.

LDAP as a backend

What if I’m not using LDAP?

There’s two possibilities: you’re using a variant of LDAP, such as Windows AD, or you do not have any backend with all the information already.

For the first case: just adapt the settings. For the latter: skip this completely, Keycloak’s database is your backend, attribute roles and groups using its own web interface.

It is the “go-to” user database. We’ve been using it for quite a while now, and we plan to have only one central database, so we’ll connect Keycloak to it.

If you can avoid having more than one user database, do it. Managing multiple identity providers, specially if they differ in technology, is a pain. Even more so if a few specific users have to be in both, duplicating information like this is hell.

  1. Start by adding an LDAP user federation:

Add the “LDAP User Federation”

  1. Fill in the appropriate values for your LDAP connection:

It’s relevant to point out that in our use case of Keycloak we just want to: provide authentication and authorization to a few services we host. So, for now, we set the edit the LDAP connection to READ_ONLY. We will later implement password resets using alternative e-mails.

Set it to READ_ONLY

We also saw no benefit from importing the users into keycloak. We’ve disabled that.

Disable Syncing Users

Group and Role mapping

This is what will make Role-Based Access Control work like a charm later. Under Mappers click Add mapper.

Fill in the appropriate fields. We did not have child groups in our LDAP, so these settings worked fine for us:

Group Mapper

The same has to be done for roles. In our particular case, groups are roles are basically the same thing. If you can, in fact, merge them, that’s even better. Less to worry about equals less to worry about.

Testing authentication

Right now, if you configure any particular client, authentication should work as normal. Let’s test with NextCloud!

First, let’s configure the client in Keycloak:

Nextcloud Client Config

Make sure that “Authentication flow” is set to “standard”, but most importantly: “Authorization” is set (we’ll use this later).

After this we need to configure Keycloak as a provider in Nextcloud. This varies from client to client. As a general rule, search for something like “OpenID provider” on the client’s documentation.

Tip

If you ever forget keycloak openid configuration, the URL https://your.domain/realms/your-realm/.well-known/openid-configuration will most likely have it!

Then, if we try to log in to NextCloud using the OpenID login, we get:

Keycloak Login

Seems like it works:

NextCloud Home

Perfect! Time to start implementing Role-Based Access Control!

A new Browser Flow

This is done under the “Authentication > Flows” tab on the sidebar.

This is where the magic happens: create a browser flow for NextCloud in the same idea as the following:

Nextcloud Browser Flow

More importantly, configure both “require role” to assert the user has the “uma protection” role for the target client:

Require role

I don’t have the “uma protection” role!

Make sure you configure your client with “Authorization” enabled!

Wait, so I have to create a new flow for every client???!

Well… yes…

Since we have just a couple of clients we don’t mind. In fact, we like to be a bit verbose when it comes to granting access to things anyways.

Client UMA Roles

But if you look for it, no one will have the UMA Role! What now?!

We associate other roles with the uma protection one!

Child Role

This is actually very versatile. You can associate the uma protection role with other roles, groups, and even directly attribute them to users.

That way, adding “NextCloud uma protection” role as an associated role to, for example, the “secretary-users” role, means we want to give the “secretary-users” access to NextCloud!

Working Role-Based-Access-Control

After that, change the browser flow in the client’s settings. It should be at the bottom of the “Advanced” tab.

Using the Browser Flow

For testing purposes, I created a Realm Role called ROLE-1, and added the NextCloud uma authorization role as an associated role.

ROLE-1

Now, let’s test it with two users: user1 has ROLE-1, and user2 has not.

Test users

  • Flow 1: User has access (has the ROLE-1 role)

User1 login

After credentials I had to finish filling:

Note

This is actually very relevant: If you add required properties that the user has not filled, they will be REQUIRED to fill it during their first login.

User1 login

After filling that in:

User1 login

Perfect, login works!

  • Flow 2: User does not have access (does not have the ROLE-1 role)

User2 login

After credentials:

User2 login

We can conclude that RBAC is working as intended. Now you can start customizing the theme for your brand, to look more “professional”.

Bonus: hardening Keycloak a bit

Since all your user identity information will eventually be centralized in Keycloak (if you plan to centralize all your “Identity Providing”), it will be a very valuable target at your organization. Therefore, it is imperative to prevent leaks from ocurring.

Disabling access to clients by default

It is actually better to change the default Browser Flow to just a “Deny Access”, and grant access to applications as needed.

You can do that under the “Authentication” tab on the sidebar. Where you create the alternative Browser Flows.

Separate admin virtual host

If you can, you should restrict access to keycloak’s admin features as much as possible. If I’m not mistaken, the docs say that the routes below are safe for public access:

  • /realms/
  • /resources/
  • /.well-known/

Then, you can use another virtual host for access to any route. For example:

keycloak.domain.xyz: public routes, accessible everywhere
admin.keycloak.domain.xyz: all routes, accessible only from internal network

This has to be configured in the reverse proxy level: your apache, nginx, ingress, etc.

Disabling Direct Grants

Basically, when performing a direct grant authentication, the application directly sends the username and password to keycloak. This differs from the default flow where the user is redirected to keycloak, inputs the username and password, and is then redirected back to the application.

We do not use it nor plan to use it. If the application does not directly support redirecting to the Keycoak login page we will fork it.

This way we reduce the attack surface where passwords can leak. With a bit of hardening, this setup can become sufficiently secure for our use case.

Doesn’t really prevent anything, except using it. And as a good rule of thumb: if you’re not 200% (yep 2x 100%) sure you need it, don’t use it.