API gateways sit at the edge of your infrastructure, handling all incoming API traffic before it reaches backend services. This position makes them natural enforcement points for security policies. Authentication, authorization, rate limiting, and request validation can all happen at the gateway, providing consistent protection across all backend services.
Centralizing security at the gateway reduces duplication and ensures consistent enforcement. Individual services don't need to implement the same authentication logic, and security updates apply everywhere immediately. However, this centralization also makes the gateway a critical security component that requires careful configuration.
Authentication at the Gateway
Gateways can validate authentication tokens before requests reach backends, rejecting invalid requests early. This reduces load on backend services and provides a single point for authentication policy enforcement.
# Kong API Gateway JWT authentication
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: jwt-auth
config:
uri_param_names: []
cookie_names: []
header_names:
- Authorization
claims_to_verify:
- exp
secret_is_base64: false
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ingress
annotations:
konghq.com/plugins: jwt-auth
spec:
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api
port:
number: 80
Forward verified identity to backends via headers:
# Pass user information to backends
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: request-transformer
config:
add:
headers:
- "X-User-ID:$(jwt.sub)"
- "X-User-Email:$(jwt.email)"
- "X-User-Roles:$(jwt.roles)"
Backend services trust headers from the gateway:
// Backend trusts gateway-provided headers
class GatewayAuthMiddleware
{
public function handle(Request $request, Closure $next): Response
{
// Only trust headers from internal gateway
if (!$this->isFromGateway($request)) {
abort(403);
}
$userId = $request->header('X-User-ID');
if ($userId) {
$user = User::find($userId);
Auth::login($user);
}
return $next($request);
}
private function isFromGateway(Request $request): bool
{
// Verify request came from gateway (internal network)
$allowedIps = config('gateway.allowed_ips');
return in_array($request->ip(), $allowedIps);
}
}
Rate Limiting
Rate limiting at the gateway protects backend services from overload and abuse. Implement multiple rate limiting tiers based on authentication level and endpoint sensitivity.
# Kong rate limiting plugin
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: rate-limit-standard
config:
second: 10
minute: 100
hour: 1000
policy: redis
redis_host: redis
redis_port: 6379
fault_tolerant: true
hide_client_headers: false
---
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: rate-limit-premium
config:
second: 100
minute: 1000
hour: 10000
policy: redis
redis_host: redis
Apply different limits based on API tier:
# Standard tier endpoints
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-standard
annotations:
konghq.com/plugins: jwt-auth,rate-limit-standard
spec:
rules:
- host: api.example.com
http:
paths:
- path: /v1
pathType: Prefix
backend:
service:
name: api
port:
number: 80
---
# Premium tier endpoints
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-premium
annotations:
konghq.com/plugins: jwt-auth,rate-limit-premium
spec:
rules:
- host: api.example.com
http:
paths:
- path: /v1/premium
pathType: Prefix
backend:
service:
name: api-premium
port:
number: 80
Request Validation
Validate requests at the gateway to reject malformed or malicious payloads before they reach backends.
# Request validation with JSON Schema
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: request-validator
config:
body_schema: |
{
"type": "object",
"required": ["name", "email"],
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"email": {
"type": "string",
"format": "email"
},
"phone": {
"type": "string",
"pattern": "^\\+?[0-9]{10,15}$"
}
},
"additionalProperties": false
}
allowed_content_types:
- application/json
verbose_response: false
Validate request size to prevent resource exhaustion:
# Limit request body size
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: request-size-limiting
config:
allowed_payload_size: 10 # MB
size_unit: megabytes
require_content_length: true
IP-Based Controls
Implement IP-based access controls for sensitive endpoints or to block known malicious sources.
# IP restriction for admin endpoints
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: ip-restriction-admin
config:
allow:
- 10.0.0.0/8 # Internal network
- 192.168.1.100 # VPN exit
deny: []
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: admin-api
annotations:
konghq.com/plugins: ip-restriction-admin,jwt-auth
spec:
rules:
- host: admin-api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-api
port:
number: 80
Block abusive IPs dynamically:
// Automatically block IPs after abuse detection
class AbuseDetectionService
{
public function checkAndBlock(Request $request): void
{
$ip = $request->ip();
$abuseScore = $this->calculateAbuseScore($ip);
if ($abuseScore > 100) {
$this->blockIp($ip);
Log::warning('IP blocked for abuse', [
'ip' => $ip,
'score' => $abuseScore,
]);
}
}
private function blockIp(string $ip): void
{
// Add to gateway blocklist via API
Http::post('http://kong-admin:8001/plugins', [
'name' => 'ip-restriction',
'config' => [
'deny' => [$ip],
],
]);
}
}
TLS and Certificate Management
Terminate TLS at the gateway to centralize certificate management and enable request inspection.
# TLS configuration with automatic certificate management
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: api-tls
spec:
secretName: api-tls-secret
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
dnsNames:
- api.example.com
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
tls:
- hosts:
- api.example.com
secretName: api-tls-secret
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api
port:
number: 80
Enforce strong TLS configurations:
# NGINX Ingress TLS configuration
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-configuration
data:
ssl-protocols: "TLSv1.2 TLSv1.3"
ssl-ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256"
ssl-prefer-server-ciphers: "true"
hsts: "true"
hsts-max-age: "31536000"
hsts-include-subdomains: "true"
Bot Protection
Protect APIs from automated abuse with bot detection and challenge mechanisms.
# Bot detection plugin
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: bot-detection
config:
deny:
- curl
- wget
- python-requests
- Go-http-client
allow:
- GoogleBot
- Bingbot
More sophisticated bot detection might use behavioral analysis:
class BotDetectionMiddleware
{
public function handle(Request $request, Closure $next): Response
{
$score = $this->calculateBotScore($request);
if ($score > 0.9) {
// Likely bot, reject
return response()->json(['error' => 'Forbidden'], 403);
}
if ($score > 0.7) {
// Suspicious, add challenge
$request->headers->set('X-Bot-Score', $score);
}
return $next($request);
}
private function calculateBotScore(Request $request): float
{
$score = 0;
// No user agent
if (!$request->userAgent()) {
$score += 0.3;
}
// Request frequency
$recentRequests = $this->getRecentRequestCount($request->ip());
if ($recentRequests > 100) {
$score += 0.3;
}
// Missing common headers
if (!$request->header('Accept-Language')) {
$score += 0.1;
}
// Known bot signatures
if ($this->matchesBotSignature($request->userAgent())) {
$score += 0.5;
}
return min($score, 1.0);
}
}
Logging and Monitoring
Comprehensive logging at the gateway provides security visibility and forensic capability.
# Enable detailed logging
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: http-log
config:
http_endpoint: http://log-collector:8080/logs
method: POST
timeout: 1000
keepalive: 60000
content_type: application/json
custom_fields_by_lua:
user_id: "return kong.request.get_header('X-User-ID')"
Alert on security-relevant events:
# Prometheus alerts for gateway security
groups:
- name: gateway-security
rules:
- alert: HighAuthenticationFailureRate
expr: |
sum(rate(kong_http_status{code="401"}[5m]))
/ sum(rate(kong_http_status[5m])) > 0.1
for: 5m
labels:
severity: warning
annotations:
summary: "High authentication failure rate"
- alert: RateLimitingTriggered
expr: sum(rate(kong_http_status{code="429"}[5m])) > 100
for: 1m
labels:
severity: info
annotations:
summary: "Rate limiting actively triggered"
Conclusion
API gateways provide a strategic control point for security enforcement. Centralize authentication to ensure consistent verification. Implement rate limiting to protect against abuse. Validate requests to catch malformed payloads. Use IP controls for sensitive endpoints.
The gateway is a critical security component—its compromise affects all backend services. Secure the gateway itself with proper access controls, audit logging, and regular updates. Monitor gateway metrics for security anomalies. Defense in depth means backends should still validate critical security assumptions even when the gateway provides first-line defense.