From b05f30e2f9ed4fc25365d6ef824b686902a77b75 Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Tue, 23 Jun 2026 12:49:04 +0530 Subject: [PATCH] fix(backend):add session database settings --- surfsense_backend/app/config/__init__.py | 29 +++++++++++++++++++++++- surfsense_backend/app/db.py | 7 +++--- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/surfsense_backend/app/config/__init__.py b/surfsense_backend/app/config/__init__.py index 3d8dc2aaf..5d9bca130 100644 --- a/surfsense_backend/app/config/__init__.py +++ b/surfsense_backend/app/config/__init__.py @@ -768,6 +768,8 @@ class Config: # Google OAuth GOOGLE_OAUTH_CLIENT_ID = os.getenv("GOOGLE_OAUTH_CLIENT_ID") GOOGLE_OAUTH_CLIENT_SECRET = os.getenv("GOOGLE_OAUTH_CLIENT_SECRET") + GOOGLE_DESKTOP_CLIENT_ID = os.getenv("GOOGLE_DESKTOP_CLIENT_ID") + GOOGLE_DESKTOP_CLIENT_SECRET = os.getenv("GOOGLE_DESKTOP_CLIENT_SECRET") GOOGLE_PICKER_API_KEY = os.getenv("GOOGLE_PICKER_API_KEY") # Google Calendar redirect URI @@ -914,11 +916,36 @@ class Config: # JWT Token Lifetimes ACCESS_TOKEN_LIFETIME_SECONDS = int( - os.getenv("ACCESS_TOKEN_LIFETIME_SECONDS", str(24 * 60 * 60)) # 1 day + os.getenv("ACCESS_TOKEN_LIFETIME_SECONDS", str(30 * 60)) # 30 minutes ) REFRESH_TOKEN_LIFETIME_SECONDS = int( os.getenv("REFRESH_TOKEN_LIFETIME_SECONDS", str(14 * 24 * 60 * 60)) # 2 weeks ) + REFRESH_ROTATION_GRACE_SECONDS = int( + os.getenv("REFRESH_ROTATION_GRACE_SECONDS", "45") + ) + REFRESH_ABSOLUTE_LIFETIME_SECONDS = int( + os.getenv("REFRESH_ABSOLUTE_LIFETIME_SECONDS", str(30 * 24 * 60 * 60)) + ) + if REFRESH_ABSOLUTE_LIFETIME_SECONDS <= REFRESH_TOKEN_LIFETIME_SECONDS: + raise ValueError( + "REFRESH_ABSOLUTE_LIFETIME_SECONDS must be greater than " + "REFRESH_TOKEN_LIFETIME_SECONDS so the sliding inactivity window works." + ) + SESSION_COOKIE_NAME = os.getenv("SESSION_COOKIE_NAME", "surfsense_session") + REFRESH_COOKIE_NAME = os.getenv("REFRESH_COOKIE_NAME", "surfsense_refresh") + SESSION_COOKIE_SECURE_POLICY = os.getenv( + "SESSION_COOKIE_SECURE_POLICY", "auto" + ).lower() + SESSION_COOKIE_SAMESITE = os.getenv("SESSION_COOKIE_SAMESITE", "lax").lower() + if SESSION_COOKIE_SAMESITE == "none": + raise ValueError("SESSION_COOKIE_SAMESITE=none is not supported") + COOKIE_DOMAIN = os.getenv("COOKIE_DOMAIN") or None + CSRF_ALLOWED_ORIGINS = [ + origin.strip() + for origin in os.getenv("CSRF_ALLOWED_ORIGINS", "").split(",") + if origin.strip() + ] _PAT_MAX_EXPIRY_DAYS = os.getenv("PAT_MAX_EXPIRY_DAYS", "").strip() PAT_MAX_EXPIRY_DAYS = ( int(_PAT_MAX_EXPIRY_DAYS) if _PAT_MAX_EXPIRY_DAYS else None diff --git a/surfsense_backend/app/db.py b/surfsense_backend/app/db.py index 5cc3cea5d..3918c993c 100644 --- a/surfsense_backend/app/db.py +++ b/surfsense_backend/app/db.py @@ -2719,9 +2719,10 @@ class RefreshToken(Base, TimestampMixin): index=True, ) user = relationship("User", back_populates="refresh_tokens") - token_hash = Column(String(256), unique=True, nullable=False, index=True) + token_hash = Column(String(64), unique=True, nullable=False, index=True) expires_at = Column(TIMESTAMP(timezone=True), nullable=False, index=True) - is_revoked = Column(Boolean, default=False, nullable=False) + revoked_at = Column(TIMESTAMP(timezone=True), nullable=True) + absolute_expiry = Column(TIMESTAMP(timezone=True), nullable=True) family_id = Column(UUID(as_uuid=True), nullable=False, index=True) @property @@ -2730,7 +2731,7 @@ class RefreshToken(Base, TimestampMixin): @property def is_valid(self) -> bool: - return not self.is_expired and not self.is_revoked + return not self.is_expired and self.revoked_at is None class PersonalAccessToken(BaseModel, TimestampMixin):