Day 7: HMAC Request Signing & Rate Limiting
What I Built
- HMAC-SHA256 request signing with replay attack protection (5-minute window)
- FastAPI middleware for automatic signature verification on all API requests
- Rate limiting with configurable limits per endpoint (10 trades/min, 100 quotes/min)
- Log sanitization using structlog to mask sensitive fields (passwords, tokens, balances)
- Comprehensive security test suite covering all attack vectors
Code Highlight
# HMAC signing with replay protection
class HMACSigner:
def sign_request(self, method: str, url: str, body: Optional[str] = None,
headers: Optional[Dict[str, str]] = None,
timestamp: Optional[int] = None) -> Dict[str, str]:
# Creates signature: HMAC-SHA256(method + url + timestamp + body)
# Returns headers: X-Timestamp, X-Signature, X-Algorithm
def verify_signature(self, method: str, url: str, body: Optional[str] = None,
headers: Optional[Dict[str, str]] = None,
signature_headers: Dict[str, str] = None,
max_age: int = 300) -> bool:
# Verifies signature and checks timestamp age
# FastAPI middleware
class HMACVerificationMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
# Verifies HMAC on all POST/PUT/PATCH requests
# Skips health checks and GET requests
# Returns 401 on invalid signatures
Architecture Decision
Chose HMAC-SHA256 over JWT for API authentication because it provides request integrity without the complexity of token management. The 5-minute replay window balances security with usability, and per-endpoint rate limiting prevents abuse while allowing legitimate high-frequency operations like market data requests.
Testing Results
All 9 unit tests pass, covering critical security scenarios:
- Valid signature verification
- Invalid signature rejection
- Replay attack prevention (old timestamps)
- Request tampering detection
- Missing header handling
- Environment variable configuration
Next Steps
Day 8: Circuit breakers and health checks for graceful failure handling.
Follow @therealkamba on X for regular updates. View all posts →