feat: Phase 9 — Authenticated Testing + Legal Basis Validator (lit. mapping)
Phase 9: Playwright login + 5 post-login checks: - §312k BGB: Kündigungsbutton (2 Klicks) - Art. 17 DSGVO: Konto löschen - Art. 20 DSGVO: Daten exportieren - Art. 7(3): Einwilligungen widerrufen - Art. 15: Profildaten einsehen Auto-detects login form selectors. Credentials destroyed after test. Legal Basis Validator: Checks 7 common lit-mapping mistakes: - Cookie tracking on lit. f instead of lit. a (Planet49) - Analytics on lit. b (contract overextension) - Klarna without Art. 22 reference - Session recording without consent Integrated into website scan pipeline. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,7 @@ from fastapi.middleware.cors import CORSMiddleware
|
||||
from pydantic import BaseModel
|
||||
|
||||
from services.consent_scanner import run_consent_test, ConsentTestResult
|
||||
from services.authenticated_scanner import run_authenticated_test, AuthTestResult
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format="%(levelname)s:%(name)s: %(message)s")
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -84,3 +85,90 @@ async def scan_consent(req: ScanRequest):
|
||||
},
|
||||
scanned_at=datetime.now(timezone.utc).isoformat(),
|
||||
)
|
||||
|
||||
|
||||
class AuthScanRequest(BaseModel):
|
||||
url: str
|
||||
username: str
|
||||
password: str
|
||||
username_selector: str = ""
|
||||
password_selector: str = ""
|
||||
submit_selector: str = ""
|
||||
|
||||
|
||||
class AuthCheckInfo(BaseModel):
|
||||
found: bool = False
|
||||
text: str = ""
|
||||
legal_ref: str = ""
|
||||
|
||||
|
||||
class AuthScanResponse(BaseModel):
|
||||
url: str
|
||||
authenticated: bool
|
||||
login_error: str = ""
|
||||
checks: dict[str, AuthCheckInfo]
|
||||
findings_count: int
|
||||
scanned_at: str
|
||||
|
||||
|
||||
LEGAL_REFS = {
|
||||
"cancel_subscription": "§312k BGB (Kuendigungsbutton)",
|
||||
"delete_account": "Art. 17 DSGVO (Recht auf Loeschung)",
|
||||
"export_data": "Art. 20 DSGVO (Datenportabilitaet)",
|
||||
"consent_settings": "Art. 7 Abs. 3 DSGVO (Widerruf der Einwilligung)",
|
||||
"profile_visible": "Art. 15 DSGVO (Auskunftsrecht)",
|
||||
}
|
||||
|
||||
|
||||
@app.post("/authenticated-scan", response_model=AuthScanResponse)
|
||||
async def authenticated_scan(req: AuthScanRequest):
|
||||
"""Test post-login functionality. Credentials are destroyed after test."""
|
||||
logger.info("Starting authenticated test for %s", req.url)
|
||||
|
||||
result = await run_authenticated_test(
|
||||
url=req.url,
|
||||
username=req.username,
|
||||
password=req.password,
|
||||
username_selector=req.username_selector,
|
||||
password_selector=req.password_selector,
|
||||
submit_selector=req.submit_selector,
|
||||
)
|
||||
|
||||
checks = {
|
||||
"cancel_subscription": AuthCheckInfo(
|
||||
found=result.cancel_subscription.found,
|
||||
text=result.cancel_subscription.text,
|
||||
legal_ref=LEGAL_REFS["cancel_subscription"],
|
||||
),
|
||||
"delete_account": AuthCheckInfo(
|
||||
found=result.delete_account.found,
|
||||
text=result.delete_account.text,
|
||||
legal_ref=LEGAL_REFS["delete_account"],
|
||||
),
|
||||
"export_data": AuthCheckInfo(
|
||||
found=result.export_data.found,
|
||||
text=result.export_data.text,
|
||||
legal_ref=LEGAL_REFS["export_data"],
|
||||
),
|
||||
"consent_settings": AuthCheckInfo(
|
||||
found=result.consent_settings.found,
|
||||
text=result.consent_settings.text,
|
||||
legal_ref=LEGAL_REFS["consent_settings"],
|
||||
),
|
||||
"profile_visible": AuthCheckInfo(
|
||||
found=result.profile_visible.found,
|
||||
text=result.profile_visible.text,
|
||||
legal_ref=LEGAL_REFS["profile_visible"],
|
||||
),
|
||||
}
|
||||
|
||||
missing = sum(1 for c in checks.values() if not c.found)
|
||||
|
||||
return AuthScanResponse(
|
||||
url=req.url,
|
||||
authenticated=result.authenticated,
|
||||
login_error=result.login_error,
|
||||
checks=checks,
|
||||
findings_count=missing,
|
||||
scanned_at=datetime.now(timezone.utc).isoformat(),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user