Introduction of Keycloak, From Installation to Auth Flows

In the next few posts, I will explore using OIDC (mainly Keycloak) with Kong Gateway(Enterprise). The topics I will be covering include:

  1. Using different authorization flows to protect API services.
  2. Mapping virtual credentials to work with other plugins.
  3. Directory mapping for Kong manager.
  4. Application registration with OIDC.

As these are a lot of content, I will write a new post for each topic and reference each other. My goal is to give you an overall view of what you can achieve using OIDC with Kong and most importantly show you how to make it work step by step.

In today’s post, I will only cover the basics of keycloak. We will be using keycloak to work with Kong in the later posts.

Install keycloak with docker

Installing Keycloak is pretty easy, users can use a database to store all information. As it is for demonstration purposes, you can use below docker-compose.yaml to start a keycloak container behind Traefik quickly.

Traefik will be responsible for proxying requests to keycloak and handle TLS certificate automatically. If you are not sure how to use Traefik, please check my previous posts/videos.

Please note this set up is for testing purpose only and it does not have data persistence. You might want to add a database if you plan to use it in long term. (Even in dev environment)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
version: '2.1'
services:
keycloak:
networks:
- proxy
container_name: keycloak
image: jboss/keycloak
environment:
# Create initial username and password
KEYCLOAK_USER: <USER_NAME>
KEYCLOAK_PASSWORD: <PASSWORD>
PROXY_ADDRESS_FORWARDING: "true"
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
- "traefik.http.routers.keycloak-secure.entrypoints=websecure"
- "traefik.http.routers.keycloak-secure.rule=Host(`key.yourdomain`)"

networks:
proxy:
external: true

Prepare data in keycloak

After we’ve installed keycloak, let’s put in some data to use in our demo.

Create a new realm

You use a realm to hold all your applications and users data. Different realms Do NOT share data with each other. For more information about additional realm settings, please check official documentation here.

Create Users and Groups

This is pretty self-explainatory. I will create a couple users and groups for the demo.

Create a client

  1. Let’s use demo-client-id as client_id. This will be used in all your requests and in the Keycloak database to identify the client. Other IDPs normally generates client id as random string for user.

  2. On client page, we need to change Access Type to confidential and switch Service Accounts Enabled to on. This is for testing client credentials flow.

  3. Under * Valid Redirect URIs, put in http://localhost/callback. We will use this URL to test authorization code flow later.

  4. Go to Credentials tab and save Secret on notepad. We will need it as client_secret in our calls.

Now we are ready to do some test.

Authentication flows

I will cover 4 authentication flows in my examples as I will use them in my future posts.

Let’s start by creating some environment variables.

1
2
3
4
export KEYCLOAK_HOST=
export KEYCLOAK_REALM=
export CLIENT_ID=demo-client
export CLIENT_SECRET=

Password

Password flow is used to authenticate users. The openid scope returns an id_token which includes users information which we can use for consumer mapping and group mapping in future posts.

1
2
3
4
5
6
7
8
9
curl --request POST \
--url https://$KEYCLOAK_HOST/auth/realms/$KEYCLOAK_REALM/protocol/openid-connect/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=password \
--data client_id=$CLIENT_ID \
--data client_secret=$CLIENT_SECRET \
--data username=demo \
--data password=demo \
--data scope=openid

Client credentials

Client credential flow is machine to machine flow. The access_token returned is not bond to a specific user but a service account. We can use it in our applicaiton registraion of developer portal in future.

1
2
3
4
5
6
curl --request POST \
--url https://$KEYCLOAK_HOST/auth/realms/$KEYCLOAK_REALM/protocol/openid-connect/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=client_credentials \
--data client_id=$CLIENT_ID \
--data client_secret=$CLIENT_SECRET

Introspection

Some companies requires the token to be generated locally and pass the access_token to the requests. Keycloak has introspection endpoint which we can use to verify token validity as well as getting the content of token.

1
2
3
4
5
6
curl --request POST \
--url https://$KEYCLOAK_HOST/auth/realms/$KEYCLOAK_REALM/protocol/openid-connect/token/introspect \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data client_id=$CLIENT_ID \
--data client_secret=$CLIENT_SECRET \
--data token=<TOKEN>

Authorization code

Users need to use a browser for this flow. Please copy below URL to notepad, change domain, client_id, redirect_uri to match your settings. Once we open this link on browser, we should be redirected to a log in page. Please enter username and password to log in.

As we have set these variables, we can get our url with below command.

1
echo https://$KEYCLOAK_HOST/auth/realms/$KEYCLOAK_REALM/protocol/openid-connect/auth?client_id=$CLIENT_ID&response_type=code&redirect_uri=http://localhost/callback&scope=openid

We will be redirected back to https://localhost/callback , the URL should look like below.

1
http://localhost/callback?session_state=2698a6a7-d5db-4b3e-805f-ec60bb2f7020&code=6caabc2e-1f08-4566-8c57-3e829ff3924a.2698a6a7-d5db-4b3e-805f-ec60bb2f7020.fa1fcec4-96eb-4868-a924-06d9f5e9fd22

6caabc2e-1f08-4566-8c57-3e829ff3924a.2698a6a7-d5db-4b3e-805f-ec60bb2f7020.fa1fcec4-96eb-4868-a924-06d9f5e9fd22 is the code we need to redeem our tokens, let’s save it to environment variable

1
export CODE=6caabc2e-1f08-4566-8c57-3e829ff3924a.2698a6a7-d5db-4b3e-805f-ec60bb2f7020.fa1fcec4-96eb-4868-a924-06d9f5e9fd22

Now we can redeem our code

1
2
3
4
5
6
7
8
curl --request POST \
--url https://$KEYCLOAK_HOST/auth/realms/$KEYCLOAK_REALM/protocol/openid-connect/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=authorization_code \
--data redirect_uri=http://localhost/callback \
--data code=$CODE \
--data client_id=$CLIENT_ID \
--data client_secret=$CLIENT_SECRET

Now we should get id_token, access_token and refresh_token.

I’ve also created insomnia collection for keycloak which you can import from https://gist.githubusercontent.com/liyangau/47cadc868dc1fdfab81309e5e5f8cac7/raw. Please review before using it.

You can also click below button to import this collection to insomnia directly.

Run in Insomnia}

That’s all for today, I am planning to make a video to show these exact steps asap as long article might still be confusing sometimes.

Stay tuned.