Skip to main content

Kong JWT Authentication

Introduction

JSON Web Tokens (JWT) provide a compact and self-contained way to securely transmit information between parties. When combined with Kong, a popular API Gateway, JWT becomes a powerful authentication mechanism for your APIs. This tutorial will guide you through understanding and implementing JWT authentication with Kong.

What is JWT?

JSON Web Tokens are an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. JWTs can be verified and trusted because they are digitally signed using a secret or a public/private key pair.

A JWT consists of three parts, separated by dots (.):

  • Header: Contains the type of token and the signing algorithm
  • Payload: Contains the claims or the data
  • Signature: Used to verify that the sender of the JWT is who it says it is
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Kong JWT Plugin

Kong's JWT plugin enables your API Gateway to verify JWT tokens sent by clients. When a client makes a request to your API, Kong verifies the token before forwarding the request to your upstream service.

How Kong JWT Authentication Works

Here's a high-level flow of JWT authentication with Kong:

Setting Up Kong JWT Authentication

Let's walk through setting up JWT authentication in Kong step by step.

Prerequisites

  • Kong installed and running
  • Basic understanding of Kong services and routes
  • curl or another API testing tool

Step 1: Create a Service and Route

First, let's create a service pointing to your backend API:

bash
curl -X POST http://localhost:8001/services \
--data "name=my-api" \
--data "url=http://my-api.com"

Next, create a route for this service:

bash
curl -X POST http://localhost:8001/services/my-api/routes \
--data "paths[]=/api"

Step 2: Enable the JWT Plugin

Now, let's enable the JWT plugin on the service:

bash
curl -X POST http://localhost:8001/services/my-api/plugins \
--data "name=jwt"

Step 3: Create a Consumer

Create a consumer who will access your API:

bash
curl -X POST http://localhost:8001/consumers \
--data "username=john"

Step 4: Create JWT Credentials

Create a JWT credential for this consumer:

bash
curl -X POST http://localhost:8001/consumers/john/jwt \
--data "key=user-issuer" \
--data "secret=secret-key"

The response will include:

json
{
"consumer": { "id": "7bce93e1-0a90-489c-c887-d385545f8f4b" },
"created_at": 1442426001000,
"id": "bcbfb45d-e391-42bf-c2ed-94e32946753a",
"key": "user-issuer",
"secret": "secret-key"
}

Creating and Using JWT Tokens

Now that we've set up Kong, let's see how to create and use JWT tokens.

Creating a JWT Token

You can create a JWT token using various programming languages. Here's an example using JavaScript with the jsonwebtoken library:

javascript
const jwt = require('jsonwebtoken');

// The payload
const payload = {
sub: "1234567890",
name: "John Doe",
iat: Math.floor(Date.now() / 1000)
};

// Use the secret key from your Kong JWT credential
const secret = 'secret-key';

// The JWT header includes the key (issuer) from your Kong JWT credential
const header = {
typ: "JWT",
alg: "HS256",
kid: "user-issuer"
};

// Create the token
const token = jwt.sign(payload, secret, { header: header });
console.log(token);

Output:

eyJraWQiOiJ1c2VyLWlzc3VlciIsInR5cCI6IkpXVCIsImFsZyI6IkhTMjU2In0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNjQ2NjQ5NjAwfQ.Z4XaMlvZKO2JxT3H5WEj5eN9g-hGvKxTWYx-8c0F2Wo

Using the JWT Token

To make a request to your protected API, include the JWT in the Authorization header:

bash
curl -X GET http://localhost:8000/api \
-H "Authorization: Bearer eyJraWQiOiJ1c2VyLWlzc3VlciIsInR5cCI6IkpXVCIsImFsZyI6IkhTMjU2In0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNjQ2NjQ5NjAwfQ.Z4XaMlvZKO2JxT3H5WEj5eN9g-hGvKxTWYx-8c0F2Wo"

Alternatively, you can pass it as a query parameter:

bash
curl -X GET "http://localhost:8000/api?jwt=eyJraWQiOiJ1c2VyLWlzc3VlciIsInR5cCI6IkpXVCIsImFsZyI6IkhTMjU2In0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNjQ2NjQ5NjAwfQ.Z4XaMlvZKO2JxT3H5WEj5eN9g-hGvKxTWYx-8c0F2Wo"

Advanced Configuration

Kong's JWT plugin provides several configuration options:

Customizing Token Verification

You can customize how Kong verifies tokens with these parameters:

bash
curl -X POST http://localhost:8001/services/my-api/plugins \
--data "name=jwt" \
--data "config.claims_to_verify=exp" \
--data "config.key_claim_name=kid" \
--data "config.secret_is_base64=false"

JWT Plugin Configuration Options

ParameterDescriptionDefault
config.uri_param_namesParameters in the URI that contain the tokenjwt
config.cookie_namesNames of cookies that contain the tokennone
config.claims_to_verifyClaims to verifynone
config.key_claim_nameClaim that contains the keyiss
config.secret_is_base64If true, the secret is base64 encodedfalse
config.run_on_preflightRun on preflight OPTIONS requeststrue
config.maximum_expirationMaximum allowed expiration (in seconds)none

Real-World Example: Protecting a User API

Let's walk through a real-world example of protecting a user management API with Kong JWT authentication.

Step 1: Set Up the API in Kong

bash
# Create a service
curl -X POST http://localhost:8001/services \
--data "name=user-api" \
--data "url=http://user-service:3000"

# Create routes
curl -X POST http://localhost:8001/services/user-api/routes \
--data "paths[]=/users"

Step 2: Add JWT Authentication

bash
curl -X POST http://localhost:8001/services/user-api/plugins \
--data "name=jwt"

Step 3: Create Admin Consumer and Credentials

bash
# Create admin consumer
curl -X POST http://localhost:8001/consumers \
--data "username=admin"

# Create JWT credential
curl -X POST http://localhost:8001/consumers/admin/jwt \
--data "key=admin-api" \
--data "secret=super-secure-secret"

Step 4: Create a Token for Admin Access

javascript
const jwt = require('jsonwebtoken');

const payload = {
sub: "admin",
role: "administrator",
permissions: ["users:read", "users:write"],
exp: Math.floor(Date.now() / 1000) + (60 * 60) // 1 hour
};

const secret = 'super-secure-secret';
const header = {
typ: "JWT",
alg: "HS256",
kid: "admin-api"
};

const token = jwt.sign(payload, secret, { header: header });
console.log(token);

Step 5: Access the Protected API

bash
curl -X GET http://localhost:8000/users \
-H "Authorization: Bearer eyJraWQiOiJhZG1pbi1hcGkiLCJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsInJvbGUiOiJhZG1pbmlzdHJhdG9yIiwicGVybWlzc2lvbnMiOlsidXNlcnM6cmVhZCIsInVzZXJzOndyaXRlIl0sImV4cCI6MTY0NjY1MzIwMH0.BdCMDhSgFoJ5S9JQrELYgKkP-nHxUdlJVBpgW2UdiNM"

Common Issues and Troubleshooting

1. "No credentials found" error

If you receive a 401 Unauthorized with "No credentials found" message, ensure that:

  • You're including the JWT token in the Authorization header as "Bearer [token]"
  • The token format is correct
  • You're using the correct path that's protected by Kong

2. "Invalid signature" error

This typically means:

  • The token was signed with a different secret than what Kong expects
  • The token has been tampered with

3. "Token expired" error

Check if:

  • The token has an exp claim that's in the past
  • Your system clocks are synchronized

Best Practices for Kong JWT Implementation

  1. Use HTTPS: Always use HTTPS to prevent token interception
  2. Short Expiration Times: Set short expiration times for tokens
  3. Include Only Necessary Claims: Don't include sensitive information in tokens
  4. Rotate Secrets Regularly: Change your JWT secrets periodically
  5. Include Rate Limiting: Combine JWT with rate limiting to prevent abuse
  6. Monitor Token Usage: Log and monitor token usage for suspicious activities

Summary

In this tutorial, we've explored how to implement JWT authentication with Kong API Gateway:

  1. We learned about JWT structure and how it works with Kong
  2. We set up Kong with the JWT plugin
  3. We created consumers and credentials
  4. We generated and used JWT tokens
  5. We explored advanced configuration options
  6. We implemented a real-world example
  7. We discussed troubleshooting and best practices

JWT combined with Kong provides a robust authentication mechanism for your APIs, ensuring that only authorized clients can access your services while maintaining a stateless, scalable architecture.

Exercise

Try implementing JWT authentication with Kong for your own API:

  1. Create a simple backend API with a framework of your choice
  2. Set up Kong to proxy requests to your API
  3. Enable JWT authentication using the steps outlined in this tutorial
  4. Create a consumer and credentials
  5. Generate a token and test your protected API
  6. Try to access the API without a token and observe the response
  7. Try to access the API with an expired token

Additional Resources



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)