fix(dashboard): address persistent auth review
This commit is contained in:
@@ -48,6 +48,30 @@ def _same_origin(request: Request) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def _same_origin_navigation(request: Request) -> bool:
|
||||
referer = request.headers.get("referer")
|
||||
host = request.headers.get("host")
|
||||
if not referer or not host:
|
||||
return False
|
||||
try:
|
||||
parsed = urlsplit(referer)
|
||||
authority = urlsplit(f"//{host}")
|
||||
referer_port = parsed.port or 443
|
||||
request_port = authority.port or 443
|
||||
return (
|
||||
request.url.scheme == "https"
|
||||
and parsed.scheme == "https"
|
||||
and parsed.hostname is not None
|
||||
and authority.hostname is not None
|
||||
and parsed.hostname.lower() == authority.hostname.lower()
|
||||
and referer_port == request_port
|
||||
and parsed.username is None
|
||||
and parsed.password is None
|
||||
)
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
|
||||
def _one(values: dict[str, list[str]], name: str) -> str | None:
|
||||
candidates = values.get(name)
|
||||
if candidates is None or len(candidates) != 1:
|
||||
@@ -126,6 +150,12 @@ async def logout(request: Request) -> Response:
|
||||
authentication.log_auth_event("logout_origin_rejected", correlation_id)
|
||||
return PlainTextResponse("Forbidden", status_code=403)
|
||||
response = _redirect("/")
|
||||
_delete_auth_cookie(response)
|
||||
authentication.log_auth_event("logout", correlation_id)
|
||||
return response
|
||||
|
||||
|
||||
def _delete_auth_cookie(response: Response) -> None:
|
||||
response.delete_cookie(
|
||||
authentication.AUTH_COOKIE_NAME,
|
||||
path="/",
|
||||
@@ -133,7 +163,16 @@ async def logout(request: Request) -> Response:
|
||||
httponly=True,
|
||||
samesite="lax",
|
||||
)
|
||||
authentication.log_auth_event("logout", correlation_id)
|
||||
|
||||
|
||||
async def cleanup(request: Request) -> Response:
|
||||
correlation_id = secrets.token_hex(8)
|
||||
if not _same_origin_navigation(request):
|
||||
authentication.log_auth_event("cleanup_origin_rejected", correlation_id)
|
||||
return PlainTextResponse("Forbidden", status_code=403)
|
||||
response = _redirect("/")
|
||||
_delete_auth_cookie(response)
|
||||
authentication.log_auth_event("cleanup", correlation_id)
|
||||
return response
|
||||
|
||||
|
||||
@@ -141,4 +180,5 @@ def create_auth_routes() -> list[Route]:
|
||||
return [
|
||||
Route("/api/auth/login", login, methods=["POST"]),
|
||||
Route("/api/auth/logout", logout, methods=["POST"]),
|
||||
Route("/api/auth/cleanup", cleanup, methods=["GET"]),
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user