The Kong Gateway
The Kong Gateway is an API Gateway to manage, configure and route requests to multiple APIs.
It's used to release a single address to access multiple APIs at the same time.
Objectives
This post presents a step by step to create a plugin with authentication using an external service. This solution is used when exists multiple services managed by Kong that extends the same authorization method.
The Original Problem
In our original problem the front-end needs to know how the addresses of all services to execute requests, and both services needs request the external authentication service to validate the authorization token.
Adding Kong
Now, the front-end knows just kong address and kong register all services to release requests. However, all services still require the external authentication service.
The Solution
Our solution, implements a Kong Plugin to validate the authentication in external service and just at success case the request to services is released.
Plugin Development
It's possible add some logics to execute during the Kong requests lifecycle. To do this, we add plugins with different purposes. In our case, we created a plugin named cutom-auth to request the external auth request and validate the authentication before requesting services.
The plugin structure contains two files developed in lua:
- schema.lua: This file is used to define the plugin configurations. In our case we defined the external auth request URL and the paths to ignore authentication.
- handler.lua: The core file to execute the plugin logic. Here is the request to external auth to validate authentication.
Bellow we can see the code of this two files:
schema.lua
local typedefs = require "kong.db.schema.typedefs"
return {
name = "custom-auth",
fields = {
{ protocols = typedefs.protocols_http },
{ consumer = typedefs.no_consumer },
{ config = {
type = "record",
fields = {
{ url = typedefs.url({ required = true }) },
{
public_paths = {
type = "array",
default = {},
required = false,
elements = { type = "string" },
}
},
},
}, },
},
}
handler.lua
local http = require "resty.http"
local ngx = require "ngx"
local cjson = require "cjson"
local ExternalAuthHandler = {
VERSION = "1.0",
PRIORITY = 1000,
}
function ExternalAuthHandler:access(conf)
local path = kong.request.get_path()
local publicPaths = conf.public_paths;
for i, pub_path in ipairs(publicPaths) do
if pub_path == path then
return
end
end
local client = http.new()
kong.log("Validating Authentication: ", conf.url)
local res, err = client:request_uri(conf.url, {
ssl_verify = false,
headers = {
Authorization = kong.request.get_header("Authorization"),
}
})
if not res then
kong.log.err("Invalid Authentication Response: ", err)
return kong.response.exit(500)
end
if res.status ~= 200 then
kong.log.err("Invalid Authentication Response Status: ", res.status)
return kong.response.exit(401)
end
local json = cjson.encode(res.body)
local user_info = cjson.decode(json)
kong.service.request.set_header("X-UserInfo", ngx.encode_base64(user_info))
end
return ExternalAuthHandler
Explanation
In schema.lua we defined two params:
- url: Used to set the external auth url to validate authentication. In our case, this request validates the authentication and returns the current user.
- public_paths: Used to set the service public paths. The paths mapped here will not require authentication validation.
In handler.lua have some steps. The access method is the entry point to Kong execute this plugin in lifecycle.
The first operation is execute a GET in URL defined to validate the authentication. In case the request returns an error or an invalid status the Kong will be exit with status 500 or 401.
In case of success the X-UserInfo header will be added to the request with the current user data mapped in a base64 string. The services can be use this header to validate authorization or get user data if necessary.
Conclusion
With this plugin the Kong can validate authentication before requesting services and the structure of the diagram solution is finished.
We validated the use of this plugin in I9Partner Company using Kong and multiple internal services.
Here is an example of this plugin usage mapped in Konga.
You can follow the repository to this project here.
Reference
Authors
Jefferson Xavier
Thyaki Takuno
A I9Partner initiative.
Top comments (2)
Hi, can you add git repo of this project?
Sure, here is: github.com/jeffersonxavier/custom-...