Skip to main contentArrow Right

This tutorial was written by Vivek Maskara, a software development engineer at Remitly. You can check out his website or X account to connect and see more of his work!


The Kong Gateway is a lightweight, flexible, and fast cloud-native API gateway that lets you configure, manage, and route requests to your APIs. The gateway acts as a reverse proxy, running in front of RESTful APIs, and it can be customized using modules and plugins.

The Kong Gateway enables users to decentralize applications and easily transition to microservices with little overhead. It simplifies securing APIs with built-in authentication, rate limiting, and encryption while improving API health and visibility through load balancing, health checks, and comprehensive monitoring and analytics.

In this tutorial, you will learn about the Kong Gateway and API gateway authentication. You will also learn how to implement authentication in the Kong Gateway with Descope Flows.

API gateway authentication

An API gateway is a component that sits between clients and backend services, functioning as a reverse proxy. It accepts API calls, processes them, and aggregates responses from multiple services to handle client requests efficiently. It simplifies the integration of microservices by providing a single entry point for client requests, reducing the complexity of client interactions with multiple services. It also provides tools for monitoring API health and scalability, including logging, analytics, and real-time monitoring, allowing developers to track service performance and availability.

The Kong Gateway is a scalable platform that lets you manage, secure, and optimize API traffic. It offers load balancing, rate limiting, and authentication features, making API management easier. With its open source core and enterprise-level extensions, Kong enables seamless API integration and high performance for modern applications.

Authentication is a key feature of API gateways that helps secure the APIs. Handling user authentication at the gateway level centralizes the auth process and makes it easier to manage. It simplifies the implementation of security policies, reduces the risk of unauthorized access, and enhances overall API security.

In this tutorial, you build a sample app using an echo server hosted on a Kubernetes cluster. The cluster uses the Kong Gateway to manage API traffic and endpoints. You integrate Descope for authentication, which generates JSON Web Tokens (JWTs) that are compliant with the OpenID Connect (OIDC), and use Kong to verify and streamline user access. The architecture diagram shows the lifecycle of an API request:

Fig: App architecture

If the request is unauthenticated, the Kong Gateway redirects the user to Descope for authentication. Upon completing the login/sign-up flow and sending it to the Kong Gateway, the user receives an authorization grant. Next, the Kong Gateway requests access and ID tokens using the authorization grant before making the upstream call to the echo service. This setup ensures secure, centralized, and efficient management of API requests and user access within the cluster.

Prerequisites

Before starting, you need to prepare the following:

Set up an echo server

Begin by creating a new directory for your application and navigate into it:

mkdir kong-api-descope-authn
cd kong-api-descope-authn

As you saw in the architecture diagram earlier, you need to deploy a service that exposes REST APIs. For this tutorial, you can deploy a simple echo server that responds by returning the clients’ requests. Navigate to the root of the project and create a file named echo.kube.yaml with the following content:

apiVersion: v1
kind: Namespace
metadata:
  name: echoserver
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echoserver
  namespace: echoserver
spec:
  replicas: 1
  selector:
    matchLabels:
      app: echoserver
  template:
    metadata:
      labels:
        app: echoserver
    spec:
      containers:
      - image: ealen/echo-server:latest
        imagePullPolicy: IfNotPresent
        name: echoserver
        ports:
        - containerPort: 80
        env:
        - name: PORT
          value: "80"
---
apiVersion: v1
kind: Service
metadata:
  name: echoserver
  namespace: echoserver
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  type: ClusterIP
  selector:
    app: echoserver
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: echoserver
  namespace: echoserver
  annotations:
spec:
  ingressClassName: kong
  rules:
  - http:
      paths:
      - path: /echo
        pathType: Prefix
        backend:
          service:
            name: echoserver
            port:
              number: 80

The preceding code snippet creates the echoserver namespace in the Kubernetes cluster and deploys a single replica of the ealen/echo-server Docker container within that namespace. It exposes the container via a ClusterIP service and configures an ingress resource to route HTTP traffic to the service through the Kong Ingress Controller at the /echo path.

To deploy the server to your Kubernetes cluster, execute the following command in your project’s root:

kubectl apply -f echo.kube.yaml

The command above creates a new namespace containing a pod, deployment, service, and ingress. It returns an output, as shown below:

namespace/echoserver created
deployment.apps/echoserver created
service/echoserver created
ingress.networking.k8s.io/echoserver created

Notice that the echoserver ingress exposes an HTTP route /echo on port 80. In subsequent sections, you use this route via the Kong Gateway. Optionally, you can define more routes in the ingress.

Set up Kong Gateway

You need to set up the Kong Gateway in your Kubernetes cluster. The Kong OIDC plugin is available to premium or enterprise users. This tutorial uses Kong Konnect, which gives you access to premium features. Navigate to the Gateway Manager tab in the Kong Konnect portal, click the New Control Plane button, and choose Kong Ingress Controller (KIC) from the options menu. Provide a name for the KIC in the wizard that opens:

Fig: Create Kong Ingress Controller

Next, click Generate Script to establish a connection to the KIC from your cluster. Follow the instructions from the generated script to install the Kong Gateway to your Kubernetes cluster. At the end of the wizard, you can verify whether the resources were deployed correctly using the following command:

kubectl get all --namespace kong

This outputs all the resources in the kong cluster, as shown here:

NAME                                   READY   STATUS             RESTARTS         AGE
pod/ingress-kong-75b85bc6dc-h28gr      1/2     Running            2 (3d13h ago)    3d13h
pod/kong-controller-545bc56656-k7m4h   0/1     Running            2 (2m7s ago)   13d
pod/kong-gateway-84cc686fb5-xs8qc      1/1     Running            1 (3d13h ago)    13d

NAME                                         TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                         AGE
service/kong-controller-validation-webhook   ClusterIP      10.107.222.116   <none>        443/TCP                         13d
service/kong-gateway-admin                   ClusterIP      None             <none>        8444/TCP                        13d
service/kong-gateway-manager                 NodePort       10.98.49.41      <none>        8002:30977/TCP,8445:32582/TCP   13d
service/kong-gateway-proxy                   LoadBalancer   10.111.95.63     127.0.0.1     80:30744/TCP,443:30724/TCP      13d
service/kong-proxy                           LoadBalancer   10.100.121.243   127.0.0.1     80:31590/TCP,443:32147/TCP      3d13h
service/kong-validation-webhook              ClusterIP      10.102.128.198   <none>        443/TCP                         3d13h

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ingress-kong      0/1     1            0           3d13h
deployment.apps/kong-controller   0/1     1            0           13d
deployment.apps/kong-gateway      1/1     1            1           13d

NAME                                         DESIRED   CURRENT   READY   AGE
replicaset.apps/ingress-kong-75b85bc6dc      1         1         0       3d13h
replicaset.apps/kong-controller-545bc56656   1         1         0       13d
replicaset.apps/kong-gateway-7b7ddccf49      0         0         0       6h25m
replicaset.apps/kong-gateway-84cc686fb5      1         1         1       13d
replicaset.apps/kong-gateway-c84c7c7ff       0         0         0       6h28m
replicaset.apps/kong-gateway-c9bcc4467       0         0         0       6h29m

Configure Descope

Descope provides authentication and user management services. It enables secure access to applications through various authentication methods, such as OIDC and Security Assertion Markup Language (SAML). Descope also offers features like multi-factor authentication (MFA), single sign-on (SSO), and role-based access control (RBAC) to ensure that only authorized users can access specific resources. It integrates with your existing infrastructure, streamlining the process of implementing and managing authentication and authorization for web and mobile applications.

Descope makes it easier to integrate authentication in your application using Descope Flows, a visual, no-code interface for building screens and authentication flows for common user interactions. These flows include various user authentication journeys such as login, sign-up, password reset, MFA, and step-up authentication.

In the following steps, you’ll define an OIDC flow with passkey authentication:

Import the OIDC flow

Start by logging in to your Descope account and creating a new project if you don’t already have one. The descope-sample-apps repo contains an example of an OIDC flow that uses a passkey authentication mechanism. Download the oidc_flow.json to your local device. Navigate to the Flows tab in the Descope portal and click Import to import the oidc-flow.json flow.

Once you import the OIDC flow, it displays a visual user journey:

Fig: OIDC Flow on Descope

Optionally, you can customize the flow based on your application’s requirements using Descope’s visual flow editor.

Configure the OIDC application

Navigate to the Applications tab and click the OIDC default application to edit it. On the application details page, update the flow parameter in the Flow Hosting URL to oidc-flow. The updated Flow Hosting URL looks similar to this:

https://auth.descope.io/<project_id>?flow=oidc-flow

Create an access key

Access keys enable secure machine-to-machine authentication, allowing other services or devices to access your application securely. You'll need an access key for the Descope application while configuring the OIDC plugin in your Kubernetes cluster.

To create an access key, navigate to the Access Keys tab and click + Access Key. Enter a name for the access key and click Generate Key to generate a new key:

Fig: Create a new access key

Make sure to copy the generated key before closing the modal as this won’t be displayed again on the Descope portal.

Add custom claims

To make Descope authentication work with the Kong Gateway, you need to add a custom azp (authorized party) claim to the JWT. The azp claim is used in JWTs to identify the client or entity authorized to use the access token. Follow these steps to add a custom claim:

  • Navigate to Project > JWT Templates in the Descope portal.

  • Click JWT Template to create a new template and choose Default User JWT from the list.

  • On the edit screen, add a custom claim with key azp and value project.id as shown in the screenshot.

Fig: Add a custom azp claim

Set up the OIDC plugin in Kong

The Kong OIDC plugin integrates with OIDC providers to enable secure authentication and authorization for APIs. It manages user sessions, validates tokens, and handles token exchange, ensuring that only authenticated users can access protected resources. This plugin simplifies the implementation of OAuth 2.0 and OIDC standards, providing a robust security layer for API endpoints.

You can now add the Kong OIDC plugin to your Kubernetes cluster to use the Descope OIDC flow.

Create a kong-oidc-plugin.yaml file in the root of the project and add the following content:

apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: oidc-auth
config:
  issuer: <DESCOPE_ISSUER_URL>
  client_id:
  - <DESCOPE_CLIENT_ID>
  client_secret:
  - <DESCOPE_CLIENT_SECRET>
  redirect_uri:
  - http://127.0.0.1.nip.io/echo
  auth_methods:
  - authorization_code
  display_errors: true
  token_endpoint_auth_method: "client_secret_post"
  scopes:
  - openid
  - descope.custom_claims
  filters:
    - claim: groups
      match: .*
      value_from: claims
      type: access_token
plugin: openid-connect

Replace these placeholder values in the configuration file:

  • DESCOPE_ISSUER_URL with the Descope Issuer URL. This value can be found under Applications > OIDC default application in the Descope project portal.

  • DESCOPE_CLIENT_ID with the Descope Project ID. This value is found under Project > General in the Descope project portal.

  • DESCOPE_CLIENT_SECRET with the access key you created in the previous step.

To create the plugin, execute the following command in your project’s root:

kubectl apply -f kong-oidc-plugin.yaml --namespace echoserver

The preceding command creates a new plugin in the echoserver namespace.

The Kong Ingress Controller uses annotations to add functionality to Kubernetes resources when no standardized configuration method is available. To annotate echoserver with the oidc-auth plugin, execute the following command:

kubectl patch ingress echoserver -p '{"metadata":{"annotations":{"konghq.com/plugins":"oidc-auth"}}}' --namespace echoserver

The preceding command creates a patch to annotate the echoserver ingress with the oidc-auth plugin. It outputs the following:

ingress.networking.k8s.io/echoserver patched

Demoing the app

Now that the Kubernetes cluster is configured with Kong and the OIDC plugin, you can test the setup.

Establish a tunnel

If you are running the Kubernetes cluster locally using minikube, you can execute the following command to create a tunnel that exposes the services on the localhost:

minikube tunnel

The output of the command above would be similar to the following:

✅  Tunnel successfully started

📌  NOTE: Please do not close this terminal as this process must stay alive for the tunnel to be accessible ...

❗  The service/ingress kong-gateway-proxy requires privileged ports to be exposed: [80 443]
🔑  sudo permission will be asked for it.
🏃  Starting tunnel for service kong-gateway-proxy.
❗  The service/ingress kong-proxy requires privileged ports to be exposed: [80 443]
🔑  sudo permission will be asked for it.
🏃  Starting tunnel for service kong-proxy.
❗  The service/ingress echoserver requires privileged ports to be exposed: [80 443]
🔑  sudo permission will be asked for it.
🏃  Starting tunnel for service echoserver.

Keep the tunnel running and open a new terminal window to verify whether an external IP address was assigned to your Kong services. Execute the following command to get the services:

kubectl get services --namespace kong

It should display that 127.0.0.1 is assigned as the external IP for the kong-gateway-proxy and kong-proxy services. Note that if the address is different from 127.0.0.1, you need to update the redirect URL and reapply the configuration:

--- OUTPUT TRIMMED ---
kong-gateway-proxy                   LoadBalancer   10.111.95.63     127.0.0.1     80:30744/TCP,443:30724/TCP      14d
kong-proxy                           LoadBalancer   10.100.121.243   127.0.0.1     80:31590/TCP,443:32147/TCP      4d11h
--- OUTPUT TRIMMED —

Test the echoserver

The echoserver API endpoints should be accessible only after OIDC authentication. If you hit the /echo endpoint, it should redirect you to Descope for authentication before processing the request. To test the echoserver /echo endpoint, open the following URL in a web browser:

http://127.0.0.1.nip.io/echo

Notice that the URL uses the nip.io format, as it provides wildcard DNS for any IP address. When you hit the URL, you are redirected to the Descope login page, as shown in the screenshot:

Fig: Descope login screen

Enter your email ID to proceed with authentication. If a passkey doesn’t exist for the specified email ID, you are prompted to generate a passkey on your machine; otherwise, it proceeds with passkey verification and redirects you back to the /echo endpoint. Now that the /echo endpoint contains the authorization code grant, Kong uses it to exchange it with the access_token from the IDP (ie Descope). Finally, the web browser displays the response of the /echo API endpoint:

Fig: Echo API response

Conclusion

The Kong Gateway is a cloud-native solution that efficiently manages, secures, and routes API requests for decentralized applications. Integrating Descope authentication with Kong simplifies the authentication process by centralizing user verification and leveraging OIDC-compliant JWTs for secure, streamlined access management.

In this article, you learned how to implement authentication using the Kong Gateway and Descope flows. You can find this tutorial’s complete source code on GitHub.

Sign up for a free Forever Descope account and request a demo to learn more.