Sage100-vps/security/cookies.py
2026-01-02 17:56:28 +03:00

157 lines
5 KiB
Python

from fastapi import Response, Request
from typing import Optional
import logging
from config.config import settings
logger = logging.getLogger(__name__)
class CookieManager:
@staticmethod
def _get_samesite_value() -> str:
value = settings.cookie_samesite.lower()
if value in ("strict", "lax", "none"):
return value
return "strict"
@staticmethod
def _should_be_secure() -> bool:
if settings.is_development and not settings.cookie_secure:
return False
return True
@classmethod
def set_access_token(
cls, response: Response, token: str, max_age: Optional[int] = None
) -> None:
if max_age is None:
max_age = settings.access_token_expire_minutes * 60
response.set_cookie(
key=settings.cookie_access_token_name,
value=token,
max_age=max_age,
expires=max_age,
path="/",
domain=settings.cookie_domain,
secure=cls._should_be_secure(),
httponly=settings.cookie_httponly,
samesite=cls._get_samesite_value(),
)
logger.debug("Cookie access_token defini")
@classmethod
def set_refresh_token(
cls, response: Response, token: str, max_age: Optional[int] = None
) -> None:
if max_age is None:
max_age = settings.refresh_token_expire_days * 24 * 60 * 60
response.set_cookie(
key=settings.cookie_refresh_token_name,
value=token,
max_age=max_age,
expires=max_age,
path="/auth",
domain=settings.cookie_domain,
secure=cls._should_be_secure(),
httponly=settings.cookie_httponly,
samesite=cls._get_samesite_value(),
)
logger.debug("Cookie refresh_token defini")
@classmethod
def set_csrf_token(
cls, response: Response, token: str, max_age: Optional[int] = None
) -> None:
if max_age is None:
max_age = settings.csrf_token_expire_minutes * 60
response.set_cookie(
key=settings.cookie_csrf_token_name,
value=token,
max_age=max_age,
expires=max_age,
path="/",
domain=settings.cookie_domain,
secure=cls._should_be_secure(),
httponly=False,
samesite=cls._get_samesite_value(),
)
logger.debug("Cookie csrf_token defini")
@classmethod
def clear_access_token(cls, response: Response) -> None:
response.delete_cookie(
key=settings.cookie_access_token_name,
path="/",
domain=settings.cookie_domain,
secure=cls._should_be_secure(),
httponly=settings.cookie_httponly,
samesite=cls._get_samesite_value(),
)
logger.debug("Cookie access_token supprime")
@classmethod
def clear_refresh_token(cls, response: Response) -> None:
response.delete_cookie(
key=settings.cookie_refresh_token_name,
path="/auth",
domain=settings.cookie_domain,
secure=cls._should_be_secure(),
httponly=settings.cookie_httponly,
samesite=cls._get_samesite_value(),
)
logger.debug("Cookie refresh_token supprime")
@classmethod
def clear_csrf_token(cls, response: Response) -> None:
response.delete_cookie(
key=settings.cookie_csrf_token_name,
path="/",
domain=settings.cookie_domain,
secure=cls._should_be_secure(),
httponly=False,
samesite=cls._get_samesite_value(),
)
logger.debug("Cookie csrf_token supprime")
@classmethod
def clear_all_auth_cookies(cls, response: Response) -> None:
cls.clear_access_token(response)
cls.clear_refresh_token(response)
cls.clear_csrf_token(response)
logger.debug("Tous les cookies auth supprimes")
@classmethod
def get_access_token(cls, request: Request) -> Optional[str]:
token = request.cookies.get(settings.cookie_access_token_name)
if token:
return token
auth_header = request.headers.get("Authorization")
if auth_header and auth_header.startswith("Bearer "):
return auth_header[7:]
return None
@classmethod
def get_refresh_token(cls, request: Request) -> Optional[str]:
return request.cookies.get(settings.cookie_refresh_token_name)
@classmethod
def get_csrf_token(cls, request: Request) -> Optional[str]:
csrf_header = request.headers.get("X-CSRF-Token")
if csrf_header:
return csrf_header
return request.cookies.get(settings.cookie_csrf_token_name)
def set_auth_cookies(
response: Response, access_token: str, refresh_token: str, csrf_token: str
) -> None:
CookieManager.set_access_token(response, access_token)
CookieManager.set_refresh_token(response, refresh_token)
CookieManager.set_csrf_token(response, csrf_token)