🎓 What You Will Learn
- Cookie Basics: Understanding HTTP cookies
- Setting Cookies: Creating and storing cookies
- Reading Cookies: Accessing cookie values from requests
- Secure Cookies: HttpOnly, Secure, SameSite flags
- Sessions: Using Starlette SessionMiddleware
- Cookie Expiration: Managing cookie lifetime
1How Cookies Work
Cookies are small files stored on the client side. The server sends cookies in responses, the browser stores them, and sends them back with future requests. Perfect for sessions and preferences.
Cookie Lifecycle: Server sets cookie in response, browser stores it, browser includes it in all subsequent requests to that domain.
2Setting Cookies in FastAPI
Use Response.set_cookie() to set cookies in your responses.
from fastapi import FastAPI
from fastapi.responses import Response
app = FastAPI()
@app.get("/set-cookie")
async def set_cookie():
response = Response({"message": "Cookie set"})
response.set_cookie(key="user_id", value="12345")
return response
@app.post("/login")
async def login(username: str):
response = Response({"status": "logged in"})
response.set_cookie(
key="session_id",
value="abc123def456",
max_age=3600, # 1 hour
httponly=True, # Not accessible via JavaScript
secure=True, # HTTPS only
samesite="lax" # CSRF protection
)
return response
3Reading Cookies from Requests
Access cookies from the request using the Cookie parameter.
from fastapi import FastAPI, Cookie
from typing import Optional
app = FastAPI()
@app.get("/get-cookie")
async def get_cookie(user_id: Optional[str] = Cookie(None)):
return {"user_id": user_id}
@app.get("/profile")
async def get_profile(session_id: str = Cookie(...)):
# session_id is required (... makes it mandatory)
return {"session_id": session_id, "user": "John"}
4Secure Cookie Flags
Always use security flags when setting sensitive cookies.
| Flag | Purpose | Use Case |
|---|---|---|
| HttpOnly | Cookie not accessible via JavaScript | Session tokens, auth cookies |
| Secure | Cookie only sent over HTTPS | Production environments |
| SameSite | Prevent CSRF attacks | Strict=same-site only, Lax=navigation allowed |
| Max-Age | Cookie expiration in seconds | Sessions, temporary tokens |
| Domain | Cookie accessible on specific domains | Sub-domain sharing |
@app.post("/login")
async def secure_login(username: str):
response = Response({"status": "logged in"})
response.set_cookie(
key="session_token",
value="encrypted_token_here",
max_age=86400, # 1 day
httponly=True, # Prevent JavaScript access
secure=True, # HTTPS only
samesite="strict", # Strict CSRF protection
domain="example.com" # Specific domain
)
return response
Never use HttpOnly=False for sensitive cookies. Always protect session and auth cookies with HttpOnly flag.
5Using Starlette SessionMiddleware
For production, use Starlette SessionMiddleware for automatic session management.
from fastapi import FastAPI, Request
from starlette.middleware.sessions import SessionMiddleware
app = FastAPI()
# Add session middleware
app.add_middleware(
SessionMiddleware,
secret_key="your-secret-key-here",
max_age=3600, # Session expires in 1 hour
https_only=True, # HTTPS only in production
same_site="lax"
)
@app.post("/login")
async def login(request: Request, username: str):
request.session["user"] = username
return {"message": f"Logged in as {username}"}
@app.get("/profile")
async def profile(request: Request):
user = request.session.get("user")
if not user:
return {"error": "Not logged in"}
return {"user": user}
@app.post("/logout")
async def logout(request: Request):
request.session.clear()
return {"message": "Logged out"}
SessionMiddleware: Automatically encrypts session data and stores it in a signed cookie. No server-side storage needed.
6Managing Cookie Expiration
Cookies can expire automatically based on max_age or expires.
from fastapi import FastAPI
from fastapi.responses import Response
from datetime import datetime, timedelta
app = FastAPI()
@app.post("/set-temporary-cookie")
async def set_temp_cookie():
response = Response({"status": "temp cookie set"})
# Expires in 30 minutes
response.set_cookie(
key="temp_token",
value="temp_value",
max_age=1800 # 30 minutes in seconds
)
return response
@app.post("/set-persistent-cookie")
async def set_persistent_cookie():
response = Response({"status": "persistent cookie set"})
# Expires at specific datetime
expires = datetime.now() + timedelta(days=7)
response.set_cookie(
key="persistent",
value="persistent_value",
expires=expires
)
return response
@app.post("/delete-cookie")
async def delete_cookie():
response = Response({"status": "cookie deleted"})
# Delete by setting max_age to 0
response.delete_cookie(key="session_id")
return response
7Testing Cookies
Test cookie handling with TestClient.
from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app)
def test_set_cookie():
response = client.get("/set-cookie")
assert response.status_code == 200
assert "user_id" in client.cookies
def test_cookie_roundtrip():
# Set cookie
client.get("/set-cookie")
# Verify cookie is sent in next request
response = client.get("/get-cookie")
assert response.json()["user_id"] == "12345"
def test_session():
# Login (sets session)
client.post("/login?username=john")
# Verify session is available
response = client.get("/profile")
assert response.json()["user"] == "john"
# Logout
client.post("/logout")
# Verify session is cleared
response = client.get("/profile")
assert "error" in response.json()
8Cookie Security Best Practices
- Always use
httponly=Truefor session/auth cookies - Always use
secure=Truein production (HTTPS only) - Set appropriate
samesiteflag (Strict or Lax) - Use short
max_agefor sensitive cookies (1-24 hours) - Never store sensitive data directly in cookies (use sessions instead)
- Validate and sanitize cookie values on the server
- Use signed/encrypted cookies for integrity
- Clear cookies on logout
- Test cookie behavior across browsers
- Monitor for suspicious cookie access patterns
9Cookies with CORS
When using CORS with cookies, special configuration is needed.
from fastapi import FastAPI
from starlette.middleware.cors import CORSMiddleware
from starlette.middleware.sessions import SessionMiddleware
app = FastAPI()
# Session middleware must come BEFORE CORS
app.add_middleware(SessionMiddleware, secret_key="secret")
# CORS must allow credentials
app.add_middleware(
CORSMiddleware,
allow_origins=["https://frontend.example.com"],
allow_credentials=True, # Important for cookies!
allow_methods=["*"],
allow_headers=["*"]
)
Middleware Order: SessionMiddleware must be added BEFORE CORSMiddleware. Middleware executes in reverse order (last added runs first).
10Common Cookie Patterns
| Pattern | Use Case | Example |
|---|---|---|
| Session cookie | Track logged-in user | session_id with HttpOnly |
| Preference cookie | Remember user preferences | theme, language, timezone |
| Tracking cookie | Analytics and behavior | Google Analytics _ga |
| CSRF token cookie | Prevent CSRF attacks | csrf_token matching form token |
| Auth cookie | Stateless authentication | JWT token in HttpOnly cookie |
11Debugging Cookies
Use browser DevTools to inspect cookies.
# Open browser DevTools (F12)
# Go to Application tab
# Click Cookies in left sidebar
# View all cookies for the domain
# Check cookie attributes:
# - Name: cookie name
# - Value: cookie value
# - Domain: which domain can access
# - Path: which paths can access
# - Expires/Max-Age: when it expires
# - HttpOnly: if JavaScript can access
# - Secure: if HTTPS only
# - SameSite: CSRF protection level
12Migrating from Cookies to Tokens
JWT tokens are an alternative to cookies for stateless authentication.
from fastapi import FastAPI, Depends
from fastapi.security import HTTPBearer, HTTPAuthCredentials
app = FastAPI()
security = HTTPBearer()
@app.post("/login")
async def login(username: str):
token = create_jwt_token(username)
response = Response({"token": token})
# Store JWT in HttpOnly cookie
response.set_cookie(
key="access_token",
value=token,
httponly=True,
secure=True,
max_age=3600
)
return response
@app.get("/profile")
async def profile(token: str = Depends(get_token)):
user = decode_jwt_token(token)
return {"user": user}
13Summary & Recommendations
Master cookies to build secure, stateful FastAPI applications. Use SessionMiddleware for simplicity, or JWT tokens for stateless APIs.
🚀 Congratulations! You now understand how to securely handle cookies in FastAPI. Build session management and authentication with confidence!