FastAPI Authentication

6 Kernkonzepte
Die wichtigsten FastAPI-Konzepte für Authentifizierung & Sicherheit: OAuth2 · JWT · Passwort-Hashing · Login · geschützte Endpunkte · Sicherheit FastAPI bietet integrierte Unterstützung für OAuth2 und JWT. Diese Cheatsheet zeigt, wie Sie eine sichere Authentifizierung mit Passwort-Hashing, Token-basiertem Login und geschützten Routen implementieren.

OAuth2 & Security – Konfiguration der Authentifizierung

OAuth2PasswordBearer · SECRET_KEY · ALGORITHM
from fastapi.security import OAuth2PasswordBearer oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/token") SECRET_KEY = "supersecretkey" ALGORITHM = "HS256" ACCESS_TOKEN_EXPIRE_MINUTES = 30

OAuth2 ist der Standard für die Token-basierte Authentifizierung. FastAPI bietet mit OAuth2PasswordBearer eine einfache Möglichkeit, den Token-Abfluss zu implementieren.

Beispiele
# Konfiguration der Authentifizierung
from fastapi import FastAPI
from fastapi.security import OAuth2PasswordBearer
from datetime import timedelta
app = FastAPI()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/token")
# Sicherheitskonfiguration (in .env oder config)
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
# OAuth2-Scopes (optional)
oauth2_scheme = OAuth2PasswordBearer(
tokenUrl="/token",
scopes={"me": "Eigene Daten", "admin": "Administration"}
)
Tipp: Speichern Sie SECRET_KEY und sensible Konfigurationen in Umgebungsvariablen oder einer .env-Datei – niemals direkt im Code!

JWT-Token – Erstellen & Verifizieren

create_access_token · decode · verify
# Installation: pip install python-jose[cryptography] from jose import JWTError, jwt def create_access_token(data: dict): to_encode = data.copy() expire = datetime.utcnow() + timedelta(minutes=30) to_encode.update({"exp": expire}) return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)

JWT-Token werden mit jwt.encode() erstellt und mit jwt.decode() verifiziert. Die Token enthalten Claims wie Benutzer-ID und Ablaufzeit.

Beispiele
# JWT-Token erstellen
from jose import jwt
from datetime import datetime, timedelta
def create_access_token(data: dict, expires_delta: timedelta = None):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=15)
to_encode.update({"exp": expire, "iat": datetime.utcnow()})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
# Token verifizieren
def verify_token(token: str):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
return payload
except JWTError:
raise HTTPException(status_code=401, detail="Ungültiger Token")
# Token mit Claims (z.B. Benutzer-ID)
access_token = create_access_token(
data={"sub": user_id, "role": "admin"}
)
Tipp: Verwenden Sie "sub" (Subject) als Standard-Claim für die Benutzer-ID – das ist ein branchenüblicher Standard in JWT.

Passwort-Hashing – bcrypt & Passlib

hash · verify · bcrypt
# Installation: pip install passlib[bcrypt] from passlib.context import CryptContext pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") def verify_password(plain, hashed): return pwd_context.verify(plain, hashed) def get_password_hash(password): return pwd_context.hash(password)

Passwort-Hashing ist essenziell für die sichere Speicherung von Benutzerpasswörtern. bcrypt ist ein sicherer, adaptiver Hash-Algorithmus.

Beispiele
# Benutzer-Modell mit Passwort-Hash
from pydantic import BaseModel
class User(BaseModel):
id: int
username: str
email: str
hashed_password: str
# Passwort-Hashing-Funktionen
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def get_password_hash(password: str) -> str:
return pwd_context.hash(password)
def verify_password(plain_password: str, hashed_password: str) -> bool:
return pwd_context.verify(plain_password, hashed_password)
# Benutzer erstellen (mit Hash)
hashed = get_password_hash("mein_password")
user = User(id=1, username="admin", email="admin@example.com", hashed_password=hashed)
# Passwort-Validierung
if verify_password("mein_password", user.hashed_password):
print("Passwort korrekt!")
Tipp: bcrypt ist resistent gegen Brute-Force-Angriffe durch seine adaptive Arbeitsfaktor (Runden). Verwenden Sie die Standardrunden (12) für gute Sicherheit bei akzeptabler Performance.

Login-Endpunkt – Token-Austausch

/token · OAuth2PasswordRequestForm · access_token
from fastapi.security import OAuth2PasswordRequestForm @app.post("/token") async def login(form_data: OAuth2PasswordRequestForm = Depends()): user = await authenticate_user(form_data.username, form_data.password) access_token = create_access_token(data={"sub": user.username}) return {"access_token": access_token, "token_type": "bearer"}

Login-Endpunkt verifiziert Benutzername und Passwort und gibt ein JWT-Token zurück, das für geschützte Endpunkte verwendet wird.

Beispiele
# Login-Endpunkt
@app.post("/token", response_model=Token)
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
# Benutzer authentifizieren
user = await authenticate_user(form_data.username, form_data.password)
if not user:
raise HTTPException(
status_code=401,
detail="Ungültiger Benutzername oder Passwort",
headers={"WWW-Authenticate": "Bearer"}
)
# Token erstellen
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(
data={"sub": user.username},
expires_delta=access_token_expires
)
return {"access_token": access_token, "token_type": "bearer"}
# Authentifizierungsfunktion
async def authenticate_user(username: str, password: str):
user = await get_user_by_username(username)
if not user:
return False
if not verify_password(password, user.hashed_password):
return False
return user
Tipp: Der Login-Endpunkt sollte den OAuth2-Standard /token verwenden – das ist kompatibel mit vielen Client-Bibliotheken und Swagger UI.

Geschützte Endpunkte – @jwt_required & get_current_user

Depends(oauth2_scheme) · get_current_user
# Get Current User Dependency async def get_current_user(token: str = Depends(oauth2_scheme)): payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) username = payload.get("sub") user = await get_user_by_username(username) return user @app.get("/users/me") async def read_users_me(current_user: User = Depends(get_current_user)): return current_user

Geschützte Endpunkte verwenden eine Dependency, die den Token aus dem Header extrahiert, validiert und den aktuellen Benutzer zurückgibt.

Beispiele
# Get Current User Dependency
from fastapi import HTTPException, Depends, status
async def get_current_user(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Ungültige Anmeldedaten",
headers={"WWW-Authenticate": "Bearer"}
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
except JWTError:
raise credentials_exception
user = await get_user_by_username(username)
if user is None:
raise credentials_exception
return user
# Geschützter Endpunkt
@app.get("/users/me", response_model=UserResponse)
async def read_users_me(current_user: User = Depends(get_current_user)):
return current_user
# Geschützter Endpunkt mit Scope (Admin)
@app.get("/admin")
async def admin_panel(current_user: User = Depends(get_current_user)):
if current_user.role != "admin":
raise HTTPException(status_code=403, detail="Admin-Rechte erforderlich")
return {"message": "Admin-Bereich"}
Tipp: Verwenden Sie status.HTTP_401_UNAUTHORIZED statt 401 für lesbaren Code und konsistente Statuscodes.

Sicherheit & Best Practices – Headers, CORS, Rate Limiting

CORS · Security Headers · Rate Limiting
# CORS-Konfiguration from fastapi.middleware.cors import CORSMiddleware app.add_middleware( CORSMiddleware, allow_origins=["http://localhost:3000"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"] )

Sicherheit umfasst CORS-Konfiguration, Security-Header und Rate Limiting – für eine robuste und sichere API.

Beispiele
# CORS-Middleware
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
allow_headers=["Content-Type", "Authorization"],
expose_headers=["X-Custom-Header"],
max_age=3600
)
# Security-Header (Middleware)
from starlette.middleware.base import BaseHTTPMiddleware
class SecurityHeadersMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request, call_next):
response = await call_next(request)
response.headers["X-Content-Type-Options"] = "nosniff"
response.headers["X-Frame-Options"] = "DENY"
response.headers["X-XSS-Protection"] = "1; mode=block"
response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
return response
# Rate Limiting (mit slowapi)
# pip install slowapi
from slowapi import Limiter, _rate_limit_exceeded_handler
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)
@app.get("/limited")
@limiter.limit("5/minute")
async def limited_endpoint():
return {"message": "Rate Limiting aktiv"}
Tipp: Kombinieren Sie CORS mit Rate Limiting und Security-Headern für eine produktionsreife API. Verwenden Sie slowapi für einfaches Rate Limiting in FastAPI.

FastAPI Authentication im Überblick

OAuth2 Authorization Framework
Token-basierte Authentifizierung
JWT JSON Web Tokens
Stateless Authentifizierung
bcrypt Passwort-Hashing
Sichere Passwortspeicherung
/token Login-Endpunkt
OAuth2-Password-Flow
Depends Protected Routes
get_current_user
Security CORS, Headers, Rate Limiting
Best Practices

Quick Summary

OAuth2
Authorization
JWT
Token
bcrypt
Hashing
Depends
Protected
CORS
Security
@app.post("/token") · jwt.encode(data, SECRET_KEY) · Depends(get_current_user)