FastAPI · Lesson 4 of 5
Dependency Injection and Auth
Share logic with Depends, and protect routes with tokens.
- Intermediate
- 16 min read
- 3 objectives
Before this lessonLesson 3: Models, Responses and Errors
What you will learn
- Write a dependency
- Inject a database session
- Protect a route
Many endpoints need the same things: a database session, the current user, pagination settings. Dependency injection lets you declare what an endpoint needs, and FastAPI provides it. You write the shared logic once with Depends.
A simple dependency
from fastapi import Depends
def pagination(skip: int = 0, limit: int = 20):
return {"skip": skip, "limit": min(limit, 100)}
@app.get("/items")
def list_items(page: dict = Depends(pagination)):
return page
@app.get("/users")
def list_users(page: dict = Depends(pagination)):
return pageDependencies with cleanup
A dependency that uses yield runs setup before the endpoint and cleanup after it, perfect for database sessions.
from sqlalchemy.orm import Session
from .database import SessionLocal
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.get("/posts")
def posts(db: Session = Depends(get_db)):
return db.query(Post).all()Authentication with a bearer token
FastAPI includes security helpers. The pattern: a dependency reads and verifies the token, and any route that lists it is protected.
from fastapi.security import OAuth2PasswordBearer
import jwt # pip install pyjwt
oauth2 = OAuth2PasswordBearer(tokenUrl="login")
SECRET, ALGO = "change-me", "HS256" # load from environment in real apps
def current_user(token: str = Depends(oauth2)):
try:
payload = jwt.decode(token, SECRET, algorithms=[ALGO])
except jwt.PyJWTError:
raise HTTPException(401, "Invalid token", headers={"WWW-Authenticate": "Bearer"})
return payload["sub"]
@app.get("/me")
def me(user: str = Depends(current_user)):
return {"user": user}Issuing tokens on login uses jwt.encode({"sub": username, "exp": ...}, SECRET, algorithm=ALGO). Passwords must be stored hashed, for example with passlib's bcrypt or argon2, never in plain text.
Router-level dependencies
from fastapi import APIRouter
admin = APIRouter(prefix="/admin", dependencies=[Depends(current_user)])
@admin.get("/stats")
def stats():
return {"users": 10}
app.include_router(admin)# Write your solution here
