fix: stille Anmeldeschleife bei Secure-Cookie über HTTP erklären
Bei COOKIE_SECURE=true und Zugriff über HTTP verwirft der Browser das Sitzungs-Cookie. Die Anmeldung selbst meldet Erfolg, die nächste Anfrage gilt aber als nicht angemeldet – der Nutzer landet ohne jede Meldung wieder auf der Anmeldemaske und hält es für ein falsches Passwort. - Das Frontend prüft die Sitzung unmittelbar nach der Anmeldung und nennt bei einem Fehlschlag die Ursache samt beider Auswege - Das Backend protokolliert dieselbe Kombination als Warnung und wertet dabei X-Forwarded-Proto aus, weil hinter einem Reverse Proxy immer http ankommt - docs/deployment.md beschreibt das Symptom wörtlich Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014e7t8UpmoVNMtWivY5LiSH
This commit is contained in:
co-authored by
Claude Opus 5
parent
c110340628
commit
998d5867df
@@ -1,11 +1,14 @@
|
||||
"""Setzen und Löschen der Authentifizierungs-Cookies."""
|
||||
|
||||
import logging
|
||||
from datetime import UTC, datetime
|
||||
|
||||
from fastapi import Response
|
||||
from fastapi import Request, Response
|
||||
|
||||
from app.core.config import settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
ACCESS_COOKIE = "moneyfy_access"
|
||||
REFRESH_COOKIE = "moneyfy_refresh"
|
||||
|
||||
@@ -13,6 +16,38 @@ REFRESH_COOKIE = "moneyfy_refresh"
|
||||
REFRESH_COOKIE_PATH = "/api/auth"
|
||||
|
||||
|
||||
def request_is_secure(request: Request) -> bool:
|
||||
"""Kam die Anfrage über HTTPS?
|
||||
|
||||
Hinter einem Reverse Proxy steht das echte Schema in `X-Forwarded-Proto`;
|
||||
das Schema der Verbindung zum Container ist dort immer `http`.
|
||||
"""
|
||||
weitergeleitet = request.headers.get("x-forwarded-proto", "")
|
||||
if weitergeleitet:
|
||||
# Bei mehreren Proxies steht das ursprüngliche Schema vorne.
|
||||
return weitergeleitet.split(",")[0].strip().lower() == "https"
|
||||
return request.url.scheme == "https"
|
||||
|
||||
|
||||
def warn_if_cookie_unusable(request: Request) -> bool:
|
||||
"""Meldet die Kombination, bei der der Browser das Cookie verwirft.
|
||||
|
||||
`Secure`-Cookies über eine reine HTTP-Verbindung werden stillschweigend
|
||||
weggeworfen: Die Anmeldung meldet Erfolg, die nächste Anfrage gilt aber
|
||||
wieder als nicht angemeldet. Ohne diesen Hinweis ist das kaum zu erkennen.
|
||||
"""
|
||||
if not settings.cookie_secure or request_is_secure(request):
|
||||
return False
|
||||
|
||||
logger.warning(
|
||||
"Anmeldung über %s ohne HTTPS bei COOKIE_SECURE=true – der Browser "
|
||||
"verwirft das Sitzungs-Cookie und die Anmeldemaske erscheint erneut. "
|
||||
"Entweder über HTTPS zugreifen oder COOKIE_SECURE=false setzen.",
|
||||
request.url.hostname or "unbekannt",
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
def set_auth_cookies(
|
||||
response: Response,
|
||||
access_token: str,
|
||||
|
||||
Reference in New Issue
Block a user