Single Sign-On (SSO) with Keycloak

Brief Introduction about Keycloak

Keycloak is a robust solution for user identity and access management. It’s open source software that you can self-hosting by your own. It makes securing your applications and services become easier with minimum fuss. So, you don’t need to deal with storing users or authenticating users. Everything is all available out of the box. Following are the great features that being offered by the Keycloak software:-

  • Single sign-on (SSO) and single logout.
  • Supports Standard Protocols such as OpenID Connect (OIDC), OAuth 2.0 and SAML 2.0.
  • Flexible Authentication and Authorization.
  • Multi-Factor Authentication (MFA) such as One-time Password (OTP).
  • Social logins such as Google, Facebook, Twitter, etc..
  • Provides centralized user management.
  • Supports Directory Services such as LDAP and Active Directory.
  • Customizable and extensible.
  • Easy setup and integration using provided client adapters.

Keycloak Core Concepts and Architecture

A Keycloak realm is like a namespace that allows you to manage all of your metadata and configurations. You can create as many realms as you like. The default realm is called master which is dedicated to manage Keycloak and should not be used for your own applications. Basically you need to create a new realm to get started. Following are the entities that being managed by a single realm:-

  • Clients
  • Roles
  • Identity Providers (OIDC 1.0, Keycloak OIDC, SAML 2.0, Social Logins)
  • User Federation (Kerberos, LDAP)
  • Authentication configurations
  • User Management (Groups, Users)
  • UI Themes
  • Realm settings

Following image illustrates the architecture of Keycloak software;

Image: Credit: How to secure your Spring Apps with Keycloak (2019) by Thomas Darimont
Credit: How to secure your Spring Apps with Keycloak (2019) by Thomas Darimont

User Authentication using Keycloak

Keycloak as Identity Provider to Frontend Application

Following image illustrates how a user is authenticated when accessing the frontend application;

Image: Credit: How to secure your Spring Apps with Keycloak (2019) by Thomas Darimont
Credit: How to secure your Spring Apps with Keycloak (2019) by Thomas Darimont

SSO Integration

Web SSO is the most useful feature where you login once to access all applications. Keycloak also supports single logout that can be propagated to all clients. This works for web, mobile and desktop applications.

Following image illustrates the authentication flow of a logged-in user accessing another frontend application;

Image: Credit: How to secure your Spring Apps with Keycloak (2019) by Thomas Darimont
Credit: How to secure your Spring Apps with Keycloak (2019) by Thomas Darimont

How backend services work with Keycloak

Following image illustrates the flow on how the backend services work with Keycloak to validate the access token;

Image: Credit: How to secure your Spring Apps with Keycloak (2019) by Thomas Darimont
Credit: How to secure your Spring Apps with Keycloak (2019) by Thomas Darimont

Understanding Keycloak Tokens

Keycloak works based on tokens. Following are the few things that describe a token in Keycloak, especially for OAuth2 and OIDC protocol:

  • The token is a signed self-contained JSON Web Token (JWT).
  • The token contains claims that hold metadata and user information.
  • The token is issued by Keycloak that is signed with a realm private key.
  • The token is verified using the realm public key.
  • The token has limited lifespan which is revokable.

Following are the available types of token when authenticating with Keycloak:

Access tokenUsually it has short-lived lifespan (minutes) and it is used for accessing resources.
Refresh tokenUsually it has long-lived lifespan (days) and it is used for requesting new tokens.
Offline tokenA special refresh token that “never” expires.
ID tokenContains information about user (used by OIDC).

Example Screenshots of Keycloak UI

Keycloak Admin Console

Image: Keycloak Admin Console (v11)
Keycloak Admin Console (v11)

Keycloak User Account Console

Image: Keycloak User Account Console (v11)
Keycloak User Account Console (v11)

Keycloak Admin REST API Examples

These are the most common REST APIs that I used for applications. To learn more about what else that’s available, please check out Keycloak Admin REST API documentation page.

Authenticate as Keycloak Admin

curl --location --request POST '<KEYCLOAK_SERVER>/auth/realms/master/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'username=<KEYCLOAK_ADMIN_USER>' \
--data-urlencode 'password=<KEYCLOAK_ADMIN_PASS>' \
--data-urlencode 'client_id=admin-cli'

Get user list executed from a specific user account

Following are the prerequisite steps that needed to be applied on Keycloak Admin Console:

  1. From a selected realm, go to Manage ⟶ Users.
  2. To apply for a specific user, click on “View all users” button then click on selected user ID.
  3. Go to Role Mappings tab, select realm-management from the Client Roles.
  4. Scroll down in Available Roles, find view-users and add it into Assigned Roles.

Alternatively, this can be applied as a default value for all newly registered users;

  1. From a selected realm, go to Manage ⟶ Roles.
  2. Select realm-management from the Client Roles.
  3. Scroll down in Available Roles, find view-users and add it into Client Default Roles.

Get the access token:

curl --location --request POST '<KEYCLOAK_SERVER>/auth/realms/<REALM>/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'username=<USERNAME>' \
--data-urlencode 'password=<PASSWORD>' \
--data-urlencode 'client_id=<CLIENT_ID>' \
--data-urlencode 'client_secret=<CLIENT_SECRET>'

Use the access token to get the user list:

curl --location --request GET '<KEYCLOAK_SERVER>/auth/admin/realms/<REALM>/users' \
--header 'Authorization: Bearer <ACCESS_TOKEN>'

Get a specific user info

Get the access token:

curl --location --request POST '<KEYCLOAK_SERVER>/auth/realms/<REALM>/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'username=<USERNAME>' \
--data-urlencode 'password=<PASSWORD>' \
--data-urlencode 'client_id=<CLIENT_ID>' \
--data-urlencode 'client_secret=<CLIENT_SECRET>'

Grab the user ID and use it to get the respective user info:

curl --location --request GET 'https://<KEYCLOAK_SERVER>/auth/admin/realms/<REALM>/users/<USER_ID>' \
--header 'Authorization: Bearer <ACCESS_TOKEN>'

Get user roles from a specific user

Get the access token:

curl --location --request POST '<KEYCLOAK_SERVER>/auth/realms/<REALM>/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'username=<USERNAME>' \
--data-urlencode 'password=<PASSWORD>' \
--data-urlencode 'client_id=<CLIENT_ID>' \
--data-urlencode 'client_secret=<CLIENT_SECRET>'

Grab the user ID and use it get the user roles:

curl --location --request GET '<KEYCLOAK_SERVER>/auth/admin/realms/<REALM>/users/<USER_ID>/role-mappings' \
--header 'Authorization: Bearer <ACCESS_TOKEN>'

Quick Deployment of Keycloak via Docker Compose

Example of docker-compose.yml file:

version: '3.5'

volumes:
  pgkeycloak-data:
    name: acme_pgkeycloak-data
 
networks:
  acme:
    driver: bridge
    name: acme_network

services:

  pgkeycloak:
    image: postgres:12-alpine
    container_name: keycloak_database
    volumes:
      - pgkeycloak-data:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: keycloak
      POSTGRES_USER: keycloakdb
      POSTGRES_PASSWORD: ${KEYCLOAK_DB_PASSWORD}
    ports:
      - "5432:5432"
    networks:
      - acme
 
  keycloak:
    container_name: keycloak_service
    image: keycloak:latest
    environment:
      KEYCLOAK_USER: ${KEYCLOAK_ADMIN_USER}
      KEYCLOAK_PASSWORD: ${KEYCLOAK_ADMIN_PASS}
      PROXY_ADDRESS_FORWARDING: "true"
      DB_USER: keycloakdb
      DB_PASSWORD: ${KEYCLOAK_DB_PASSWORD}
      DB_DATABASE: keycloak
      DB_ADDR: pgkeycloak
      DB_VENDOR: postgres
      DB_SCHEMA: public
    ports:
      - "8080:8080"
      - "8443:8443"
    networks:
      - acme
    depends_on:
      - pgkeycloak

You can use following docker-compose CLI to get started:

$ docker-compose -f docker-compose.yml up -d

There are a lot of great resources that you could find online (simply google it) to learn more about Keycloak, and the best way to start is to visit its official website.