Authentication in API Gateway — JWT, API Keys, and Token Validation
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
- Why should authentication be centralized in the gateway rather than each microservice?
- How does the gateway convey verified user identity to backend services?
- What is the risk of not stripping internal headers from client requests?
- Why use asymmetric (RS256) instead of symmetric (HS256) JWT signing in a gateway?
- How can you handle immediate token revocation with JWT?
Answers:
- Centralized authentication avoids duplicate code, ensures consistent enforcement, and reduces the attack surface to a single hardened component.
- The gateway adds internal headers like
X-User-IDandX-User-Roleafter successful authentication, which backend services trust. - A malicious client could send a forged
X-User-IDheader that the gateway passes through, impersonating another user. - With RS256, only the gateway signs tokens. Backends only need the public key to verify, and key compromise is limited.
- 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
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