On this page
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.
The default docker image has been customized to copy in the following two plugins:
|Zone Transfer||Plugin created in this how-to, which implements custom routing logic|
|lua-resty-jwt||Used by the plugin to parse JWTs in LUA|
FROM kong:3.0.0-alpineUSER rootRUN luarocks install lua-resty-jwtCOPY reverse-proxy/kong/zone-transfer-plugin/* /usr/local/share/lua/5.1/kong/plugins/zone-transfer/USER kong
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.
_format_version: '2.1'_transform: trueservices:- name: curityurl: http://internal-curity-eu:8443routes:- name: defaultpaths:- /plugins:- name: zone-transferconfig:eu_host: internal-curity-euus_host: internal-curity-uscookie_name: zoneclaim_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.
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.
---- 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' thenreturn nilend-- First try to find a value in the zone cookielocal zone = get_zone_from_cookie(config.cookie_name)-- Otherwise, for POST messages look in the form bodyif zone == nil and method == 'post' thenzone = get_zone_from_form(config.claim_name)end-- Update the host name if a zone is foundif zone == 'eu' thenngx.ctx.balancer_address.host = config.eu_hostelseif zone == 'us' thenngx.ctx.balancer_address.host = config.us_hostendend
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:
kong:image: custom_kong:2.8.1hostname: internal-kongports:- 80:8080volumes:- ./reverse-proxy/kong/kong.yml:/usr/local/kong/declarative/kong.ymlenvironment: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'
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:
*** 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"
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.