Use OIDC to Secure Kong Manager and Admins Group Mapping

Introduction

I wrote a post about deploying Kong and Konga before because users can only use Admin API to configurate Kong Gateway OSS. Kong Gateway Enterprise comes with a GUI called Kong manager which is very powerful for configurating Kong entities. Users can use basic auth, LDAP or OIDC authentication to protect Kong manager. In today’s post, I will talk about setting up up OIDC authentication for Kong manager and how to map IDP groups to Kong groups.

Prerequisite:

You might be wondering why I write this post when users can just follow official documentations. The reason is that official docs can be too simple sometimes and it does not cover enough detail to explain how it works.

Parameters

There are 4 kong parameters you need to use. enforce_rbac, admin_gui_auth, admin_gui_session_conf and admin_gui_auth_conf.

  • enforce_rbac
    If you don’t set this variable, you will get Error: enforce_rbac must be enabled when admin_gui_auth is enabled. Make sure you set this to true.
  • admin_gui_session_conf
    This variable is used to specify configuration for the session plugin used by Kong manager. If you don’t set it, you will get admin_gui_session_conf must be set when admin_gui_auth is enabled error.
  • admin_gui_auth
    This variable is used to specify which authentication method you want to use. Currently Kong manager supports basic-auth, ldap-auth-advanced and openid-connect.
  • admin_gui_auth_conf
    In this tutorial I will use this variable to configurate OIDC plugin for logging in Kong manager.

Session settings of Kong manager is well explained on Kong’s official doc here. Please read it first and decide what you need to use. For demonstration purpose, I will use below for admin_gui_session_conf.

1
2
3
4
5
6
{
"cookie_name": "kong_manager_session",
"cookie_secure": false,
"secret": "manager_secret",
"storage": "kong"
}

OIDC Configuration Explain

In the official doc, the example of admin_gui_auth_conf is as below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{                                      
"issuer": "https://accounts.google.com/",
"client_id": ["<ENTER_YOUR_CLIENT_ID>"],
"client_secret": ["<ENTER_YOUR_CLIENT_SECRET_HERE>"],
"consumer_by": ["username","custom_id"],
"ssl_verify": false,
"consumer_claim": ["email"],
"leeway": 60,
"redirect_uri": ["http://localhost:8002"],
"login_redirect_uri": ["http://localhost:8002"],
"logout_methods": ["GET", "DELETE"],
"logout_query_arg": "logout",
"logout_redirect_uri": ["http://localhost:8002"],
"scopes": ["openid","profile","email","offline_access"],
"auth_methods": ["authorization_code"]
}

You need to modify these values based on your IDP requirements. For example, issuer, client_id, client_secret, redirect_url need to be changed. You might also need to change scopes if your IDP requires different scope for authorization code flow. ( For example Azure requires a <client_id>/.default in scope).

One important setting you need to pay attention to is consumer_claim. This has direct impact on how you create username for your kong manager admins.

Kong was using email in the official doc, which is convenient but could be problmatic if you want to enable developer portal later.

What consumer_claim does is to map a claim from your IDP issued token to the username of Kong admin. For example, if the issued id_token has a custom claim "kong-admin": "john_smith", you can set "consumer_claim": ["kong-admin"] and then create your kong admin with username=john_smith.

You can create your Kong admin on Kong manager or via Admin API below. (Below requests create an admin on default workspace with super-admin privilege)

  • Create Admin User

    1
    2
    3
    4
    5
    6
    7
    curl --request POST \
    --url http://localhost:8001/default/admins \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --header 'Kong-Admin-Token: <RBAC_TOKEN>' \
    --data username=john_smith \
    --data [email protected] \
    --data rbac_token_enabled=false
  • Assign Role to this User

    1
    2
    3
    4
    5
    curl --request POST \
    --url http://localhost:8001/default/admins/john_smith/roles \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --header 'Kong-Admin-Token: <RBAC_TOKEN>' \
    --data roles=super-admin

Once I’ve put the right values in admin_gui_auth_conf and start Kong, when user log in Kong manager as john_smith, he will be forwarded to IDP to authenticate themselves.

Group Mapping Explain

As we can see from above, users get their privileges from their assigned role(s). If we don’t set their role, they won’t see anything after log in. If there are only a few kong admins, it might not be an issue, however, it will be a problem when you have a lot of admins.

Luckily Kong supports mapping groups claims from IDP token to a Kong Group. The official document explains it clearly.

What you need to do are below:

  1. Create Kong groups.
  2. Assign roles to each group.
  3. Match authenticated_groups_claim to the claim variable name and make sure group claim value is the same as the kong group name.

For example, if the groups claim from IDP’s token is "groups":["kong-super-admin"], we need to set authenticated_groups_claim=groups and create our Kong group name as kong-super-admin and assign appropriate permission to this group.

Add groups claim to different IDP

The method to add group claim to id_token can be tricky. For example, I haven’t found a way to add group names to AzureAD issued id_token. What I can add in the id_token is something like "groups":["2354a1b9-a8c6-426a-a827-b7b97895b453"]. so I have to create my Kong group name to 2354a1b9-a8c6-426a-a827-b7b97895b453.

Below are the steps to add group claims for the IDPs that I have tested. I will add more if I got a chance to play with other IDPs.

Keycloak

Keycloak is very flexible and easy to use. Users can choose to add groups claims to a client or to a scope.

Add to a client

  1. Go to Clients tab on the left penal and click the client you want to use.
  2. Go to Mappers tab
  3. Click Create button
  4. Choose Group Membership for Mapper Type and name your group claim in Token Claim Name. Normally I will use groups in both Name and Token Claim Name.
  5. Full group path is on by default, this will show the full path if you have subgroups. It will add / in front of the group value. If you don’t use subgroups, it might be better to turn it off.

After that ALL tokens issued for this client will include groups claim.

Add to a scope

Users can also add groups claim to a custom scope.

  1. Click Client Scopes on the left penal of dashboard and click Create.
  2. You need to create a scope name. I name this scope groups and Save.
  3. You should see Mappers tab now. You can just follow above steps (from step 2) to add Group Membership.
  4. Add newly created scope to client.
    1. Go back to Keycloak Dashboard ➡ Clients ➡ select the client you want to use.
    2. Go to Client Scopes tab. Add groups scope as optional scope.

After that, if you need groups information in your id_token, you can request it with scope groups.

As this post is about using OIDC for kong manager, to use the group information, you need to change "scopes": ["openid","profile","email","offline_access"] to "scopes": ["openid","profile","email","offline_access","groups"] to get the group claim and use it with authenticated_groups_claim.

Auth0

To add group values to Auth0 applications, you would need to use their Authorization Extension. Here is the official doc.

Here are the steps:

  1. Install extension
    • Log in to auth0 deshboard → Extensions on left penal
    • Search Authorization and install the plugin
  2. Config Extension
    • Click this extension
    • Click Groups tab and then create groups
    • Add users to groups
  3. Add claim via Rules
    • Go back to Auth0 dashboard → Auth PipelineRules on left penal.

    • Click Create → Empty rule

    • Give it a name and then put in below code. (This code can be found on official doc here)

      1
      2
      3
      4
      5
      6
      7
      8
      function (user, context, callback) {
      var namespace = 'http://yourdomain/claims/'; // You can set your own namespace, but do not use an Auth0 domain

      // Add the namespaced tokens. Remove any which is not necessary for your scenario
      context.idToken[namespace + "groups"] = user.groups;

      callback(null, user, context);
      }

There is a catch here. Auth0 requires Namespaced Custom claims hence users are not allow to use groups as the group name. From above code you can see users can define groups claim name with namespace variable. For example we can use something like “http://aufomm/demo/groups" as group variable name.

You will get "http://fomm/groups": ["kong-super-admin"] returned from id_tokens. To use this group information with Kong manager, you need to set authenticated_groups_claim=http://aufomm/demo/groups

Okta

Okta developer account comes with default authorization server. Normally its url will be https://<yourdomain>.okta.com/oauth2/default. Users can choose to create a new authorization server or use existing one.

Here are the step to add group claim to authorization server:

  1. On Okta Dashboard, go to Security → API
  2. Click the authorization server you want to use.
  3. Add groups claim
    • Create Scope (optional)
      Go to Scopes tab and create a new scope groups
    • Add Claim to all application
      1. Go to Claims tab
      2. Click Add Claim button
        • Enter groups as name
        • Select ID Token in Include in token type
        • Select Groups in Value type
        • Select Matches regex and .* in Filter
        • Include in Any scope or choose The following scopes and then enter your scope name groups we define above.

If you choose Any scope you can get groups claims in your id_token for all your requests through this authorization server. Otherwise you need to request groups scope specifically to get this claim.

The group claim you get looks like "groups":["Everyone","kong-readonly"]. We can see there is a value Everyone in it. Unless you want to create a Kong group for Everyone, please don’t create a Kong Group called Everyone.

Azure

This could be the easiest IDP we’ve talked about today although I am still not able to find a way to show real group name in id_token.

If you know how to set up group claims on AzureAD correctly, please leave me a comment. Thank you

Here are the step:

  1. Go to App registrations
  2. Select Token configuration on the left penal
  3. Click Add groups claim
  4. Tick All groups (includes distribution lists but not groups assigned to the application)
  5. Customize token properties by type → ID → sAMAccountName. Actually any selection selelction with sAMAccountName will work.

Now when you request token, you will get "groups":["2354a1b9-a8c6-426a-a827-b7b97895b453"] in your id_token. You need to create your Kong group name with this ID.

Woohoo, I did not expect to write such a long post before I started.

I hope this article can be of any help.