python 58 lines · 8 steps

Cookie session auth in FastAPI

A full login-to-logout flow that mints opaque session tokens, stores them server-side, and rides in a hardened HTTP-only cookie.

Explained by highlit
1import secrets
2from datetime import datetime, timedelta, timezone
3 
4from fastapi import APIRouter, Cookie, Depends, HTTPException, Response, status
5from pydantic import BaseModel
6 
7router = APIRouter(tags=["auth"])
8 
9SESSION_COOKIE = "session_id"
10SESSION_TTL = timedelta(days=7)
11 
12 
13class LoginPayload(BaseModel):
14 email: str
15 password: str
16 
17 
18@router.post("/login")
19async def login(payload: LoginPayload, response: Response):
20 user = await users.authenticate(payload.email, payload.password)
21 if user is None:
22 raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Invalid credentials")
23 
24 token = secrets.token_urlsafe(32)
25 await sessions.store(token, user_id=user.id, expires=datetime.now(timezone.utc) + SESSION_TTL)
26 
27 response.set_cookie(
28 key=SESSION_COOKIE,
29 value=token,
30 max_age=int(SESSION_TTL.total_seconds()),
31 httponly=True,
32 secure=True,
33 samesite="lax",
34 path="/",
35 )
36 return {"id": user.id, "email": user.email}
37 
38 
39async def current_user(session_id: str | None = Cookie(default=None)):
40 if session_id is None:
41 raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Not authenticated")
42 session = await sessions.get(session_id)
43 if session is None or session.is_expired:
44 raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Session expired")
45 return await users.get(session.user_id)
46 
47 
48@router.post("/logout")
49async def logout(response: Response, session_id: str | None = Cookie(default=None)):
50 if session_id is not None:
51 await sessions.revoke(session_id)
52 response.delete_cookie(SESSION_COOKIE, path="/")
53 return {"detail": "logged out"}
54 
55 
56@router.get("/me")
57async def me(user=Depends(current_user)):
58 return {"id": user.id, "email": user.email}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Server-side sessions keyed by an opaque random token keep secrets off the client and let you revoke access instantly.
  2. 2Hardening a session cookie means combining httponly, secure, samesite, and a bounded max_age together.
  3. 3A shared dependency turns 'is this request authenticated?' into one reusable check any route can require.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Cookie session auth in FastAPI — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code