On this page
article
FastAPI Authentication & Deployment
Implement JWT authentication, OAuth2, middleware, and deploy FastAPI with Docker and uvicorn.
Production APIs require authentication, middleware, and reliable deployment. FastAPI provides built-in support for industry-standard security patterns.
OAuth2 with JWT
from datetime import datetime, timedelta, timezone
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from passlib.context import CryptContext
SECRET_KEY = "your-secret-key-change-in-production"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
def create_access_token(data: dict, expires_delta: timedelta | None = None):
to_encode = data.copy()
expire = datetime.now(timezone.utc) + (expires_delta or timedelta(minutes=15))
to_encode.update({"exp": expire})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
async def get_current_user(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username = payload.get("sub")
if username is None:
raise credentials_exception
except JWTError:
raise credentials_exception
return username
@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
# Verify username/password against database
if form_data.username != "admin" or form_data.password != "secret":
raise HTTPException(status_code=400, detail="Incorrect credentials")
token = create_access_token(data={"sub": form_data.username})
return {"access_token": token, "token_type": "bearer"}
@app.get("/me")
async def read_users_me(current_user: str = Depends(get_current_user)):
return {"username": current_user}
Middleware
import time
from fastapi import Request
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
start = time.perf_counter()
response = await call_next(request)
process_time = time.perf_counter() - start
response.headers["X-Process-Time"] = str(process_time)
return response
CORS Configuration
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["https://myfrontend.com"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
Testing
from fastapi.testclient import TestClient
client = TestClient(app)
def test_read_root():
response = client.get("/")
assert response.status_code == 200
assert response.json() == {"message": "Hello, FastAPI!"}
def test_create_item():
response = client.post("/items/", json={"name": "Test", "price": 9.99})
assert response.status_code == 201
Docker Deployment
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]
Production Tips
- Use multiple workers:
uvicorn app.main:app --workers 4 - Put nginx or a load balancer in front for SSL termination
- Store secrets in environment variables, not code
- Enable rate limiting with slowapi or similar
- Monitor with Prometheus metrics via starlette-exporter
FastAPI’s performance, type safety, and auto-generated docs make it the top choice for modern Python API development.