backend-api-python
Build secure, production-ready FastAPI backends with Alembic migrations, SQLite for dev, PostgreSQL for prod, and industry-leading security practices.
DIRECTIVE_TEXTUELLE
Backend API Python (FastAPI) Skill
Build secure, production-ready FastAPI backends with industry-leading security practices.
When to Use
Use this skill when the user wants to:
- Build RESTful APIs with FastAPI framework
- Implement secure authentication and authorization
- Create database migrations with Alembic
- Use SQLite for development, PostgreSQL for production
- Implement rate limiting and input validation
- Set up API documentation (OpenAPI/Swagger)
- Implement comprehensive error handling
- Secure file uploads and sensitive data
- Implement security headers and CORS policies
- Set up environment-based configuration
- Create production-ready database schemas
Technology Stack
Core Framework
- FastAPI: Modern async Python web framework
- Automatic OpenAPI documentation
- Type hints and validation
- Async/await support
- Built-in dependency injection
- WebSocket support
Database
- Alembic: Database migration tool
- SQLite: Development database
- PostgreSQL: Production database
- SQLAlchemy: ORM for database operations
Security Libraries
- python-jose/cryptography: JWT handling and encryption
- passlib/bcrypt: Password hashing
- Pydantic: Input validation and data modeling
- python-multipart: File upload handling
- slowapi: Rate limiting
- trafaret: Data validation
- gunicorn/uvicorn: ASGI server deployment
Dev Tools
- pytest: Testing framework
- pytest-asyncio: Async testing
- black: Code formatting
- ruff: Linting
- httpx: HTTP client for testing
Project Structure
backend-api-python/
├── .env # Environment variables
├── .env.example # Environment template
├── alembic/ # Alembic migrations
│ ├── env.py
│ ├── script.py.mako
│ └── versions/
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI app instance
│ ├── config.py # Configuration settings
│ ├── dependencies.py # FastAPI dependencies
│ ├── models/ # SQLAlchemy models
│ │ ├── __init__.py
│ │ ├── base.py # Base model
│ │ └── user.py
│ ├── schemas/ # Pydantic schemas
│ │ ├── __init__.py
│ │ └── user.py
│ ├── api/ # API routers
│ │ ├── __init__.py
│ │ ├── deps.py # API dependencies
│ │ └── v1/
│ │ ├── __init__.py
│ │ ├── users.py
│ │ └── auth.py
│ ├── core/ # Core security modules
│ │ ├── __init__.py
│ │ ├── security.py # Security utilities
│ │ ├── config.py # Security config
│ │ └── constants.py
│ ├── crud/ # CRUD operations
│ │ ├── __init__.py
│ │ └── user.py
│ ├── db/ # Database utilities
│ │ ├── __init__.py
│ │ ├── base.py
│ │ └── session.py
│ ├── services/ # Business logic
│ │ ├── __init__.py
│ │ ├── auth.py
│ │ └── user.py
│ ├── utils/ # Helper functions
│ │ ├── __init__.py
│ │ ├── helpers.py
│ │ └── error_handlers.py
│ └── __init__.py
├── requirements.txt # Production dependencies
├── requirements-dev.txt # Development dependencies
├── alembic.ini # Alembic configuration
├── pyproject.toml # Project configuration
└── README.md
Security Best Practices
1. Authentication & Authorization
Password Storage:
- Always use bcrypt or Argon2 for password hashing
- Store only the hash, never the plaintext password
- Use a secure salt value
JWT Security:
- Set appropriate expiration times (short-lived tokens)
- Use secure secret keys from environment variables
- Store refresh tokens securely (httpOnly, secure cookies)
- Implement proper token validation and expiration checking
Authentication Flow:
# Example: Secure authentication implementation
from passlib.context import CryptContext
from jose import jwt
from datetime import datetime, timedelta
from fastapi import Depends, HTTPException, status
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def verify_password(plain_password: str, hashed_password: str) -> bool:
"""Verify password against hash."""
return pwd_context.verify(plain_password, hashed_password)
def get_password_hash(password: str) -> str:
"""Hash a password."""
return pwd_context.hash(password)
def create_access_token(data: dict, expires_delta: timedelta = None):
"""Create JWT access token with security measures."""
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=15)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
2. Input Validation
Use Pydantic Models:
- Always validate all inputs with Pydantic schemas
- Use type hints for better IDE support
- Implement custom validation logic when needed
- Use
EmailStrfor email validation
Validation Example:
from pydantic import BaseModel, EmailStr, validator, Field
from typing import Optional
class UserCreate(BaseModel):
email: EmailStr
username: str = Field(..., min_length=3, max_length=50)
password: str = Field(..., min_length=8, max_length=128)
@validator('password')
def password_complexity(cls, v):
if not any(c.isupper() for c in v):
raise ValueError('Must contain at least one uppercase letter')
if not any(c.isdigit() for c in v):
raise ValueError('Must contain at least one digit')
return v
3. Database Security
Connection Security:
- Never hardcode database credentials
- Use environment variables for all sensitive data
- Implement SSL connections for PostgreSQL
- Use environment-based configuration for dev/prod
SQL Injection Prevention:
- Always use SQLAlchemy ORM (parameterized queries)
- Avoid raw SQL queries unless absolutely necessary
- Use parameterized queries with proper escaping
4. API Security
Rate Limiting:
- Implement rate limiting to prevent abuse
- Use per-user rate limiting
- Apply stricter limits to sensitive endpoints
from slowapi import Limiter
from slowapi.util import get_remote_address
limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, rate_limit_exceeded_handler)
CORS Configuration:
- Configure CORS properly for production
- Specify allowed origins, methods, and headers
- Don’t use wildcards (*) in production
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["https://yourdomain.com"], # Never use "*"
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=["*"],
)
Input Sanitization:
- Sanitize all user inputs
- Validate and sanitize file uploads
- Use safe HTML escaping for output
5. File Upload Security
Upload Restrictions:
- Limit file size
- Validate file types
- Store uploads outside web root
- Generate secure random filenames
from fastapi import UploadFile, File, HTTPException
MAX_FILE_SIZE = 10 * 1024 * 1024 # 10MB
ALLOWED_EXTENSIONS = {'.jpg', '.jpeg', '.png', '.pdf'}
async def validate_upload(file: UploadFile = File(...)):
# Check file size
contents = await file.read()
if len(contents) > MAX_FILE_SIZE:
raise HTTPException(400, "File too large")
# Check extension
file_ext = os.path.splitext(file.filename)[1].lower()
if file_ext not in ALLOWED_EXTENSIONS:
raise HTTPException(400, "Invalid file type")
# Return validated data
return {
"filename": secure_filename(file.filename),
"size": len(contents),
"content_type": file.content_type
}
6. Error Handling
Don’t Expose Sensitive Errors:
- Never expose stack traces to clients in production
- Use generic error messages
- Log detailed errors server-side
Custom Error Responses:
from fastapi import Request
@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
logger.error(f"Unexpected error: {exc}", exc_info=True)
return JSONResponse(
status_code=500,
content={"detail": "An unexpected error occurred"}
)
7. Security Headers
Set Security Headers:
- X-Content-Type-Options: nosniff
- X-Frame-Options: DENY
- X-XSS-Protection: 1; mode=block
- Content-Security-Policy
- Strict-Transport-Security (HSTS)
from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware
from starlette.middleware.trustedhost import TrustedHostMiddleware
app.add_middleware(HTTPSRedirectMiddleware)
app.add_middleware(
TrustedHostMiddleware,
allowed_hosts=["yourdomain.com"]
)
8. Environment Variables
Secure Configuration:
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
# Database
DATABASE_URL: str
DATABASE_URL_DEV: str
DATABASE_URL_PROD: str
# JWT
SECRET_KEY: str
ALGORITHM: str = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
# Application
DEBUG: bool = False
ENVIRONMENT: str = "development"
class Config:
env_file = ".env"
env_file_encoding = "utf-8"
case_sensitive = True
settings = Settings()
9. Data Protection
Sensitive Data:
- Never log or expose sensitive data
- Use encryption for sensitive fields in database
- Implement proper data masking
HTTPS Required:
- Always use HTTPS in production
- Configure redirect from HTTP to HTTPS
- Set HSTS header
10. Dependency Injection
Secure Dependencies:
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
security = HTTPBearer()
async def get_current_user(
credentials: HTTPAuthorizationCredentials = Depends(security)
) -> User:
"""Get current authenticated user."""
try:
token = credentials.credentials
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
user_id = payload.get("sub")
if not user_id:
raise HTTPException(status_code=401, detail="Invalid token")
user = crud.get_user(db, user_id)
if not user:
raise HTTPException(status_code=404, detail="User not found")
return user
except JWTError:
raise HTTPException(status_code=401, detail="Invalid token")
11. Audit Logging
Track Security Events:
- Log authentication attempts
- Log failed login attempts
- Track sensitive data access
- Keep logs secure and immutable
12. Third-Party Dependencies
Dependency Management:
- Regularly update dependencies
- Use lock files (requirements.txt, poetry.lock)
- Monitor for security vulnerabilities
- Use pip-audit or similar tools
Quick Start Commands
# Create new FastAPI project
pip install fastapi uvicorn alembic sqlalchemy psycopg2-binary python-jose passlib python-multipart
# Initialize database
alembic init alembic
# Create new migration
alembic revision --autogenerate -m "Create initial tables"
# Apply migrations
alembic upgrade head
# Run server
uvicorn app.main:app --reload
Getting Started
- Clone or set up the project structure
- Install dependencies from requirements.txt
- Configure environment variables from .env.example
- Run database migrations with Alembic
- Start the development server
- Access API documentation at
/docs