From acc8c0658dfa0d4d93b9485077f9c686324642a8 Mon Sep 17 00:00:00 2001 From: momorew Date: Tue, 8 Sep 2026 18:32:55 +0530 Subject: [PATCH] csrf issue --- .env.test | 1 + app/middleware/csrf.py | 16 ++-- app/modules/auth/routes/auth_routes.py | 120 +++++++++++++++++-------- app/modules/auth/sso_router.py | 11 +++ 4 files changed, 102 insertions(+), 46 deletions(-) diff --git a/.env.test b/.env.test index 4f71ff2..fdaee37 100644 --- a/.env.test +++ b/.env.test @@ -47,6 +47,7 @@ MAX_CONTEXT_CHARS=4000 MIN_SIMILARITY_SCORE=0.18 LOG_LEVEL=INFO CORS_ORIGINS=https://saas-test.maskantech.in,https://docqubeapp-test.maskantech.in,https://docqube-test.maskantech.in,http://localhost:5173,http://localhost:3000 +COOKIE_DOMAIN=.maskantech.in SMTP_HOST=smtp.gmail.com SMTP_PORT=465 SMTP_USER=info.maskantech@gmail.com diff --git a/app/middleware/csrf.py b/app/middleware/csrf.py index 80bd8d7..7cf955c 100644 --- a/app/middleware/csrf.py +++ b/app/middleware/csrf.py @@ -34,25 +34,27 @@ class CSRFMiddleware(BaseHTTPMiddleware): content={"detail": "CSRF verification failed"} ) if not csrf_cookie: - self._set_csrf_cookie(response) + self._set_csrf_cookie(response, request) return response response = await call_next(request) if not csrf_cookie: - self._set_csrf_cookie(response) + self._set_csrf_cookie(response, request) return response - def _set_csrf_cookie(self, response): + def _set_csrf_cookie(self, response, request: Request = None): """Helper to set the CSRF cookie with appropriate security flags.""" - is_prod = settings.APP_ENV == "production" + is_secure = settings.APP_ENV in ["production", "test", "testing"] or (request and request.url.scheme == "https") + samesite_mode = "none" if is_secure else "lax" + cookie_domain = getattr(settings, "COOKIE_DOMAIN", None) or None response.set_cookie( key="csrf_token", value=str(uuid.uuid4()), httponly=False, - samesite="none" if is_prod else "lax", - secure=is_prod, - domain=settings.COOKIE_DOMAIN if is_prod else None, + samesite=samesite_mode, + secure=is_secure, + domain=cookie_domain, path="/" ) \ No newline at end of file diff --git a/app/modules/auth/routes/auth_routes.py b/app/modules/auth/routes/auth_routes.py index 0c33ba0..2ad0ece 100644 --- a/app/modules/auth/routes/auth_routes.py +++ b/app/modules/auth/routes/auth_routes.py @@ -45,13 +45,17 @@ def login( ): token_data = AuthController.login_user(form_data, db, request) + is_secure = settings.APP_ENV in ["production", "test", "testing"] or request.url.scheme == "https" + samesite_mode = "none" if is_secure else "lax" + cookie_domain = getattr(settings, "COOKIE_DOMAIN", None) or None + response.set_cookie( key="docqube_access_token", value=token_data["access_token"], httponly=True, - secure=settings.APP_ENV == "production", - samesite="none" if settings.APP_ENV == "production" else "lax", - domain=settings.COOKIE_DOMAIN if settings.APP_ENV == "production" else None, + secure=is_secure, + samesite=samesite_mode, + domain=cookie_domain, max_age=3600, path="/", ) @@ -60,9 +64,9 @@ def login( key="docqube_refresh_token", value=token_data["refresh_token"], httponly=True, - secure=settings.APP_ENV == "production", - samesite="none" if settings.APP_ENV == "production" else "lax", - domain=settings.COOKIE_DOMAIN if settings.APP_ENV == "production" else None, + secure=is_secure, + samesite=samesite_mode, + domain=cookie_domain, max_age=7 * 24 * 3600, path="/api/auth/refresh", ) @@ -71,21 +75,31 @@ def login( key="docqube_has_session", value="true", httponly=False, - secure=settings.APP_ENV == "production", - samesite="none" if settings.APP_ENV == "production" else "lax", - domain=settings.COOKIE_DOMAIN if settings.APP_ENV == "production" else None, + secure=is_secure, + samesite=samesite_mode, + domain=cookie_domain, max_age=7 * 24 * 3600, path="/", ) + + response.set_cookie( + key="csrf_token", + value=str(uuid.uuid4()), + httponly=False, + secure=is_secure, + samesite=samesite_mode, + domain=cookie_domain, + path="/" + ) if hasattr(request.state, "new_device_id"): response.set_cookie( key="docqube_device_id", value=request.state.new_device_id, httponly=True, - secure=settings.APP_ENV == "production", - samesite="none" if settings.APP_ENV == "production" else "lax", - domain=settings.COOKIE_DOMAIN if settings.APP_ENV == "production" else None, + secure=is_secure, + samesite=samesite_mode, + domain=cookie_domain, max_age=365 * 24 * 3600, path="/", ) @@ -97,14 +111,17 @@ def google_login( request: Request, response: Response, payload: GoogleLoginIn, db: Session = Depends(get_db) ): token_data = AuthController.google_login(payload, db, request) + is_secure = settings.APP_ENV in ["production", "test", "testing"] or request.url.scheme == "https" + samesite_mode = "none" if is_secure else "lax" + cookie_domain = getattr(settings, "COOKIE_DOMAIN", None) or None response.set_cookie( key="docqube_access_token", value=token_data["access_token"], httponly=True, - secure=settings.APP_ENV == "production", - samesite="none" if settings.APP_ENV == "production" else "lax", - domain=settings.COOKIE_DOMAIN if settings.APP_ENV == "production" else None, + secure=is_secure, + samesite=samesite_mode, + domain=cookie_domain, max_age=3600, path="/", ) @@ -113,9 +130,9 @@ def google_login( key="docqube_refresh_token", value=token_data["refresh_token"], httponly=True, - secure=settings.APP_ENV == "production", - samesite="none" if settings.APP_ENV == "production" else "lax", - domain=settings.COOKIE_DOMAIN if settings.APP_ENV == "production" else None, + secure=is_secure, + samesite=samesite_mode, + domain=cookie_domain, max_age=7 * 24 * 3600, path="/api/auth/refresh", ) @@ -124,21 +141,31 @@ def google_login( key="docqube_has_session", value="true", httponly=False, - secure=settings.APP_ENV == "production", - samesite="none" if settings.APP_ENV == "production" else "lax", - domain=settings.COOKIE_DOMAIN if settings.APP_ENV == "production" else None, + secure=is_secure, + samesite=samesite_mode, + domain=cookie_domain, max_age=7 * 24 * 3600, path="/", ) + + response.set_cookie( + key="csrf_token", + value=str(uuid.uuid4()), + httponly=False, + secure=is_secure, + samesite=samesite_mode, + domain=cookie_domain, + path="/" + ) if hasattr(request.state, "new_device_id"): response.set_cookie( key="docqube_device_id", value=request.state.new_device_id, httponly=True, - secure=settings.APP_ENV == "production", - samesite="none" if settings.APP_ENV == "production" else "lax", - domain=settings.COOKIE_DOMAIN if settings.APP_ENV == "production" else None, + secure=is_secure, + samesite=samesite_mode, + domain=cookie_domain, max_age=365 * 24 * 3600, path="/", ) @@ -225,13 +252,17 @@ def refresh_token(request: Request, response: Response, db: Session = Depends(ge new_access_token = create_access_token(payload_access) + is_secure = settings.APP_ENV in ["production", "test", "testing"] or (request and request.url.scheme == "https") + samesite_mode = "none" if is_secure else "lax" + cookie_domain = getattr(settings, "COOKIE_DOMAIN", None) or None + response.set_cookie( key="docqube_access_token", value=new_access_token, httponly=True, - secure=settings.APP_ENV == "production", - samesite="none" if settings.APP_ENV == "production" else "lax", - domain=settings.COOKIE_DOMAIN if settings.APP_ENV == "production" else None, + secure=is_secure, + samesite=samesite_mode, + domain=cookie_domain, max_age=3600, path="/", ) @@ -240,9 +271,9 @@ def refresh_token(request: Request, response: Response, db: Session = Depends(ge key="docqube_has_session", value="true", httponly=False, - secure=settings.APP_ENV == "production", - samesite="none" if settings.APP_ENV == "production" else "lax", - domain=settings.COOKIE_DOMAIN if settings.APP_ENV == "production" else None, + secure=is_secure, + samesite=samesite_mode, + domain=cookie_domain, max_age=7 * 24 * 3600, path="/", ) @@ -304,26 +335,37 @@ def logout( except Exception: pass + is_secure = settings.APP_ENV in ["production", "test", "testing"] or (request and request.url.scheme == "https") + samesite_mode = "none" if is_secure else "lax" + cookie_domain = getattr(settings, "COOKIE_DOMAIN", None) or None + response.delete_cookie( "docqube_access_token", path="/", - samesite="none" if settings.APP_ENV == "production" else "lax", - secure=settings.APP_ENV == "production", - domain=settings.COOKIE_DOMAIN if settings.APP_ENV == "production" else None, + samesite=samesite_mode, + secure=is_secure, + domain=cookie_domain, ) response.delete_cookie( "docqube_refresh_token", path="/api/auth/refresh", - samesite="none" if settings.APP_ENV == "production" else "lax", - secure=settings.APP_ENV == "production", - domain=settings.COOKIE_DOMAIN if settings.APP_ENV == "production" else None, + samesite=samesite_mode, + secure=is_secure, + domain=cookie_domain, ) response.delete_cookie( "docqube_has_session", path="/", - samesite="none" if settings.APP_ENV == "production" else "lax", - secure=settings.APP_ENV == "production", - domain=settings.COOKIE_DOMAIN if settings.APP_ENV == "production" else None, + samesite=samesite_mode, + secure=is_secure, + domain=cookie_domain, + ) + response.delete_cookie( + "csrf_token", + path="/", + samesite=samesite_mode, + secure=is_secure, + domain=cookie_domain, ) return {"status": "success", "message": "Logged out"} diff --git a/app/modules/auth/sso_router.py b/app/modules/auth/sso_router.py index 3c88487..1ef0506 100644 --- a/app/modules/auth/sso_router.py +++ b/app/modules/auth/sso_router.py @@ -4,6 +4,7 @@ import time import logging import hmac import hashlib +import uuid from app.db.database import get_db from app.core.settings import settings @@ -133,6 +134,16 @@ async def sso_login( max_age=7 * 24 * 3600 ) + response.set_cookie( + key="csrf_token", + value=str(uuid.uuid4()), + httponly=False, + secure=is_secure, + samesite=samesite_mode, + domain=cookie_domain, + path="/" + ) + return { "status": "success", "message": "SSO Login successful",