Phase 3: WebSocket CSRF, SameSite=Lax, Tenant FK CASCADE

This commit is contained in:
Agent Zero
2026-08-04 09:27:10 +02:00
parent 4a104af615
commit e7edc46286
3 changed files with 145 additions and 3 deletions
+1 -1
View File
@@ -39,7 +39,7 @@ class Settings(BaseSettings):
bcrypt_rounds: int = 12
session_cookie_name: str = "leocrm_session"
session_cookie_secure: bool = True # Secure by default — set to False only for local HTTP development
session_cookie_samesite: str = "strict" # Strict blocks WebSocket cookies; use Lax only if WS needed
session_cookie_samesite: str = "lax" # Lax allows WebSocket cookies while preventing CSRF on top-level navigations
session_cookie_httponly: bool = True
password_reset_expiry_hours: int = 1
+17 -2
View File
@@ -116,8 +116,23 @@ def verify_ws_origin(websocket) -> bool:
# CSRF token validation: check query parameter 'csrf_token' against session
# The frontend must send ?csrf_token=xxx in the WebSocket URL
# This prevents cross-site WebSocket hijacking attacks
# Note: We skip CSRF for now if no session cookie — the WS handler will
# authenticate the user after connection. Origin check is the primary defense.
csrf_token = websocket.query_params.get("csrf_token", "")
if not csrf_token:
logger.warning("WebSocket connection rejected: missing csrf_token query parameter")
return False
# Validate CSRF token against session in Redis
session_id = websocket.cookies.get(settings.session_cookie_name)
if not session_id:
logger.warning("WebSocket connection rejected: missing session cookie")
return False
redis = get_redis()
session_data = await get_session_data(redis, session_id)
if not session_data or session_data.get("csrf_token") != csrf_token:
logger.warning("WebSocket connection rejected: invalid CSRF token")
return False
return True