DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Securing REST APIs With Nest.js: A Step-by-Step Guide
  • Navigating the API Seas: A Product Manager's Guide to Authentication
  • What D'Hack Is DPoP?
  • Using OKTA as Client Provider in Mulesoft

Trending

  • Building Enterprise-Ready Landing Zones: Beyond the Initial Setup
  • Integration Isn’t a Task — It’s an Architectural Discipline
  • Vibe Coding With GitHub Copilot: Optimizing API Performance in Fintech Microservices
  • A Modern Stack for Building Scalable Systems
  1. DZone
  2. Software Design and Architecture
  3. Security
  4. Secure Your API With JWT: Kong OpenID Connect

Secure Your API With JWT: Kong OpenID Connect

In this article, walk through the issues of session-based authorization and the benefits of stateless tokens, namely JWT.

By 
Adam Zaręba user avatar
Adam Zaręba
·
Mar. 19, 24 · Tutorial
Likes (4)
Comment
Save
Tweet
Share
10.7K Views

Join the DZone community and get the full member experience.

Join For Free

Good Old History: Sessions

Back in the old days, we used to secure web applications with sessions. The concept was straightforward: upon user authentication, the application would issue a session identifier, which the user would subsequently present in each subsequent call. On the backend side, the common approach was to have application memory storage to handle user authorization - simple mapping between session ID and user privileges. 

Secure web applications with sessions

Unfortunately, the simple solution had scaling limitations. If we needed to scale an application server, we used to apply session stickiness on the exposed load balancer:

Apply session stickiness on the exposed load balancer

 Or, move session data to shared storage like a database. 

Move session data to shared storage like a database

That caused other challenges to tackle: how to evenly distribute traffic for long living sessions and how to reduce request processing time for communication with shared session storage.

Distributed Nature of Authorization

The stateful nature of sessions becomes even more troublesome when we consider distributed applications. Handling proper session stickiness, and connection draining on a scale like multiple microservices gives no easy manageable solution.

Distributed Nature of Authorization

Stateless Authorization: JWT

Luckily, we can use a stateless solution - JWT - which is based on a compact and self-contained, encoded JSON object acting as a replacement for session ID for client/server communication. The idea is to encode user privileges or roles into a token and sign data with a trusted issuer to prove token integrity. In this scenario, the user, once authenticated, gets an access token in response with all data required for authorization - no more server session storage needed. The server during authorization needs to decode the token and get user privileges from the token itself. 

Stateless Authorization: JWT

Exposing Unprotected API in Kong

To see how things can work, let’s use Kong, acting as an API Gateway for calling upstream service. For this demo, we will use the Kong Enterprise edition together with the OpenID Connect plugin handling JWT validation. But let's first expose some REST resources with Kong. 

To make the demo simple, we can expose a single/mock endpoint in Kong which will proxy requests to the httpbin.org service. Endpoint deployment can be done with a declarative approach: we define the configuration for setting up the Kong service that will call upstream. Then the decK tool will create respective resources in Kong Gateway. The configuration file is as follows: 

YAML
 
_format_version: "3.0"
_transform: true

services:
  - host: httpbin.org
    name: example_service
    routes:
      - name: example_route
        paths:
          - /mock


Once deployed, we can verify endpoint details in Kong Manager UI:

Verify endpoint details in Kong Manager UI

For now, the endpoint is not protected and we can call it without any authorization details. Kong Gateway is exposed on a local machine on port 8000, so we can call it like this:

 
➜  ~ curl http://localhost:8000/mock/anything

{

  "args": {}, 

  "data": "", 

  "files": {}, 

  "form": {}, 

  "headers": {

    "Accept": "*/*", 

    "Host": "httpbin.org", 

    "User-Agent": "curl/8.4.0", 

    "X-Amzn-Trace-Id": "Root=1-65e2f62e-2ea7165246c573e24a3efeaf", 

    "X-Forwarded-Host": "localhost", 

    "X-Forwarded-Path": "/mock/anything", 

    "X-Forwarded-Prefix": "/mock", 

    "X-Kong-Request-Id": "3cef792ded0dfb53575cd866c20aba42"

  }, 

  "json": null, 

  "method": "GET", 

  "url": "http://localhost/anything"

}


Securing API With OpenID Connect Plugin

To secure our API we need two things:

  • IdP server, which will issue JWT tokens
  • Kong endpoint configuration that will validate JWT tokens

Setting up an IdP server is out of scope for this blog post, but for the demo, we can use Keycloak. In my test setup, I created a “test” user which is granted to have a “custom-api-get” scope - we will use this scope name later on for authorization with Kong. To get a JWT token, we need to call the Keycloak token endpoint. It returns an encoded token, which we can decode on the jwt.io website:

An encoded token, decoded on the jwt.io website:

On the Kong side, we will define endpoint authorization with the OpenID Connect plugin. For this, again, we will use the decK tool to update the endpoint definition.

YAML
 
_format_version: "3.0"

_transform: true


services:

  - host: httpbin.org

    name: example_service

    routes:

      - name: example_route

        paths:

          - /mock

        plugins:

          - name: openid-connect

            enabled: true

            config:

              display_errors: true

              scopes_claim:

                - scope

              bearer_token_param_type:

                - header

              issuer: http://keycloak:8080/auth/realms/master/.well-known/openid-configuration

              scopes_required:

                - custom-api-get

              auth_methods:

                - bearer

In the setup above, we stated that the user is allowed to call the endpoint if the JWT token contains the “custom-api-get” scope. We also specified how we want to pass the token (header value). To enable JWT signature verification, we also had to define the issuer. Kong will use this endpoint internally to get a list of public keys that can be used to check token integrity/signature (the content of that response is cached in Kong to avoid future requests). 

With this configuration, calling an endpoint without a token is not allowed. The plugin returns error details as follows:

 
➜  ~ curl http://localhost:8000/mock/anything

{"message":"Unauthorized (no suitable authorization credentials were provided)"}


To make it work, we need to pass a JWT token (for the sake of space, the token value is not presented):

 
➜  ~ curl http://localhost:8000/mock/anything --header "Authorization: Bearer $TOKEN"

{

  "args": {}, 

  "data": "", 

  "files": {}, 

  "form": {}, 

  "headers": {

    "Accept": "*/*", 

    "Authorization": "Bearer $TOKEN", 

    "Host": "httpbin.org", 

    "User-Agent": "curl/8.4.0", 

    "X-Amzn-Trace-Id": "Root=1-65e30053-4f1b17b771c240463a878c41", 

    "X-Forwarded-Host": "localhost", 

    "X-Forwarded-Path": "/mock/anything", 

    "X-Forwarded-Prefix": "/mock", 

    "X-Kong-Request-Id": "c1cf555ab43d951f73f72a30d5546516"

  }, 

  "json": null, 

  "method": "GET", 

  "url": "http://localhost/anything"

}


We should remember that tokens have a limited lifetime (in our demo, it was 1 minute), and the plugin verifies it as well. Calling the endpoint with an expired token returns the error:

 
curl http://localhost:8000/mock/anything --header "Authorization: Bearer $TOKEN"

{"message":"Unauthorized (invalid exp claim (1709375597) was specified for access token)"}


Summary

In this short post, we walked through the issues of session-based authorization and the benefits of stateless tokens, namely JWT. In a microservices solution, we can move authorization from microservice implementation into a centralized layer like Gateway. We just scratched the surface of JWT-based authorization, but we can implement more advanced scenarios by validating additional claims. If you’re interested in JWT details, I recommend you familiarize yourself with the specifications. Practice will make you an expert! 

API OpenID authentication JWT (JSON Web Token) security

Opinions expressed by DZone contributors are their own.

Related

  • Securing REST APIs With Nest.js: A Step-by-Step Guide
  • Navigating the API Seas: A Product Manager's Guide to Authentication
  • What D'Hack Is DPoP?
  • Using OKTA as Client Provider in Mulesoft

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!