Spaces:
Sleeping
Sleeping
| """Dependencias de autorizaci贸n y CSRF para FastAPI. | |
| Cierra el agujero cr铆tico de la versi贸n PHP: /api/interpret y /api/papers estaban | |
| abiertos. Aqu铆 requieren sesi贸n v谩lida. Las peticiones mutantes exigen doble-token CSRF. | |
| """ | |
| from __future__ import annotations | |
| import hmac | |
| from fastapi import Cookie, Header, HTTPException, Request, status | |
| from .session import CABECERA_CSRF, COOKIE_CSRF, COOKIE_SESION, leer_sesion | |
| def usuario_actual(request: Request) -> dict: | |
| """Devuelve la sesi贸n o 401. Usar como dependencia en rutas protegidas.""" | |
| token = request.cookies.get(COOKIE_SESION) | |
| sesion = leer_sesion(token) | |
| if not sesion or not sesion.get("email"): | |
| raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="No autenticado.") | |
| return sesion | |
| def verificar_csrf( | |
| request: Request, | |
| x_csrf_token: str | None = Header(default=None, alias=CABECERA_CSRF), | |
| morphos_csrf: str | None = Cookie(default=None, alias=COOKIE_CSRF), | |
| ) -> None: | |
| """Double-submit cookie: la cabecera debe coincidir con la cookie CSRF.""" | |
| if request.method in ("GET", "HEAD", "OPTIONS"): | |
| return | |
| # Comparaci贸n en tiempo constante: el token es un secreto de sesi贸n, as铆 que se compara con | |
| # compare_digest por costumbre defensiva (no con `!=`, que corta en el primer byte distinto). | |
| if not x_csrf_token or not morphos_csrf or not hmac.compare_digest(x_csrf_token, morphos_csrf): | |
| raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="CSRF inv谩lido.") | |