/images/resources/tutorials/integration/tutorials-kong.png

Dynamic User Routing with Kong Open Source

Advanced Security
Download on GitHub
On this page

Intro

This tutorial shows how to implement dynamic routing of OAuth requests using a Kong reverse proxy. The code resources are available in the GitHub Repository link.

This routing capability enables companies to deploy the Curity Identity Server to multiple regions, while forwarding OAuth requests for users to their home region. The overall solution is described in the Implementing Dynamic User Routing walkthrough.

Docker Image

The default docker image has been customized to copy in the following two plugins:

PluginDescription
Zone TransferPlugin created in this how-to, which implements custom routing logic
lua-resty-jwtUsed by the plugin to parse JWTs in LUA
dockerfile
123456
FROM kong:3.0.0-alpine
USER root
RUN luarocks install lua-resty-jwt
COPY reverse-proxy/kong/zone-transfer-plugin/* /usr/local/share/lua/5.1/kong/plugins/zone-transfer/
USER kong

Proxy Configuration

The example uses the DB-less and Declarative Configuration which provides the simplest local deployment options. The Kong proxy routes are provided by a kong.yml file, which would be different for each stage of a company's deployment pipeline.

yaml
1234567891011121314151617
_format_version: '2.1'
_transform: true
services:
- name: curity
url: http://internal-curity-eu:8443
routes:
- name: default
paths:
- /
plugins:
- name: zone-transfer
config:
eu_host: internal-curity-eu
us_host: internal-curity-us
cookie_name: zone
claim_name: zone

The plugin comes into effect for all paths and supplies values for host names to the plugin's logic. The host name in the URL field will then be overridden at runtime by the plugin's calculated value.

Plugin Code

The code for the plugin is easy to follow and simply involves reading HTTP request values. The various responsibilities are broken down into functions in a standard way.

lua
12345678910111213141516171819202122232425
--
-- Try to read the zone value from an OAuth request
--
function _M.run(config)
local method = string.lower(ngx.var.request_method)
if method == 'options' or method == 'head' then
return nil
end
-- First try to find a value in the zone cookie
local zone = get_zone_from_cookie(config.cookie_name)
-- Otherwise, for POST messages look in the form body
if zone == nil and method == 'post' then
zone = get_zone_from_form(config.claim_name)
end
-- Update the host name if a zone is found
if zone == 'eu' then
ngx.ctx.balancer_address.host = config.eu_host
elseif zone == 'us' then
ngx.ctx.balancer_address.host = config.us_host
end
end

Docker Compose

In the repository's Docker Compose file, the overall deployment of the Kong reverse proxy is defined, which includes copying in the environment specific kong.yml file. In the example setup Kong runs on port 8080 and is exposed to the host PC at port 80:

yaml
1234567891011121314
kong:
image: custom_kong:2.8.1
hostname: internal-kong
ports:
- 80:8080
volumes:
- ./reverse-proxy/kong/kong.yml:/usr/local/kong/declarative/kong.yml
environment:
KONG_DATABASE: 'off'
KONG_DECLARATIVE_CONFIG: '/usr/local/kong/declarative/kong.yml'
KONG_PROXY_LISTEN: '0.0.0.0:8080'
KONG_ADMIN_LISTEN: '0.0.0.0:8081'
KONG_LOG_LEVEL: 'info'
KONG_PLUGINS: 'bundled,zone-transfer'

Working Plugin

When the reverse proxy is run as part of an overall solution, Kong outputs log messages to show zones received in OAuth requests, so that the plugin's behavior can be visualized:

12345
*** Found zone 'eu' in cookie, client: 172.19.0.1, server: , request: "POST /authn/authentication/UserName-Password HTTP/1.1"
*** Found zone 'eu' in wrapped token, client: 172.19.0.1, server: , request: "POST /oauth/v2/oauth-token HTTP/1.1"
*** Found zone 'eu' in cookie, client: 172.19.0.1, server: , request: "POST /authn/authentication/UserName HTTP/1.1"
*** Found zone 'us' in cookie, client: 172.19.0.1, server: , request: "POST /authn/authentication/UserName-Password HTTP/1.1"
*** Found zone 'us' in wrapped token, client: 172.19.0.1, server: , request: "POST /oauth/v2/oauth-token HTTP/1.1"

Conclusion

It is a standard job to implement dynamic routing in API gateways, and this is straightforward using Kong's extensibility features. When combined with the Curity Identity Server's multi zone features, a company can deploy a global IAM system with user data separated by region, and with good reliability.

Join our Newsletter

Get the latest on identity management, API Security and authentication straight to your inbox.

Start Free Trial

Try the Curity Identity Server for Free. Get up and running in 10 minutes.

Start Free Trial