FastAPI Tutorial Part 18: API Security Best Practices
Secure your FastAPI application against common vulnerabilities. Learn input validation, rate limiting, CORS, and OWASP security patterns.
Moshiour Rahman
Advertisement
Input Validation
Pydantic Validation
from pydantic import BaseModel, Field, field_validator
import re
class UserInput(BaseModel):
username: str = Field(min_length=3, max_length=50, pattern=r"^[a-zA-Z0-9_]+$")
email: str = Field(pattern=r"^[\w\.-]+@[\w\.-]+\.\w+$")
@field_validator("username")
@classmethod
def no_sql_injection(cls, v):
dangerous = ["'", '"', ";", "--", "/*", "*/"]
if any(char in v for char in dangerous):
raise ValueError("Invalid characters")
return v
SQL Injection Prevention
# NEVER do this
query = f"SELECT * FROM users WHERE name = '{user_input}'"
# Use parameterized queries
result = db.execute(
text("SELECT * FROM users WHERE name = :name"),
{"name": user_input}
)
Rate Limiting
from slowapi import Limiter
from slowapi.util import get_remote_address
limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter
@app.get("/api/data")
@limiter.limit("10/minute")
async def get_data(request: Request):
return {"data": "limited"}
Security Headers
from fastapi.middleware.cors import CORSMiddleware
@app.middleware("http")
async def add_security_headers(request, call_next):
response = await call_next(request)
response.headers["X-Content-Type-Options"] = "nosniff"
response.headers["X-Frame-Options"] = "DENY"
response.headers["X-XSS-Protection"] = "1; mode=block"
response.headers["Strict-Transport-Security"] = "max-age=31536000"
return response
CORS Configuration
app.add_middleware(
CORSMiddleware,
allow_origins=["https://yourdomain.com"], # Not "*" in production
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=["Authorization", "Content-Type"],
)
Secrets Management
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
secret_key: str # From environment
database_url: str
api_key: str
class Config:
env_file = ".env"
# Never hardcode secrets
# Use: export SECRET_KEY="your-secret" or .env file
Authentication Security
from passlib.context import CryptContext
pwd_context = CryptContext(
schemes=["bcrypt"],
deprecated="auto",
bcrypt__rounds=12 # Increase rounds for security
)
# Token expiration
ACCESS_TOKEN_EXPIRE_MINUTES = 15 # Short-lived
REFRESH_TOKEN_EXPIRE_DAYS = 7
Security Checklist
| Vulnerability | Prevention |
|---|---|
| SQL Injection | Parameterized queries |
| XSS | Input validation, output encoding |
| CSRF | CORS, SameSite cookies |
| Auth bypass | JWT validation, secure sessions |
| Data exposure | Response filtering |
Summary
| Security Layer | Implementation |
|---|---|
| Input | Pydantic validation |
| Transport | HTTPS, security headers |
| Authentication | JWT, bcrypt |
| Rate limiting | slowapi |
Next Steps
In Part 19, we’ll explore OpenAPI and Documentation - creating comprehensive API documentation.
Series Navigation:
- Part 1-17: Previous parts
- Part 18: Security (You are here)
- Part 19: OpenAPI & Documentation
Advertisement
Moshiour Rahman
Software Architect & AI Engineer
Enterprise software architect with deep expertise in financial systems, distributed architecture, and AI-powered applications. Building large-scale systems at Fortune 500 companies. Specializing in LLM orchestration, multi-agent systems, and cloud-native solutions. I share battle-tested patterns from real enterprise projects.
Related Articles
FastAPI Tutorial Part 5: Dependency Injection - Share Logic Across Endpoints
Master FastAPI dependency injection for clean, reusable code. Learn database sessions, authentication, pagination, and complex dependency chains.
PythonFastAPI Tutorial Part 20: Building a Production-Ready API
Build a complete production-ready FastAPI application. Combine all concepts into a real-world e-commerce API with authentication, database, and deployment.
PythonFastAPI Tutorial Part 8: Error Handling and Exceptions
Master error handling in FastAPI. Learn custom exceptions, global handlers, validation errors, and building user-friendly error responses.
Comments
Comments are powered by GitHub Discussions.
Configure Giscus at giscus.app to enable comments.