Use OIDC Plugin to read info from Keycloak for Rate limiting and ACL

In my previous post, I talked about using OIDC plugin to protect API services and further control access with consumer mapping. However, cosumer mapping requires Kong consumer objects, which might not be possible if you have hundreds of users on IDP (Keycloak) and you need to limit their access by rate limiting or ACL.

Fortunately Kong’s OIDC plugin supports mapping useres from IDP to virtual credentials in Kong.

In today’s post, I will show you how to get users and its groups information from IDP and use Rate limiting and ACL plugin to limit access.

Prerequisites:

  • Kong Gateway(Enterprise)
  • OIDC is running. (Keycloak in this example) If you don’t have keycloak running, you can check my previous post

Prepare Kong

I am running latest Kong Gateway (Enterprise) version 2.3.3.2.

Create service

Define a service object in kong and use your api server as upstream. In our example, I will use httpbin.

1
2
3
4
curl -X POST \
--url "http://localhost:8001/services" \
--data "name=oidc-demo" \
--data "url=http://httpbin.org/anything"

Create Route

Next we will create a path /demo to access our service.

1
2
3
curl -X POST \
--url "http://localhost:8001/services/oidc-demo/routes" \
--data 'paths[]=/demo'

Enable OIDC plugin

1
2
3
4
5
6
7
8
9
curl --request POST \
--url http://localhost:8001/plugins \
--data name=openid-connect \
--data config.issuer=https://<keycloak>/auth/realms/demo \
--data config.client_id=<client_id> \
--data config.client_secret=<client_secret> \
--data config.auth_methods=bearer \
--data config.credential_claim=preferred_username \
--data config.authenticated_groups_claim=groups

Let me explain these settings in detail. As issuer, client_id, client_secret are self-explanatory, I will skip them.

  • config.auth_methods=bearer
    This means I am using bearer as auth method. In my API calls, I will pass a JWT id_token as Authorization header.
  • config.credential_claim=preferred_username
    This setting is similar to consumer_claim except it is reading a claim value as virtual credential. In this example, I am using the value of preferred_username as virtual credentials.
  • config.authenticated_groups_claim=groups
    This setting reads group names from your token and you can further use ACL config.allow or config.deny to control access by group.

Enable Rate Limiting plugin

1
2
3
4
5
6
curl --request POST \
--url http://localhost:8001/plugins \
--data name=rate-limiting \
--data config.limit_by=credential \
--data config.hour=20 \
--data config.policy=local

For Rate limiting advanced plugin

1
2
3
4
5
6
7
8
curl --request POST \
--url http://localhost:8001/plugins \
--data name=rate-limiting-advanced \
--data config.identifier=credential \
--data config.limit=20 \
--data config.window_size=600 \
--data config.sync_rate=-1 \
--data config.strategy=cluster

Rate limiting plugins gets credentials from OIDC plugin and set limit for each credential.

For example, OIDC reads value from preferred_username, let’s say test and admin. These two users will get their own limits.

Enable ACL plugin

1
2
3
4
curl --request POST \
--url http://localhost:8001/plugins \
--data name=acl \
--data config.allow=admin

let’s say my token contains a groups claim

1
2
3
4
5
...
"groups": [
"admin"
],
...

This setting gets groups from OIDC plugin, ACL will allow/deny access based on the groups we set. In above example, only users in admin group can access the api service.

That’s all I want to cover today.