API Security Framework
A production-ready security framework for hardening REST and GraphQL APIs against the most common attack vectors. This toolkit provides battle-tested authentication middleware, intelligent rate limiting, strict input validation, CORS policy generators, and automated security testing scripts — everything you need to ship APIs that withstand real-world attacks without bolting on security as an afterthought.
Key Features
- JWT Authentication Middleware — Token generation, validation, refresh rotation, and blacklisting with configurable expiry and algorithm selection (HS256, RS256, ES256).
- Adaptive Rate Limiting — Sliding window rate limiter with per-endpoint, per-user, and per-IP granularity. Includes burst detection and automatic throttle escalation.
- Input Validation Engine — Schema-based request validation for JSON payloads, query parameters, path variables, and headers. Catches injection attempts, oversized payloads, and type mismatches.
- CORS Policy Generator — Generates strict, environment-aware CORS configurations. Separate policies for dev, staging, and production with origin whitelisting.
- GraphQL Security Layer — Query depth limiting, complexity analysis, introspection disabling for production, and field-level authorization checks.
- Automated Security Scanner — Python scripts that test your API endpoints for OWASP API Top 10 vulnerabilities, generating actionable HTML reports.
- Request Signing & HMAC Verification — Middleware for verifying request integrity using HMAC-SHA256 signatures, preventing tampering in transit.
Quick Start
# Extract and review the framework
unzip api-security-framework.zip
cd api-security-framework/
# Review the configuration template
cp config.example.yaml config.yaml
# Run the security scanner against your API
python3 scripts/security_scan.py --target https://api.example.com/v1/ --output report.html
Minimal Authentication Setup
import hmac
import hashlib
import json
import time
import base64
from typing import Optional
class APIAuthenticator:
"""Lightweight JWT-style token handler using stdlib only."""
def __init__(self, secret_key: str, expiry_seconds: int = 3600):
self.secret_key = secret_key.encode()
self.expiry_seconds = expiry_seconds
self._blacklist: set[str] = set()
def generate_token(self, user_id: str, roles: list[str]) -> str:
header = base64.urlsafe_b64encode(json.dumps({"alg": "HS256"}).encode()).decode()
payload_data = {
"sub": user_id,
"roles": roles,
"iat": int(time.time()),
"exp": int(time.time()) + self.expiry_seconds,
}
payload = base64.urlsafe_b64encode(json.dumps(payload_data).encode()).decode()
signature = hmac.new(self.secret_key, f"{header}.{payload}".encode(), hashlib.sha256).hexdigest()
return f"{header}.{payload}.{signature}"
def validate_token(self, token: str) -> Optional[dict]:
try:
header, payload, signature = token.split(".")
expected_sig = hmac.new(self.secret_key, f"{header}.{payload}".encode(), hashlib.sha256).hexdigest()
if not hmac.compare_digest(signature, expected_sig):
return None
if token in self._blacklist:
return None
data = json.loads(base64.urlsafe_b64decode(payload))
if data["exp"] < int(time.time()):
return None
return data
except (ValueError, KeyError):
return None
Architecture / How It Works
Client Request
│
▼
┌─────────────────┐
│ Rate Limiter │──► 429 Too Many Requests
└────────┬────────┘
▼
┌─────────────────┐
│ CORS Validator │──► 403 Forbidden (bad origin)
└────────┬────────┘
▼
┌─────────────────┐
│ Auth Middleware │──► 401 Unauthorized
└────────┬────────┘
▼
┌─────────────────┐
│ Input Validator │──► 422 Validation Error
└────────┬────────┘
▼
┌─────────────────┐
│ Your API Logic │──► 200 OK
└─────────────────┘
Each layer is independent and composable. You can use the rate limiter alone, pair authentication with input validation, or deploy the full pipeline.
Usage Examples
CORS Policy Configuration
cors:
production:
allowed_origins:
- "https://app.example.com"
- "https://admin.example.com"
allowed_methods: ["GET", "POST", "PUT", "DELETE"]
allowed_headers: ["Authorization", "Content-Type", "X-Request-ID"]
expose_headers: ["X-RateLimit-Remaining", "X-RateLimit-Reset"]
max_age: 86400
allow_credentials: true
development:
allowed_origins: ["http://localhost:3000", "http://localhost:5173"]
allowed_methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]
allowed_headers: ["*"]
max_age: 0
allow_credentials: true
Configuration
| Parameter | Default | Description |
|---|---|---|
rate_limit.max_requests |
100 |
Max requests per window per client |
rate_limit.window_seconds |
60 |
Sliding window duration |
auth.algorithm |
HS256 |
Token signing algorithm |
auth.token_expiry |
3600 |
Token TTL in seconds |
auth.refresh_expiry |
604800 |
Refresh token TTL (7 days) |
cors.max_age |
86400 |
Preflight cache duration |
validation.max_payload_bytes |
1048576 |
Maximum request body size (1MB) |
graphql.max_depth |
10 |
Maximum query nesting depth |
graphql.max_complexity |
1000 |
Maximum query complexity score |
Best Practices
- Always validate on the server — Client-side validation is UX; server-side validation is security.
-
Use constant-time comparison for tokens and signatures (
hmac.compare_digest, not==). - Rotate secrets regularly — Automate key rotation and support multiple active signing keys during transitions.
- Log security events separately — Authentication failures, rate limit hits, and validation errors should go to a dedicated security log.
-
Set strict Content-Type headers — Reject requests without proper
Content-Typeto prevent MIME confusion attacks. - Version your API — Security policies can differ per version; don't break existing clients when tightening rules.
Troubleshooting
| Problem | Cause | Fix |
|---|---|---|
| CORS errors in browser | Origin not in allowlist | Add your frontend domain to cors.allowed_origins
|
| 429 responses during testing | Rate limiter too aggressive | Increase max_requests or add test IPs to bypass list |
| Token validation fails after deploy | Clock skew between servers | Use NTP sync; add 30s leeway to expiry checks |
| GraphQL introspection leaking schema | Introspection enabled in prod | Set graphql.introspection: false in production config |
This is 1 of 9 resources in the Security Engineer Pro toolkit. Get the complete [API Security Framework] with all files, templates, and documentation for $39.
Or grab the entire Security Engineer Pro bundle (9 products) for $119 — save 30%.
Top comments (0)