feat(2-Schritt1): Additiver Ein-Klick-Login per Capability-Token
Zweiter Auth-Weg NEBEN Authelia (nichts schaltet um, kein Aussperr-Risiko): - Link https://voice.jamulix.de/?k=<token> -> Token landet im va_token-Cookie (HttpOnly, Secure, SameSite=Lax, 1 Jahr), Token wird aus der URL entfernt. - Cookie/?k= authentifiziert App-Routen (require_user) und WS (/ws/voice, /ws/chat). Token = vorhandenes Nutzer-Token (get_user_by_token). - authenticate(): fehlt der SSO-Header, wird auf Token-Auth durchgefallen (statt hartem 401) — Voraussetzung für die spätere nginx-Trennung. Authelia/Forward-Auth bleibt voll funktionsfähig (Live verifiziert: beide Wege gehen). Tests: Cookie-, ?k=- und Negativ-Pfad. 217 passed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
cc354938df
commit
47daf918ae
4 changed files with 88 additions and 10 deletions
48
tests/test_capability_login.py
Normal file
48
tests/test_capability_login.py
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
"""Schritt 1: additiver Ein-Klick-Login per Capability-Token (Cookie / ?k=)."""
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
import app.dependencies as deps
|
||||
from app.main import app
|
||||
from app.config import settings
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
|
||||
def test_capability_link_sets_cookie_and_strips_url(monkeypatch):
|
||||
monkeypatch.setattr(settings, "auth_enabled", True)
|
||||
user, token = deps.get_store().create_user("Senior")
|
||||
r = client.get(f"/?k={token}", follow_redirects=False)
|
||||
assert r.status_code == 303
|
||||
# Cookie wird gesetzt
|
||||
sc = r.headers.get("set-cookie", "")
|
||||
assert "va_token=" in sc and "HttpOnly" in sc
|
||||
# URL ist um ?k= bereinigt (Redirect-Ziel ohne k)
|
||||
assert "k=" not in r.headers.get("location", "")
|
||||
client.cookies.clear()
|
||||
|
||||
|
||||
def test_cookie_authenticates_api(monkeypatch):
|
||||
monkeypatch.setattr(settings, "auth_enabled", True)
|
||||
user, token = deps.get_store().create_user("Senior")
|
||||
client.cookies.set("va_token", token)
|
||||
me = client.get("/api/me")
|
||||
assert me.status_code == 200
|
||||
assert me.json()["user_id"] == user.id
|
||||
client.cookies.clear()
|
||||
|
||||
|
||||
def test_query_token_authenticates_api(monkeypatch):
|
||||
monkeypatch.setattr(settings, "auth_enabled", True)
|
||||
user, token = deps.get_store().create_user("Senior")
|
||||
me = client.get(f"/api/me?k={token}")
|
||||
assert me.status_code == 200
|
||||
assert me.json()["user_id"] == user.id
|
||||
|
||||
|
||||
def test_invalid_capability_link_does_not_set_cookie(monkeypatch):
|
||||
monkeypatch.setattr(settings, "auth_enabled", True)
|
||||
r = client.get("/?k=not-a-real-token", follow_redirects=False)
|
||||
# ungültiges Token -> kein Cookie, kein 303-Redirect auf bereinigte URL
|
||||
assert "va_token=" not in r.headers.get("set-cookie", "")
|
||||
client.cookies.clear()
|
||||
Loading…
Add table
Add a link
Reference in a new issue