From 3cccf2e0e802b08552c6726b28b3a42bbc8dcf03 Mon Sep 17 00:00:00 2001 From: Beda Schmid Date: Sun, 1 Mar 2026 21:43:09 -0300 Subject: [PATCH] Fix auth route response injection crash --- backend/app/api/routes_auth.py | 7 +++---- backend/tests/test_security_controls.py | 13 +++++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/backend/app/api/routes_auth.py b/backend/app/api/routes_auth.py index dec1318..4aaaced 100644 --- a/backend/app/api/routes_auth.py +++ b/backend/app/api/routes_auth.py @@ -26,13 +26,12 @@ from app.services.auth_login_throttle import ( clear_login_throttle, record_failed_login_attempt, ) -from app.services.authentication import authenticate_user, issue_user_session, revoke_auth_session try: from fastapi import Response except (ImportError, AttributeError): from fastapi.responses import Response - +from app.services.authentication import authenticate_user, issue_user_session, revoke_auth_session router = APIRouter(prefix="/auth", tags=["auth"]) logger = logging.getLogger(__name__) @@ -132,7 +131,7 @@ def _clear_session_cookies(response: Response) -> None: def login( payload: AuthLoginRequest, request: Request, - response: Response | None = None, + response: Response, session: Session = Depends(get_session), ) -> AuthLoginResponse: """Authenticates credentials with throttle protection and returns issued session metadata.""" @@ -241,7 +240,7 @@ def me(context: AuthContext = Depends(require_user_or_admin)) -> AuthSessionResp @router.post("/logout", response_model=AuthLogoutResponse) def logout( - response: Response | None = None, + response: Response, context: AuthContext = Depends(require_user_or_admin), session: Session = Depends(get_session), ) -> AuthLogoutResponse: diff --git a/backend/tests/test_security_controls.py b/backend/tests/test_security_controls.py index c99c834..183f9fe 100644 --- a/backend/tests/test_security_controls.py +++ b/backend/tests/test_security_controls.py @@ -784,6 +784,15 @@ class AuthLoginRouteThrottleTests(unittest.TestCase): self.commit_count += 1 + @staticmethod + def _response_stub() -> SimpleNamespace: + """Builds a minimal response object for direct route invocation.""" + + return SimpleNamespace( + set_cookie=lambda *_args, **_kwargs: None, + delete_cookie=lambda *_args, **_kwargs: None, + ) + @staticmethod def _request_stub(ip_address: str = "203.0.113.2", user_agent: str = "unit-test") -> SimpleNamespace: """Builds request-like object containing client host and user-agent header fields.""" @@ -810,6 +819,7 @@ class AuthLoginRouteThrottleTests(unittest.TestCase): auth_routes_module.login( payload=payload, request=self._request_stub(), + response=self._response_stub(), session=session, ) self.assertEqual(raised.exception.status_code, 429) @@ -839,6 +849,7 @@ class AuthLoginRouteThrottleTests(unittest.TestCase): auth_routes_module.login( payload=payload, request=self._request_stub(), + response=self._response_stub(), session=session, ) self.assertEqual(raised.exception.status_code, 429) @@ -876,6 +887,7 @@ class AuthLoginRouteThrottleTests(unittest.TestCase): response = auth_routes_module.login( payload=payload, request=self._request_stub(), + response=self._response_stub(), session=session, ) self.assertEqual(response.access_token, "session-token") @@ -893,6 +905,7 @@ class AuthLoginRouteThrottleTests(unittest.TestCase): auth_routes_module.login( payload=payload, request=self._request_stub(), + response=self._response_stub(), session=session, ) self.assertEqual(raised.exception.status_code, 503)