clouduse / auth.py
Jerry20062016's picture
Make session lifetime configurable
c2005b7
import os
from datetime import datetime, timedelta, timezone
from itsdangerous import URLSafeTimedSerializer, BadSignature, SignatureExpired
from fastapi import Request, Response
from db import get_user_by_id
SECRET_KEY = os.environ.get("SECRET_KEY", "dev-secret-key-change-in-production")
COOKIE_NAME = "session"
DEFAULT_SESSION_MAX_AGE_DAYS = 7
SECONDS_PER_DAY = 24 * 3600
def session_max_age_seconds() -> int:
raw_days = os.environ.get("SESSION_MAX_AGE_DAYS", "").strip()
if not raw_days:
return DEFAULT_SESSION_MAX_AGE_DAYS * SECONDS_PER_DAY
try:
days = int(raw_days)
except ValueError:
return DEFAULT_SESSION_MAX_AGE_DAYS * SECONDS_PER_DAY
if days < 1:
return DEFAULT_SESSION_MAX_AGE_DAYS * SECONDS_PER_DAY
return days * SECONDS_PER_DAY
MAX_AGE = session_max_age_seconds()
_serializer = URLSafeTimedSerializer(SECRET_KEY)
def create_session_token(user_id: int) -> str:
return _serializer.dumps({"user_id": user_id})
def verify_session_token(token: str) -> int | None:
try:
data = _serializer.loads(token, max_age=MAX_AGE)
return data.get("user_id")
except (BadSignature, SignatureExpired):
return None
def set_session_cookie(response: Response, user_id: int):
token = create_session_token(user_id)
response.set_cookie(
COOKIE_NAME,
token,
max_age=MAX_AGE,
httponly=True,
samesite="lax",
secure=os.environ.get("SECURE_COOKIES", "false").lower() == "true",
)
def clear_session_cookie(response: Response):
response.delete_cookie(COOKIE_NAME)
def get_current_user(request: Request) -> dict | None:
token = request.cookies.get(COOKIE_NAME)
return get_current_user_from_token(token)
def get_current_user_from_token(token: str | None) -> dict | None:
if not token:
return None
user_id = verify_session_token(token)
if not user_id:
return None
return get_user_by_id(user_id)