See what makes Kong the fastest, most-adopted API gateway
Check out the latest Kong feature releases and updates
Single platform for SaaS end-to-end connectivity
Enterprise service mesh based on Kuma and Envoy
Collaborative API design platform
How to Scale High-Performance APIs and Microservices
Call for speakers & sponsors, Kong API Summit 2023!
10 MIN READ
Jeff Broberg, William Seaton and Peter Sullivan from Styra also contributed to this post
API Gateway Authentication (AuthN) and Authorization (AuthZ) are important ways to control the data that is allowed to be transmitted using your APIs. Basically, it checks that a particular identity has permission to access the API, using a predefined set of credentials.
This blog post describes how to use Kong Gateway Enterprise, Styra Declarative Authorization Service (DAS) and an external Identity Provider to implement Authentication and Authorization flows for the Gateway layer.
These processes, together, enable very fine-grained, context-rich authorization requests for your API Gateways. By consuming the information and context presented by the consumer provisioning processes (the user’s identity, their entitlements, and other context), these processes allow for distributed authorization decisions based on centralized authentication, which would not be possible to be performed by a single user or consumer database. Only within this context is it possible to have context-based authentication (eg., considering date and time, IP address, etc.), multi-factor authentication, and the like.
Applications basically solve these issues in two ways:
The first option is clearly not recommended for a microservice, hybrid multi-cloud deployment scenario. It’d quickly become a very difficult infrastructure to support and evolve. Embedding AuthN or AuthZ logic in your application will act as a negative influence towards a cloud-native services architecture.
In fact, Separation of Concerns, one of the main principles in Computer Sciences, should be pursued at all costs. The principle, formalized by Edsger Dijkstra in his seminal white paper “On the Role of Scientific Thought”, states the following:
“…It is what I sometimes have called “the separation of concerns”, which is yet the only available technique for effective ordering of one’s thoughts, that I know of.
This is what I mean by “focusing one’s attention upon some aspect”: it does not mean ignoring the other aspects, it is just doing justice to the fact that from this aspect’s point of view, the other is irrelevant ….”
AuthN and AuthZ are two of these types of aspects or separation of concerns.
While the Authentication processes tend to be implemented in a centralized environment, Microservices Authorization processes are inherently distributed. Typically there are two levels of abstraction for access control policies:
Practically speaking, the Reference Architecture for both AuthN and AuthZ process should be something similar to the following:
As depicted in the diagram, the Authentication and Authorization processes are distributed. Note that one of the main benefits provided by an architecture like this is to follow the Separation of Concerns principle:
Kong Gateway has a library of plugins that provide simple ways to implement the best known and most widely used methods of API gateway authentication. Here are some of the commonly used ones:
Please, refer to the following link to read more about API Gateway authentication:
At the same time, Kong Gateway also utilizes OPA (Open Policy Agent) plugin to implement Access Control policies. OPA, developed by Styra, is an open-source project donated to the Cloud Native Computing Foundation (CNCF), where it is a graduated project, alongside tools like Kubernetes..
Styra DAS is the enterprise-grade control plane for OPA, the industry first and only. With OPA and Styra DAS, teams have a single, consistent way to implement authorization across all their API gateways and more, including Kubernetes deployments, microservices and apps.
Not only does this mean teams can learn a single paradigm, and then apply it everywhere to save time, it also means that new tools, services, APIs or infrastructure can all be more easily governed and secured.
Styra solutions let developers, DevOps and security teams mitigate risks, reduce human error and accelerate application development. The combination of OPA and Styra DAS ensures that authorization in today’s complex environments can be controlled and audited across teams, clusters and clouds
Of all authentication mechanisms listed before, OpenID Connect (OIDC) is the preferred one for advanced requirements. In fact, when applying OIDC to secure the APIs, we’re delegating the Authentication process to an external entity, called an Identity Provider (IdP).
OIDC is a standard built on top of OAuth and JWT (JSON Web Token). Please, refer to the official OpenID Connect documentation to learn more about OAuth/OIDC and its Flows.
There are so many different variations to describe an API consumption process. Here’s an example:
Styra DAS plays the Authorization Control Plane role and, as such, pushes policies to OPA, which is the Data Plane. All request authorization happens in OPA
Authorization is the process that takes place after Authentication. It should control what kind of operation the authenticated user can perform. The rules that describe allowed or denied access control are called Policies.
An Authorization Framework has these components, as described in the XACML model:
With the components described above, the Authorization flow should go through the following steps:
The following post describes how OPA implements the Authorization Framework.
There are a variety of options for enabling API authorization using Kong Gateway, Open Policy Agent (OPA) and Styra DAS. Fortunately, there are a number of best practices that can help you quickly and easily deploy this functionality, while customizing the authorization deployment for the particulars of your environment. For instance, Styra best practice tutorials show you how to deploy a sample application using Styra DAS Quick Start and Kong Gateway Enterprise.
The example deployment is shown below. In this proposed application flow, an HTTP web server allows employees of a sample organization to obtain salary details, while exposing an enterprise HR dashboard.
The diagram depicts Kong Ingress Controller, which manages external access to HTTP services in a Kubernetes cluster using the Kong API Gateway. It configures Kong using Ingress resources created inside the Kubernetes cluster. Check the official Kong Ingress Controller documentation to get it installed.
As you can see, requests are authorized using the Kong Ingress Controller and OPA authorization policy — which, for instance, might include a users’ authentication details (including their role in LDAP or Active Directory, for example), as well as more fine-grained policy detail, such as their location, time of log in, or even their seniority or level of budget controlled within the organization. Each of these latter details can be easily configured using OPA. This sample application demonstrates not only the ease of deployment for combined authentication and authorization decisions, but the flexibility provided by OPA, Kong, and Styra DAS.
For more information, please see our tutorial guide for enabling OPA authorization with Kong Gateway Enterprise.
To exercise a little bit the topology we have described so far here are some Kubernetes declarations to define an Ingress and Authentication and Authorization policies.
The environment, as described in the previous section, comprehends Kong’s Kubernetes Ingress Controller and OPA, both running on a Kubernetes Cluster, and Styra DAS. The Kubernetes Ingress Controller configures Kong Enterprise Gateway using Ingress resources created inside the Kubernetes cluster.
The Authentication policy is responsible for integrating with an external Identity Provider (IdP) to (1) authenticate the API Consumer and (2) issue an JWT-based token. The Gateway will take care of the IdP integration as well as the token validation. The example below is used for the OAuth 2.0 Client Credentials Grant.
The Authorization policy, on the other hand, takes the JWT to evaluate if the API Consumer is capable of accessing the existing Kubernetes Service exposed by the Ingress.
This is a very simple Kubernetes Service definition based on the external and public httpbin.org service.
cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Service metadata: name: ext-service namespace: default spec: type: ExternalName externalName: httpbin.org EOF
Kong for Kubernetes Ingress Controller exposes the Kubernetes Service with the path “/route1”
cat <<EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: route1 namespace: default annotations: konghq.com/strip-path: "true" spec: ingressClassName: kong rules: - http: paths: - path: /route1 pathType: ImplementationSpecific backend: service: name: ext-service port: number: 80 EOF
The Ingress will be protected by an OIDC Authentication process. That is, the API Consumer has to present previously created credentials to get a token from the Identity Provider and then consume the Ingress.
First of all, we instantiate the Kong OIDC plugin.
cat <<EOF | kubectl apply -f - apiVersion: configuration.konghq.com/v1 kind: KongPlugin metadata: name: oidc namespace: default config: issuer: "<YOUR_IDP_ISSUER_ENDPOINT>" scopes: - scope1 cache_ttl: 10 plugin: openid-connect EOF
Now, we can apply the plugin to the Ingress with a Kubernetes annotation:
kubectl patch ingress route1 -p '{"metadata":{"annotations":{"konghq.com/plugins":"oidc"}}}'
The policy, written in Rego, will allow the Ingress consumption only by a specific Client Id. The API Consumer receives an error if it submits a request with a token issued for a different Client Id. Please refer to the OPA documentation for more information about Policies and declarative language Rego.
Below is the policy you will create within Styra DAS:
package policy.ingress default allow = false allow = true { is_cid } is_cid { token.payload.cid == "clientid_xyz" } headers["header-from-opa"] = "accepted" { allow } headers["header-from-opa"] = "rejected" { not allow } bearer_token := t { v := input.input.request.http.headers.authorization startswith(v, "Bearer ") t := substring(v, count("Bearer "), -1) } token = {"payload": payload} { [header, payload, signature] := io.jwt.decode(bearer_token) }
To configure the Ingress for our OPA Authorization Policy, we will use Styra DAS. Within the Styra DAS workspace, you will need to Create System for Kong Enterprise Gateway and then add the above Rego policy to your system. To configure Styra DAS, navigate to System name (the name you choose for the system) >> Settings >> Install, before copying and running the three listed commands in kubectl. These commands will (1) Configure Kong plugin for OPA authorization, (2) Configure OPA, and (3) Install Styra Local Plane (SLP).
(Note: this process is described in detail in the Styra DAS Quick Start, as well as in the Styra DAS tutorials. To create a new Quick Start within Styra DAS, select Getting Started from the help menu, shown as a question mark in the top-left corner, before choosing Take a tutorial and selecting Kong Enterprise Gateway.)
Now, add the Rego policy for your system. Navigate to System name >> policy >> ingress >> rules.rego where you will input the above JWT-based rule. In the editor top-left corner, select Code, shown as left-right arrows, and simply copy and paste the above Rego to replace the sample policy. Now, Publish the rule. With this policy configured, we can call the Ingress and receive an authorization decision. For more detail on this process within Styra DAS, see the free Styra Academy course on Microservices Authorization.
Note that, this time, the Ingress has two plugins enabled:
kubectl patch ingress route1 -p '{"metadata":{"annotations":{"konghq.com/plugins":"oidc, opa"}}}'
The Ingress is consumable only with the clientid_xyz Client Id:
# http <KONG_GATEWAY_ADDRESS>/route1/get -a clientid_xyz:clientsecret_xyz HTTP/1.1 200 OK Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: * Connection: keep-alive Content-Length: 1493 Content-Type: application/json Date: Mon, 18 Jul 2022 19:31:05 GMT Server: gunicorn/19.9.0 Set-Cookie: session=U7mi9fXuwlfumxX_Y9eOkQ|1658176265|VwOoxOYtd63-ki7CYT7OGZWiXW5xLcBw7qVKp03Xc7qYQvXtsiHrMHlu9zDk6ZaF1SYaQQKBiJQsPn4HG_fhe8TaBtqbKzjMRDQ8RFykkK7VmBoYkQer28kwa7YxvcCT0GV3vUH1E4HyOGHRA7kpAQJrDkPk18EE-47OgKGuHYgA_wJaEoHzsZapzTw3BBqnzIIHlrM6KtXdg31DTanqIoYfk6FWPWokTOXePFyEE-Rx5MUwu5DuSz8WrSTggy1K0n82_NykGcyLLKheP55Kdl_-5NNshxmTPdz_TOOYr12iegI5omT6Lx0Vde9J5MFTeqBdKUuISREL1DV-K7qm6eLHgTNxVNpvzM9WZ1jiKWpwbNQafKhkMo-zXl6Dz_p9PVSnN3cvHqUL8Iar_xrAbjPPwxCwNesVkYT-zIS60ndijnEN1_EN6Zz45bEHRdvqkqDQ-wuJlQMTzLWUFYttcq8Y1mGmpwGD46MaUOup_USNUl9axDU1yNM63teES7107Y424nQWX-d4QplssJw0rZXIVdZiCgV7mWj4y69uqBIQukcEo6KpXRN-BIqFe0CURGDrNad_sX7yAYU56pDWuUOhJbeI-08R_Fyuz8nqOhwkCyeglKa93GjD5nxFtqm5wmxY7KX9CePmAubni8b1SdnIbPrGIGxwOCnx3mrIMsXMcQ74I4AAeaPstuKaXXiHCcK7nkGEj_xH-m8GgXFjKYRRAVEmR9CWAGvfmZRzJCZ3LWa3GQrWfY7qCgMCVUKE2dsJ2bvhMtpWjCIHabrDe9AHdebqo7Oe_OpGMETryPUVVfH8Hi3v1NObZnWfoONXkL6CRgo-Q9U7w_4drfWsrAxlRg0L7NKW4QQ5bNhI7IaQlGVWnP9XWIry4sAKvYWBbjK-lvyD2vVB2Z0aibAV1mJSB6QVT5NGUcQ7HWa_9jvQdhA5p3qQyYv9n1PdD78bSZuKytE-96E0u2jLhrdTqveRAMEJhuqTynr1jf3dTM0cWWAkWYu0iprA9U2Se2Ut8ooybv_cZOxiTalGShasrPs412rTO_Diktc55Ub1ru58BwOYw70aWZceTOu_oiA8s1o6rkQCpPqMkHmzRhfc9TwA4AKjoJJ781MpmGbEFzk06bzClqef2w7TjQ0QpsL1OOdMJ8tA6TeBrnJ8e2Ae3MzEGvwPmDj5ViRntRQ5IhbexRATUNLJURf3ZeD6Exibb4F5-PMz-vK23_o49Lu5mQQ_L9DrWU6EdUFhg-61Y_I|tPbO5RmEuMW7OqCClHU8oguttLE; Path=/; SameSite=Lax; HttpOnly Via: kong/2.8.1.2-enterprise-edition X-Kong-Proxy-Latency: 135 X-Kong-Upstream-Latency: 166 { "args": {}, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Authorization": "Bearer eyJraWQiOiJoRVNaOXN3cThRUkRlUDZBclZZZHo5S0VQWWlQX2E3a3FhQ3JCcEpjMVpZIiwiYWxnIjoiUlMyNTYifQ.eyJ2ZXIiOjEsImp0aSI6IkFULjZWdHZIUUROUXVOR3ZiemRLMFZ0b3FYOUZneU5mVjhKeEhYQ05pS2pZbVEiLCJpc3MiOiJodHRwczovL2Rldi01NjkwMDUub2t0YS5jb20vb2F1dGgyL2RlZmF1bHQiLCJhdWQiOiJhcGk6Ly9kZWZhdWx0IiwiaWF0IjoxNjU4MTcyNjM2LCJleHAiOjE2NTgxNzI5MzYsImNpZCI6IjBvYTNjN2dua2Zkekc3RjA3NHg3Iiwic2NwIjpbInNjb3BlMSJdLCJzdWIiOiIwb2EzYzdnbmtmZHpHN0YwNzR4NyIsImFwcGxpY2F0aW9uX2lkIjoiMG9hM2M3Z25rZmR6RzdGMDc0eDcifQ.LLnaFmYTJNXxJIh3qBcF8bCNJNr_cWoOInxS9QQnwTzqjdIAaOZEXrNHVLpdAsasEBAllKs2b6UN-r3PohzWi653uY6c1URWcRs683ugWmt9XARXJIl0OqHRDcQ4tmuDzOvH12Usb1TrcaQJ-PbeP43YyxN_9bQUADaX0LbUQxNMIh7QndFRu_0FLzj_EMDR3xV1s03MtFkrWrzq9Hl6ar7QUic46hcX7TZW7tPbWjbrw7ZqiG2_Wepja5J6yjc-spL7ZqvGeZCVbz3bsS8sb8vcsD6iWzyIF3N87fHh6aHmn4rPN0WbsYR2nq56Px73iYIVchk_bWNip2kgCEr_HQ", "Header-From-Opa": "accepted", "Host": "abbfaa58fae70437fbf0cb5219c8163f-422507362.eu-west-3.elb.amazonaws.com", "User-Agent": "HTTPie/3.2.1", "X-Amzn-Trace-Id": "Root=1-62d5b4f9-3191e4c76348117a589e833e", "X-Forwarded-Host": "abbfaa58fae70437fbf0cb5219c8163f-422507362.eu-west-3.elb.amazonaws.com", "X-Forwarded-Path": "/route1/get", "X-Forwarded-Prefix": "/route1" }, "origin": "192.168.95.142, 35.180.136.165", "url": "http://abbfaa58fae70437fbf0cb5219c8163f-422507362.eu-west-3.elb.amazonaws.com/get" }
If we use a different Client Id, even submitting valid credentials, we get an error:
# http <KONG_GATEWAY_ADDRESS>/route1/get -a clientid_abc:clientsecret_abc HTTP/1.1 418 Connection: keep-alive Content-Length: 26 Content-Type: application/json; charset=utf-8 Date: Mon, 18 Jul 2022 19:30:59 GMT Server: kong/2.8.1.2-enterprise-edition Set-Cookie: session=4yrNrmut7x64SO9xKLlDyQ|1658176259|2FD5k8uNIv0MfVW1b64K2rYtYZ3ws97MSMG_rP__COD3q-UTS34AK-HYVbS6cWmxTHA5B7ayz98KX8B-8RNDP_2qgdStz8482HWbkXEkCvBpZ3Ynyq_9zXQWwrHLCdqAKqCWk20VAnkS6JD-G-FMD7bbX-Bkm1PjvchVkhWIl7f0wmK4R8YTuCdSxm43Jut617VVLf9vHNwP9L5olHXn2v4QAv7Ml_Id7WZhaYLIc232N-hEQPYU6x-jcTkJQF3q7FlSJqbyEza8IVZvm3KLQLNaNeI9_qg5-C-nSJwH8QU65yBRVcVGiSUQ2Nuc8wSjhN9RDRcWxTn3T1Wgcoz5Ze1NUFCzImD56ZpFuTm3_OzJKOzeMhh31uyZflzDLdEAx3DWIdL3_OTHAPx4TyW4YPm9mMPw0uHLn9bJLdOhySnNEEeVIFXjkUVmm9crupf_Y_yJUj8MHzr4oP1bGpECXhMLUopDfrkI_pruuedJk5ObEOBgzlG_aQSQZ51qslyBOHUaDEULk2pK1Mu2QljPod74vKJJYPpfogtlAscQQZLD5R_qcvQd4AIBeVPgh3Z4qxt_QZOqOjuLaMZuHAlXRoPNOc0TVNsHgffZBbtflldUh0gqHyLAEA1eXkFUl7ySVcyRSXMYDO1T0cL9lp4uld6w0NbtmdTS6B4CqmvaGqj6dht1LQGMr2EXP75BpkdDa3rBbkmo3-g5dIF-d7tpzMvoRbLKkl156pUG0oqq83ReW-zB_Z2l34dwKeIpSWxs6xFzVJoL66ircaJndyZUHYShFMATAScmHcnpEzqOJE3x6bzpHgLVz3io84TWf3G25zGkQzAbCUMt_WFGzQvq8evH9R42oRIFyJCeI5pBlJcZrUmw6JkCVver692Yj7DQnarQjqgz0ZKFv8vPmTLON8je_ju6zkbn7vZVQs_MkODWJQr-VdzGO15hpFqkkjLPJOxa-BkmOaml42Ozd0hw4vLBp8Z2brRBU7aQxjVhyz0TtEXORSGzFRydJGRfPSUXPLT0SbaX7jO3tS5v4rrsz8uXG6Jgsh7gBlWNefBv_P2UyJRmeS4M8MWEXt4pBrcX_NhMwdHldvwHKp66g2y1U4UikQSMmpheQQHoqS6jT3o8CZLIKbsMihY2gKMUHC8RUID-25Pk84vru0C8G8u_i21iyZeWruXscx6wra-75QxxiiM9jmkYSM8Ty1EmIiLChbFauHoWg-BwmDC_pRr7i7r2nXcemBCtU0PE2ga3I-A|vDK91l_SzR0L0mZS33u15ZVjp4c; Path=/; SameSite=Lax; HttpOnly X-Kong-Response-Latency: 125 header-from-opa: rejected { "message": "unauthorized" }
This document has described some of the main use cases to implement Authorization processes. Several other use cases are also feasible and supported by both products.
Using Kong Gateway Enterprise and Styra make it easy to run services by providing consistent security and control for services and multiple use cases and scenarios.
You can learn more about the official documentation of both products here: Styra and Kong Gateway Enterprise.
Share Post
Learn how to make your API strategy a competitive advantage.