diff --git a/pipelines/web/auth.py b/pipelines/web/auth.py index 092427c..11cf9c3 100644 --- a/pipelines/web/auth.py +++ b/pipelines/web/auth.py @@ -114,11 +114,14 @@ def get_current_session(request: Request) -> AuthSession | None: return None config = get_auth_config() - session = get_workos_client().user_management.load_sealed_session( - session_data=sealed_session, - cookie_password=config.cookie_password, - ) - auth_response = session.authenticate() + try: + session = get_workos_client().user_management.load_sealed_session( + session_data=sealed_session, + cookie_password=config.cookie_password, + ) + auth_response = session.authenticate() + except ValueError: + return None if not getattr(auth_response, "authenticated", False): return None @@ -150,11 +153,14 @@ def get_logout_url(request: Request) -> str: if not sealed_session: return config.logout_redirect_uri - session = get_workos_client().user_management.load_sealed_session( - session_data=sealed_session, - cookie_password=config.cookie_password, - ) - return session.get_logout_url(return_to=config.logout_redirect_uri) + try: + session = get_workos_client().user_management.load_sealed_session( + session_data=sealed_session, + cookie_password=config.cookie_password, + ) + return session.get_logout_url(return_to=config.logout_redirect_uri) + except ValueError: + return config.logout_redirect_uri @lru_cache(maxsize=1) diff --git a/tests/test_web_routes.py b/tests/test_web_routes.py index b15f49b..79eddba 100644 --- a/tests/test_web_routes.py +++ b/tests/test_web_routes.py @@ -115,6 +115,31 @@ def test_logout_redirects_to_workos_and_clears_cookie(monkeypatch) -> None: assert "workos_session=" in response.headers["set-cookie"] +def test_logout_with_invalid_session_cookie_clears_cookie(monkeypatch) -> None: + monkeypatch.setattr(main.auth, "get_auth_config", _fake_auth_config) + monkeypatch.setattr(main.auth, "get_workos_client", _invalid_workos_client) + + client = TestClient(main.app) + client.cookies.set("workos_session", "bad-session-cookie") + response = client.post("/logout", follow_redirects=False) + + assert response.status_code == 303 + assert response.headers["location"] == "http://localhost:8000/" + assert "workos_session=" in response.headers["set-cookie"] + + +def test_invalid_session_cookie_is_treated_as_unauthenticated(monkeypatch) -> None: + monkeypatch.setattr(main.auth, "get_auth_config", _fake_auth_config) + monkeypatch.setattr(main.auth, "get_workos_client", _invalid_workos_client) + + client = TestClient(main.app) + client.cookies.set("workos_session", "bad-session-cookie") + response = client.get("/") + + assert response.status_code == 200 + assert "Sign in" in response.text + + def test_dashboard_route_renders_with_stubbed_repository(monkeypatch) -> None: _patch_authenticated_dashboard(monkeypatch, current_user=_viewer_session()) @@ -199,6 +224,24 @@ def _fake_auth_config() -> auth.AuthConfig: ) +def _invalid_workos_client(): + class InvalidSession: + def authenticate(self): + raise ValueError("invalid session") + + def get_logout_url(self, *, return_to: str) -> str: + raise ValueError("invalid session") + + class DummyUserManagement: + def load_sealed_session(self, *, session_data: str, cookie_password: str): + return InvalidSession() + + class DummyClient: + user_management = DummyUserManagement() + + return DummyClient() + + def _patch_authenticated_dashboard(monkeypatch, *, current_user: auth.AuthSession) -> None: monkeypatch.setattr(main.auth, "get_current_session", lambda request: current_user)