diff --git a/backend/app/routers/oidc.py b/backend/app/routers/oidc.py index 4b1432e..5130b8c 100644 --- a/backend/app/routers/oidc.py +++ b/backend/app/routers/oidc.py @@ -115,10 +115,15 @@ def _beginne(db: Session, request: Request, provider: str, weiter: str | None, link_user: User | None) -> RedirectResponse: p = _hole_provider(provider) ziel = _redirect_uri(request, p.name) + zurueck = _sicheres_ziel(weiter) if link_user is None else _sicheres_ziel(weiter or "/konto") try: begonnen = oidc_service.start(p, ziel) except oidc_service.OidcFehler as e: - raise HTTPException(status_code=status.HTTP_502_BAD_GATEWAY, detail=str(e)) from e + # Hier steht ein BROWSER, der einem Link gefolgt ist – keine Antwort auf + # fetch(). Eine Fehlerantwort waere eine Seite mit rohem JSON. Also + # zurueck in die Oberflaeche, mit dem Grund in der Adresse, genau wie + # bei der Rueckkehr vom Anbieter. + return _fehlerseite(zurueck if link_user is not None else "/login", str(e)) # Abgelaufene Versuche wegraeumen – sonst waechst die Tabelle still. db.query(OidcState).filter(OidcState.expires_at < _now()).delete() diff --git a/backend/tests/test_oidc.py b/backend/tests/test_oidc.py index d51111b..eb063b0 100644 --- a/backend/tests/test_oidc.py +++ b/backend/tests/test_oidc.py @@ -465,3 +465,21 @@ def test_ohne_einstellung_kommt_die_adresse_aus_der_anfrage(client, anbieter): r = client.get("/api/auth/oidc/authentik/start", follow_redirects=False) frage = parse_qs(urlparse(r.headers["location"]).query) assert frage["redirect_uri"][0].endswith("/api/auth/oidc/authentik/callback") + + +def test_unerreichbarer_anbieter_zeigt_keine_json_seite(client, anbieter, monkeypatch): + """Hier steht ein Browser, der einem Link gefolgt ist. Eine Fehlerantwort + waere eine Seite mit rohem JSON – der Grund gehoert in die Oberflaeche.""" + from app.services import oidc as oidc_service + + def kaputt(*a, **kw): + raise oidc_service.OidcFehler("Der Anmeldedienst ist nicht erreichbar: " + "[Errno -2] Name or service not known") + + monkeypatch.setattr("app.services.oidc.start", kaputt) + r = client.get("/api/auth/oidc/authentik/start", follow_redirects=False) + assert r.status_code == 303, r.text + ziel = r.headers["location"] + assert ziel.startswith("/login"), ziel + assert "oidc_error" in ziel + assert "Name+or+service" in ziel or "Name%20or%20service" in ziel