Skip to content

Authentication in API Gateway — JWT, API Keys, and Token Validation

DodaTech Updated 2026-06-28 5 min read

In this tutorial, you will learn about Authentication in API Gateway. We cover key concepts, practical examples, and best practices to help you master this topic.

Authentication in an API gateway validates client identity before requests reach backend services, offloading auth logic from individual Microservices and providing a single enforcement point for security policies.

What You'll Learn

  • How the gateway validates JWTs and API keys centrally
  • The difference between authentication and authorization in gateway context
  • Token introspection, Caching, and request forwarding patterns

Why It Matters

Without centralized authentication, every microservice must implement its own token validation, key verification, and session management. This duplicates code, creates inconsistent enforcement, and increases the attack surface. A gateway authenticates once and passes verified identity to backends via headers.

Real-World Use

When a user logs into the Durga Antivirus Pro dashboard, the browser receives a JWT. Every subsequent request includes the JWT in the Authorization header. The gateway validates the JWT signature, checks expiration, extracts the user ID, and forwards it to backend services via X-User-ID header.

flowchart LR
    Client["Client + JWT"] --> Auth["Auth Middleware\nin Gateway"]
    Auth -->|"Valid JWT"| Backend["Backend\nService"]
    Auth -->|"Invalid JWT"| Reject["401 Unauthorized"]
    style Auth fill:#dbeafe,stroke:#2563eb
    style Reject fill:#fecaca,stroke:#dc2626

JWT Validation in the Gateway

The gateway validates the JWT on every request. It verifies the signature using the public key, checks exp, nbf, and iss claims, and extracts user identity for downstream services.

import jwt
from flask import Flask, request, jsonify

app = Flask(__name__)

PUBLIC_KEY = open("/etc/gateway/jwt-public.pem").read()

def validate_jwt(token):
    try:
        payload = jwt.decode(
            token,
            PUBLIC_KEY,
            algorithms=["RS256"],
            audience="api.dodatech.com"
        )
        return payload
    except jwt.ExpiredSignatureError:
        return None
    except jwt.InvalidTokenError:
        return None

@app.before_request
def authenticate():
    auth_header = request.headers.get("Authorization", "")
    if not auth_header.startswith("Bearer "):
        return jsonify({"error": "Missing or invalid token"}), 401
    token = auth_header[7:]
    payload = validate_jwt(token)
    if not payload:
        return jsonify({"error": "Invalid or expired token"}), 401
    request.user = payload

API Key Authentication

For machine-to-machine communication, API keys provide a simpler auth mechanism:

API_KEYS = {
    "sk-live-a1b2c3": {"client": "partner-1", "tier": "premium"},
    "sk-live-d4e5f6": {"client": "partner-2", "tier": "basic"},
}

@app.before_request
def authenticate_api_key():
    api_key = request.headers.get("X-API-Key")
    if not api_key:
        return jsonify({"error": "API key required"}), 401
    client_info = API_KEYS.get(api_key)
    if not client_info:
        return jsonify({"error": "Invalid API key"}), 401
    request.client = client_info

Forwarding Identity to Backends

After authentication, the gateway forwards verified identity to backend services using internal headers:

import requests

@app.route("/api/<path:path>")
def proxy_with_identity(path):
    user_id = request.user.get("sub")
    headers = {
        "X-User-ID": user_id,
        "X-User-Role": request.user.get("role", "user"),
        "X-Authenticated-By": "gateway"
    }
    resp = requests.get(
        f"http://backend-service/{path}",
        headers=headers,
        params=request.args
    )
    return resp.content, resp.status_code

Backend services trust the X-User-ID header because it was added by the gateway after authentication. These headers must be stripped from incoming client requests to prevent spoofing.

Token Caching

Validating every request against an external auth server is expensive. Cache valid tokens to reduce latency:

import time

token_cache = {}

def validate_token_cached(token):
    if token in token_cache:
        payload, expiry = token_cache[token]
        if expiry > time.time():
            return payload
    payload = validate_jwt(token)
    if payload:
        token_cache[token] = (payload, payload["exp"])
    return payload

Common Mistakes

1. Not Stripping Internal Headers from Client Requests

Clients could send a fake X-User-ID header if the gateway doesn't strip it before forwarding. Always start with a clean header set.

2. Validating Tokens at the Backend Again

If the gateway already validated the JWT, backends should trust the gateway headers. Re-validating duplicates work. Use internal network security and header sanitization.

3. Using Symmetric Keys for Microservice Auth

JWT secret keys shared across many services increase the risk of key leakage. Use asymmetric keys (RS256) so only the gateway holds the private key.

4. Not Handling Token Refresh

Expired tokens cause errors. The gateway should intercept 401 responses and guide clients to refresh tokens, or support refresh token flows.

5. Ignoring Token Revocation

JWT tokens are valid until expiry. For immediate revocation (user logout, account suspension), maintain a blocklist in Redis that the gateway checks before validating the JWT.

Practice Questions

  1. Why should authentication be centralized in the gateway rather than each microservice?
  2. How does the gateway convey verified user identity to backend services?
  3. What is the risk of not stripping internal headers from client requests?
  4. Why use asymmetric (RS256) instead of symmetric (HS256) JWT signing in a gateway?
  5. How can you handle immediate token revocation with JWT?

Answers:

  1. Centralized authentication avoids duplicate code, ensures consistent enforcement, and reduces the attack surface to a single hardened component.
  2. The gateway adds internal headers like X-User-ID and X-User-Role after successful authentication, which backend services trust.
  3. A malicious client could send a forged X-User-ID header that the gateway passes through, impersonating another user.
  4. With RS256, only the gateway signs tokens. Backends only need the public key to verify, and key compromise is limited.
  5. Maintain a blocklist in Redis of revoked token IDs (jti). The gateway checks this blocklist before accepting any JWT.

Challenge: Implement a gateway authentication middleware that supports both JWT and API key authentication. Clients can use either method. Forward the user/client identity and authentication method to backends.

FAQ

Can the gateway authenticate without storing user credentials?

: Yes. The gateway validates tokens signed by an external identity provider. The credentials themselves never reach the gateway.

What happens when the JWT signing key rotates?

: The gateway caches the new public key from the JWKS endpoint. Tokens signed with the old key remain valid until they expire.

Should all endpoints go through gateway authentication?

: Public endpoints like /health or /docs should bypass authentication. Configure route-level skip rules.

How does the gateway handle multi-factor authentication?

: The gateway validates the session token that was issued after MFA completion. The MFA step happens at the identity provider, not the gateway.

Can the gateway support SAML or social login?

: The gateway delegates SAML/OAuth flows to the identity provider and validates the resulting tokens. The gateway itself does not implement these protocols.

Mini Project

Build a Flask gateway that authenticates requests using both JWTs (Bearer tokens) and API keys (X-API-Key header). Strip all incoming X-* headers from client requests, validate the auth, then add clean X-Auth-* headers before forwarding to a mock backend.

What's Next

Continue with SSL Termination in API Gateway for TLS management, or explore Request Transformation in Gateway for modifying requests before forwarding.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro