"""Test CSRF with header.""" import time class TestCSRFHeader: """Test CSRF protection with headers.""" def test_csrf_with_header(self, client, app): """Test CSRF protection using headers.""" # Since we disabled CSRF for testing, this test verifies the login flow # In production, CSRF would be required # Generate unique username to avoid conflicts test_username = f"testuser_csrf_{int(time.time() * 1000)}" # Get login page response = client.get("/auth/login") assert response.status_code == 200 # In test mode, CSRF is disabled, so we can login without token login_data = { "username": test_username, "password": "TestPass123", } # First register the user register_response = client.post( "/auth/register", data={ "username": test_username, "password": "TestPass123", "confirm_password": "TestPass123", "acknowledge": "true", }, ) assert register_response.status_code in [200, 302] # Now test login response = client.post( "/auth/login", data=login_data, follow_redirects=False, ) assert response.status_code in [200, 302] if response.status_code == 302: # Login successful, redirecting assert "/" in response.location or "/research" in response.location def test_api_csrf_exemption(self, authenticated_client): """Test that API routes are exempt from CSRF.""" # API routes should work without CSRF token response = authenticated_client.get("/api/v1/health") assert response.status_code == 200 # Research API should also work response = authenticated_client.get("/research/api/history") assert response.status_code in [200, 404] # 404 if no history yet def test_csrf_blueprint_exemptions_configured(self, app): """Test that only api_v1 blueprint is CSRF-exempt. Flask-WTF 1.2.2 requires Blueprint objects (not strings) in _exempt_blueprints. Only api_v1 should be exempt — the browser-facing blueprints (api, benchmark, research) should require CSRF tokens since the frontend already sends them. """ csrf = app.extensions.get("csrf") assert csrf is not None, "CSRFProtect extension not initialized" exempt_names = {bp.name for bp in csrf._exempt_blueprints} # api_v1 should be exempt (programmatic REST API) assert "api_v1" in exempt_names, ( "Blueprint 'api_v1' missing from _exempt_blueprints. " "Ensure csrf.exempt() receives the Blueprint object, not a string." ) # Browser-facing blueprints should NOT be exempt for should_not_be_exempt in ("api", "benchmark", "research"): assert should_not_be_exempt not in exempt_names, ( f"Blueprint '{should_not_be_exempt}' should not be in " f"_exempt_blueprints — it is browser-facing and the frontend " f"already sends CSRF tokens." )