Building Secure FastAPI Applications: Best Practices
Security should be a primary concern from day one of API development. FastAPI makes it easy to implement security best practices, but it's your responsibility to use these tools correctly. This guide covers essential security practices for production FastAPI applications.
Authentication with JWT Tokens
JWT tokens provide a stateless way to authenticate users. Here's how to implement them securely in FastAPI:
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthCredentials
from datetime import datetime, timedelta
import jwt
security = HTTPBearer()
async def verify_token(credentials: HTTPAuthCredentials = Depends(security)):
token = credentials.credentials
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
return payload
except jwt.InvalidTokenError:
raise HTTPException(status_code=401, detail="Invalid token")
Password Hashing and Storage
Never store plain text passwords. Use bcrypt for secure hashing:
- Use strong hashing algorithms (bcrypt, scrypt, argon2)
- Add salt to prevent rainbow table attacks
- Use appropriate work factors for your use case
- Never log passwords or sensitive data
Input Validation
FastAPI's Pydantic provides automatic validation. Use it extensively to prevent injection attacks and malformed data:
from pydantic import BaseModel, EmailStr, validator
class UserCreate(BaseModel):
email: EmailStr
password: str
@validator('password')
def password_strong(cls, v):
if len(v) < 12:
raise ValueError('Password must be 12+ chars')
return v
SQL Injection Prevention
Always use parameterized queries or ORM frameworks:
- Use SQLAlchemy ORM instead of raw SQL
- Never concatenate user input into SQL strings
- Use environment variables for database credentials
- Implement principle of least privilege for database users
CORS Configuration
Configure CORS carefully to prevent unauthorized access:
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["https://yourdomain.com"], # Never use ["*"]
allow_credentials=True,
allow_methods=["GET", "POST"],
allow_headers=["Authorization"],
)
HTTPS and TLS
- Always use HTTPS in production
- Implement HSTS (HTTP Strict Transport Security)
- Use strong TLS configurations
- Keep certificates updated
Rate Limiting
Protect against brute force attacks and abuse with rate limiting. Use slowapi or similar middleware:
from slowapi import Limiter
from slowapi.util import get_remote_address
limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter
@app.post("/login")
@limiter.limit("5/minute")
async def login(credentials: LoginRequest):
Error Handling
Don't expose sensitive information in error messages:
- Use generic error messages for authentication failures
- Log detailed errors internally for debugging
- Never expose database schemas or internal details
- Implement proper error tracking with services like Sentry
Dependency Injection Security
Leverage FastAPI's dependency system for security:
async def get_current_user(token: str = Depends(oauth2_scheme)):
user = await verify_token(token)
if not user:
raise HTTPException(status_code=401)
return user
@app.get("/protected")
async def protected_route(current_user = Depends(get_current_user)):
return {"user": current_user}
Environment Variables
- Never commit secrets to version control
- Use .env files locally (excluded from git)
- Use proper secret management in production (AWS Secrets Manager, Vault, etc.)
- Rotate secrets regularly
Security Headers
Add important security headers to all responses:
from fastapi.middleware import Middleware
app.add_middleware(
TrustedHostMiddleware,
allowed_hosts=["yourdomain.com"]
)
@app.get("/")
async def root():
# Headers automatically included by middleware
Logging and Monitoring
- Log security events (failed auth, suspicious patterns)
- Monitor for unusual activity patterns
- Set up alerts for security events
- Implement proper audit trails
Conclusion
Security in FastAPI applications requires consistent vigilance and following best practices throughout development. By implementing these safeguards, you'll build applications that protect user data and maintain system integrity.