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)