Working on: The Twitch authentication

This commit is contained in:
2025-12-25 21:05:11 +01:00
parent 773288faf0
commit e69d423deb
2 changed files with 12 additions and 5 deletions

View File

@@ -1,5 +1,6 @@
import httpx
import secrets
import logging
from fastapi import APIRouter, Depends, HTTPException, Request, Response
from fastapi.responses import RedirectResponse
from sqlalchemy.orm import Session
@@ -11,6 +12,9 @@ import security
router = APIRouter()
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Dependency to get a DB session
def get_db():
db = SessionLocal()
@@ -27,6 +31,7 @@ async def login_with_twitch(request: Request):
# Generate a random state token for CSRF protection
state = secrets.token_urlsafe(16)
request.session['oauth_state'] = state
logger.info(f"Generated OAuth state: {state} for session.")
# As per RESEARCH_REPORT.md, these are the minimum required scopes
scopes = "chat:read"
@@ -48,7 +53,9 @@ async def auth_twitch_callback(code: str, state: str, request: Request, db: Sess
Step 2 of OAuth flow: Handle the callback from Twitch after user authorization.
"""
# CSRF Protection: Validate the state
if state != request.session.pop('oauth_state', None):
session_state = request.session.pop('oauth_state', None)
if state != session_state:
logger.error(f"OAuth state mismatch! Received state: '{state}', Session state: '{session_state}'")
raise HTTPException(status_code=403, detail="Invalid state parameter. CSRF attack suspected.")
# Step 4: Exchange the authorization code for an access token

View File

@@ -65,13 +65,13 @@ async def lifespan(app: FastAPI):
app = FastAPI(lifespan=lifespan)
# Add middleware to trust proxy headers (X-Forwarded-For, X-Forwarded-Proto)
# This is crucial for running behind a reverse proxy like Nginx or Caddy.
app.add_middleware(ProxyHeadersMiddleware, trusted_hosts="*")
# Add session middleware. A secret key is required for signing the session cookie.
# We can reuse our encryption key for this, but in production you might want a separate key.
# Note: Middleware is applied in reverse order (last added is first executed).
# We want ProxyHeaders to run FIRST (outermost) to fix the scheme/host,
# then SessionMiddleware to run SECOND (inner) so it sees the correct scheme.
app.add_middleware(SessionMiddleware, secret_key=settings.ENCRYPTION_KEY)
app.add_middleware(ProxyHeadersMiddleware, trusted_hosts="*")
# Mount the 'static' directory using an absolute path for reliability
# This MUST be done before the routes that depend on it are defined.