Skip to main content

35. Kong JWT Validation Strategy

Date: 2025-01-28

Status

Accepted

Category

Authentication & Authorization

Context

Kong API Gateway can validate JWTs using its built-in JWT plugin, but it currently uses HS256 (symmetric keys) with static secrets. Our architecture requires RS256 (asymmetric) validation using Keycloak’s public keys for:
  • Stateless validation at gateway layer
  • No shared secrets between Kong and Keycloak
  • Support for Keycloak key rotation
  • Consistent JWT validation across all routes
Options:
  1. Kong Enterprise OIDC Plugin: Full OIDC with automatic JWKS - $$ commercial license
  2. Community OIDC Plugin (nokia/kong-oidc): Free but maintenance burden
  3. Kong JWT Plugin + Static Public Key: Simple but manual key updates
  4. Custom Plugin with JWKS Fetching: Dynamic but requires Lua development

Decision

Use Kong’s standard JWT plugin with RS256 and periodic JWKS updates via automated CronJob, avoiding custom plugin development while maintaining security.

Architecture

Core Principles

  1. Standard Plugin: Use Kong’s built-in JWT plugin (no custom code)
  2. RS256 Validation: Asymmetric cryptography with Keycloak public key
  3. JWKS Auto-Update: CronJob fetches and updates keys every 6 hours
  4. Hybrid Routes: Different auth per route (API, browser, legacy)
  5. Stateless: No Kong-Keycloak coordination required

Configuration

Kong JWT Plugin:
Kong Consumer with Keycloak Public Key:
JWKS Updater CronJob:

Hybrid Route Configuration

API Route (JWT required):
Browser Route (No Kong auth, MCP validates):
Legacy Route (API key→JWT exchange):

Consequences

Positive Consequences

  • No custom plugin development, standard Kong features
  • RS256 security (no shared secrets), stateless validation
  • Sub-millisecond performance (static key), high throughput

Negative Consequences

  • Manual key rotation (6-hour lag), CronJob dependency
  • No automatic JWKS fetching built-in
  • Requires Python script for key updates

Mitigation Strategies

  • Automated CronJob every 6 hours (acceptable lag)
  • Monitor CronJob success/failure, alert on failures
  • Keycloak supports multiple valid keys during rotation

Alternatives Considered

  1. Kong Enterprise OIDC: Rejected - cost, not needed for stateless validation
  2. Community OIDC Plugin: Rejected - maintenance burden, compatibility issues
  3. Custom JWKS Plugin: Rejected - unnecessary complexity for infrequent key rotation
  4. No Kong Validation: Rejected - performance (MCP validation slower)

Implementation

JWKS Updater Script (scripts/update_kong_jwks.py):
Deployment:
  1. Extract Keycloak public key manually (initial setup)
  2. Configure Kong JWT plugin with RS256
  3. Deploy JWKS updater CronJob
  4. Test with sample JWTs from Keycloak

References

  • Kong Plugin: deployments/kubernetes/kong/kong-plugins.yaml (to be updated)
  • JWKS Updater: scripts/update_kong_jwks.py (to be created)
  • CronJob: deployments/kubernetes/kong/kong-jwks-updater-cronjob.yaml (to be created)
  • Related ADRs: ADR-0031, ADR-0032, ADR-0034
  • External: Kong JWT Plugin, JWKS