Secure REST API application using Gluu Gateway and OAuth plugins
You can now secure any API or web application with zero lines of code using a free open source proxy called Gluu Gateway. As application developers, we want to focus on core functionality — not security. Putting a proxy in front of web applications or API’s to enforce security is a well-trodden path to securing content. There are many excellent proxies out there that can help you do this. Gluu Gateway has some unique features —it is the only proxy to support the User Managed Access protocol, which is handy if you need to interact with a user post-authentication (e.g., for consent). It can handle both simple and complex requirements for authorization, making it an interesting option to help you secure your web content.
What is Gluu Gateway?
Gluu Gateway (GG) is an authentication and authorization solution for APIs and websites.
GG bundles the open-source Kong Community Edition 2.x Gateway for its core functionality and adds a GUI and custom plugins to enable access management policy enforcement using OAuth, UMA, OpenID Connect, and Open Policy Agent (“OPA”). In addition, GG supports the broader ecosystem of Kong plugins to enable API rate limiting, logging, and many other capabilities.
In this blog, I am focusing on securing a backchannel API application. To accomplish this, I will use the gluu-oauth-auth plugin to authenticate the request using an access token.
You can read more about the OpenID Connect OAuth 2.0 Overview and Security Flows for a more detailed description of the terms. If you’re an Angular guru, you may also want to check out the Single Page Application SSO With Gluu CE using AppAuth JS.
Gluu Gateway OAuth 2.0 Security Flow
The gluu-oauth-auth plugin performs two important functions:
- Introspect the token: verify the token is active , and cache the token key until expiration, to speed up subsequent validation of this token value.
- Correlate the OAuth Client from the access_token with a “consumer” in Kong. This is important because many policies (such as rate limiting), or based on the consumer id. There is no need to authenticate the client — authentication already happened at the OAuth Authorization Server (“AS”) token endpoint prior to obtaining an access token. The client_id claim in the access_token verifies the identity of the client that obtained the token.
For example, an app may obtain an access token using basic authentication at the token endpoint of an AS by presenting its client_id/client_secret in the authorization header. After this, the app can use the access token to call endpoints on the Gluu Gateway. This is covered in the howto about writing a Single Page Application SSO With Gluu CE using the AppAuth JS .
In Gluu Gateway, you map the OAuth client_id to a Kong Consumer ID. This can be accomplished via Kong’s configuration API. Or you can do it in the admin GUI, which may make it easier, because OAuth is the only mechanism you can use to define clients. Kong of course supports other mechanisms to authenticate consumers. But we don’t want Kong to do this — we want our OAuth Authorization Server to handle client authentication.
The sequence diagram below may help you understand the flow for an Angular application. Note, “PKCE” is used in cases where we can’t safely store a client secret in the client. For example, in a browser application, there is nothing we can do to stop a user from looking at the code.
- The request hits Gluu Gateway first — it is the Internet facing endpoint.
- You need to send the access token in the Authorization header — just like you would do for any OAuth protected API.
- The GG OAuth plugin introspects the token (or validates the signature if it’s a JWT). If the token is not active, GG returns 401 — Unauthorized.
- Before proxying the request to the upstream API endpoint, GG checks to make sure the access token has the required scopes.
- If the required scopes are present, GG proxies the request, gets a response, which is returned to the Client. If the required scopes are not present, GG returns 403–Forbidden.
Voila! OAuth access management without a single line of code! All you need to do it to install Gluu Gateway, map your OAuth client to a Kong consumer, and register the upstream API. Following is a more detailed description of how to do this.
Prerequisites
Gluu Server
This is our OAuth Authorization Server. The Client software, or Relying Party (“RP”) will get an access token from the Gluu Server /token endpoint — requesting the required scopes. So the first step is to install a Gluu Server, if you don’t already have one. There are a number of ways to do this — you can use one of the Linux packages (Ubuntu, Centos, Red Hat or Debian), you can use Docker, or you can even use Kubernetes. Probably the simplest way is to use the Linux packages, which install all the components of the Gluu Server in a simple file system container (in /opt/gluu-server). This is normally a three step process: install the package, start the gluu server, run setup. But for detailed instructions, see the Installation Guide for the current version in the official Gluu Server documentation.
Gluu Gateway (GG)
In OAuth jargon, GG is our Resource Server (“RS”). For example, it publishes the endpoints that the Client will call, presenting the access token. Gluu Gateway also has a number of distributions. See the docs for Gluu Gateway to pick the distribution that makes the most sense for you. Note: you probably want to install GG on a different VM then your Gluu Server. If you do install GG on the same VM, I would suggest setting up a different virtual ethernet interface and making sure that the GG processes bind to this IP. This is a little out of scope of this howto article… so the easiest things is to probably just use a different VM!
After installation of GG you will get the following components:
Kong Community Edition 2.x: Kong Provides the core API gateway functionality. This is the software which handles the request, applies the security plugins
, and enforces the security policy per the plugin configuration. It provides two endpoints: Admin Endpoint
andProxy Endpoint
. The Admin Endpoint
is used to configure upstream apps, services, routes, consumers, and plugins. The Proxy Endpoint
is the final endpoint which accept request from clients — in our case, the angular application calling this endpoint for protected resources.
- GG UI: You can configure your backend API, routes, consumer, and plugins in the Admin GG UI Panel
- GG Plugins: Gluu Gateway provides custom plugins to enable access management policy enforcement using OAuth, UMA, OpenID Connect and Open Policy Agent (OPA). Check here for the list.
- OXD: oxd is a client middleware. GG doesn’t obtain a token directly. It calls an oxd API, which does the heavy lifting. This keeps the code simple in the Kong plugin. Implementing asymetric client authentication in Lua would have been a lot of work for the GG developers. oxd is a certified OpenID Client, so calling one method, like “getToken”, was a lot easier. Learn more about oxd here.
Backend API(Protected Resources)
Also known as Protected resources,
Upstream App,
target
or backend API
. For this post, I am using a demo Node.js application available here. This is the backend application which is called by the frontend software client.
Angular Client
I am using an Angular Client to access protected resources. This is the frontend application which sends a request to Gluu Gateway. Check out Single Page Application SSO With Gluu CE using AppAuth JS for configuration and implementation details.
Consumer OP Client
This is the same client that I am using in the Angular App. I call this the Consumer OP Client
. You will need to register your clients client_id
in GG in order to grant them access to protected resources.
Configuration
There are 4 main steps:
- Configure your Backend API Application into Gluu Gateway Service
- Configure Kong Gateway Routes
- Add OAuth Security
- Configure
Consumer OP Client
1. Configure your Backend API Application into Gluu Gateway Service
We need to register the Backend API application with Gluu Gateway’s Service
Kong entity. After authentication, GG uses this configuration to request and get a response from the Backend API.
My API backend is running on http://localhost:3000
so I configured service for this. You will need to configure service based on your API.
Follow these step to add a Service
using GG UI
:
- Click
SERVICES
on the left panel - Click the
+ ADD NEW SERVICE
button
Fill in the following boxes:
- Name:
test-app
(you can use any name here) - URL:
http://localhost:3000
2. Configure Kong Gateway Routes
The Routes
is specifically used by the GG Kong to recognize and accept the request. It is a child entity that we need to add to the Service
object.
Follow these steps to add a Route
using GG UI
:
- Click
SERVICES
on the left panel - Click
test-app
service, which we created on the above step - Click
Routes
- Click
+ ADD ROUTE
button
Fill in the following boxes and click enter:
- Name:
test-api
(you can use any name here) - Hosts:
<your-server-host>
(this is the host of the Gluu Gateway proxy, which will be requested by the angular app)
I have GG on my server so I will use gluu.local.org
as an example. You will need to replace this with your host. Check the Gluu Gateway docs for more routing capabilities.
3. Add OAuth Security
There are many plugins available in GG which provide security. To make it simple, we will configure just one for this example.
- Click
ROUTES
on the left panel - Click
route id/name
withgluu.local.org
as the host - Click
Plugins
- Click
+ ADD PLUGIN
button - You will see
Gluu OAuth Auth and PEP
title and+
icon
Now you will see below the form and from here:
- Set
Disable
toOAUTH PEP Scope expression configuration
- Set blank to
OXD Id
,Client Id
, andClient Secret
(GG UI will create one separate client for plugin usage) - Leave
Headers
as is or configure per your requirements - Click
ADD Plugin
button
Tip: If you are a frontend developer, you know the CORS origin problem and preflight request problem. This problem occurs when you are calling APIs from a browser different from its origin(domain), in which case you need to add the Cors plugin, which by default comes with Kong CE. Check here for the Cors plugin configuration.
4. Configure Consumer OP Client
Follow these steps to configure the consumer using GG UI:
- Click
CONSUMERS
on the left panel in GG UI - Click
+ CREATE CONSUMER
button - Add
client_id
in theGluu Client Id
field. (this is the same client that you are using in the Angular App)
Now, we need to register this client client_id
into Gluu Gateway Consumer to allow them access to protected resources.
Configuration is finished here. Now you will need to call the protected API using GG Kong Proxy Endpoint.
Request to Proxy
GG Kong exposes the proxy endpoint on the port :443
so you need to call the API in your angular app and pass access_token
in the authorization header.
As per my configuration, I am calling my proxy endpoint https://gluu.local.org:443/posts
with access_token
.
Below is the angular code to call GG Proxy Endpoint:
this.http.get(
'https://gluu.local.org:443/posts',
{headers: {authorization: 'Bearer ' + this.accessToken}}
).subscribe((response) => {
this.images = response;
}, (error) => {
console.log(error);
});
If all is OK, you will get a response from the GG.
Conclusion
At a high level, implementing a piece of infrastructure like an API gateway makes sense when you have a lot of APIs. If you have just a few endpoints, it may be overkill. But there are advantages to this approach:
- Policy enforcement is not in code — it’s in the HTTP routing infrastructure. That means you can change the required scopes without touching your code.
- Your backend APIs are not Internet facing
- You can implement other security, like limiting transaction volume (i.e. how many calls per hour, day etc can a client make).
- Developers don’t need to know anything about OAuth — they can just code the functionality they need, and focus on fine grain authorization.
So this approach may not be for everyone. But GG is a great tool to have in your back pocket when the right use case presents itself.
Thank you!