65 lines
1.5 KiB
Python
65 lines
1.5 KiB
Python
"""
|
|
Security helpers (cookies, environment checks).
|
|
|
|
We use HttpOnly cookies for browser auth to avoid storing JWTs in localStorage/URLs.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from fastapi import Response
|
|
|
|
|
|
AUTH_COOKIE_NAME = "pounce_access_token"
|
|
|
|
|
|
def cookie_domain() -> str | None:
|
|
"""
|
|
Optional cookie domain override.
|
|
|
|
Use with care. Example (share across subdomains): COOKIE_DOMAIN=.pounce.ch
|
|
Leave empty in local development (localhost).
|
|
"""
|
|
value = os.getenv("COOKIE_DOMAIN", "").strip()
|
|
return value or None
|
|
|
|
|
|
def should_use_secure_cookies() -> bool:
|
|
"""
|
|
Determine whether cookies should be marked Secure.
|
|
|
|
Prefer explicit config via COOKIE_SECURE=true. Otherwise infer from SITE_URL / ENVIRONMENT.
|
|
"""
|
|
if os.getenv("COOKIE_SECURE", "").lower() == "true":
|
|
return True
|
|
|
|
site_url = os.getenv("SITE_URL", "")
|
|
if site_url.startswith("https://"):
|
|
return True
|
|
|
|
env = os.getenv("ENVIRONMENT", "").lower()
|
|
return env in {"prod", "production"}
|
|
|
|
|
|
def set_auth_cookie(response: Response, token: str, max_age_seconds: int) -> None:
|
|
response.set_cookie(
|
|
key=AUTH_COOKIE_NAME,
|
|
value=token,
|
|
httponly=True,
|
|
secure=should_use_secure_cookies(),
|
|
samesite="lax",
|
|
max_age=max_age_seconds,
|
|
path="/",
|
|
domain=cookie_domain(),
|
|
)
|
|
|
|
|
|
def clear_auth_cookie(response: Response) -> None:
|
|
response.delete_cookie(
|
|
key=AUTH_COOKIE_NAME,
|
|
path="/",
|
|
domain=cookie_domain(),
|
|
)
|
|
|
|
|