diff --git a/Docker/compose.debug.yml b/Docker/compose.debug.yml index 84c9eb2..aa4f52b 100644 --- a/Docker/compose.debug.yml +++ b/Docker/compose.debug.yml @@ -61,6 +61,9 @@ services: BANGUI_LOG_LEVEL: "debug" BANGUI_SESSION_SECRET: "${BANGUI_SESSION_SECRET:-dev-secret-do-not-use-in-production}" BANGUI_TIMEZONE: "${BANGUI_TIMEZONE:-UTC}" + # Secure=false is intentional for local HTTP development. + # In production, Secure=true prevents session cookies over unencrypted HTTP. + BANGUI_SESSION_COOKIE_SECURE: "false" volumes: - ../backend/app:/app/app:z - ../fail2ban-master:/app/fail2ban-master:ro,z diff --git a/Docs/Backend-Development.md b/Docs/Backend-Development.md index ec2eacc..13e1ddb 100644 --- a/Docs/Backend-Development.md +++ b/Docs/Backend-Development.md @@ -506,6 +506,22 @@ class Settings(BaseSettings): model_config = {"env_prefix": "BANGUI_", "env_file": ".env"} ``` +### Session Cookie Security + +The `session_cookie_secure` configuration controls the `Secure` flag on the session cookie. This flag prevents browsers from sending the session cookie over unencrypted HTTP. + +**Default:** `true` — Production deployments are secure by default. Cookies are only sent over HTTPS. + +**Local Development:** Set `BANGUI_SESSION_COOKIE_SECURE=false` in your compose file or `.env` to allow cookies over HTTP (required for `localhost:8000`). + +```yaml +# Docker/compose.debug.yml +environment: + BANGUI_SESSION_COOKIE_SECURE: "false" # Allow HTTP during local development +``` + +**Important:** If `Secure=true` is set, browsers will reject the session cookie when the backend is served over HTTP. Ensure your nginx/reverse proxy terminates TLS and passes `X-Forwarded-Proto: https` so FastAPI knows the connection is secure. + --- ## 13. Git & Workflow diff --git a/Docs/Tasks.md b/Docs/Tasks.md index d0a3110..4cb1c52 100644 --- a/Docs/Tasks.md +++ b/Docs/Tasks.md @@ -1,37 +1,3 @@ -## TASK-004 — Frontend auth state bootstrapped from `sessionStorage`, not from the backend - -**Severity:** Medium - -### Where found -`frontend/src/providers/AuthProvider.tsx` line 64 — `useState(() => sessionStorage.getItem(IS_AUTHENTICATED_KEY) === "true")`. - -### Why this is needed -On page load, the frontend sets `isAuthenticated = true` from a cached `sessionStorage` flag without contacting the backend. If the session cookie has expired server-side (e.g., server restart, session_duration elapsed), the user briefly sees the authenticated UI before the first API call triggers a 401. This also means that a user with a revoked session (manual DB deletion) appears logged in until they navigate. - -### Goal -Validate session validity with the backend on mount so the UI state always reflects reality. - -### What to do -1. Add a `GET /api/auth/session` endpoint (or reuse `GET /api/health` with auth) that returns 200 if the session is valid, 401 otherwise. -2. In `AuthProvider`, call this endpoint on mount. While the check is in flight, show a loading spinner or skeleton. -3. On 401, clear `sessionStorage` and set `isAuthenticated = false`, then redirect to `/login`. -4. Keep the `sessionStorage` flag as an optimistic hint to avoid flicker, but always confirm with the backend. - -### Possible traps and issues -- Adds one round-trip on every page load — keep the endpoint extremely lightweight (no DB joins). -- Must handle the case where the backend is temporarily unreachable (network error) — do not log the user out in that case, only on an explicit 401. -- The loading state needs a spinner or skeleton so the UI doesn't flash between states. - -### Docs changes needed -- `Features.md` — update the authentication flow description. -- `Web-Development.md` — document the mount-time session check pattern. - -### Doc references -- [Features.md](Features.md) — authentication and session management -- [Web-Development.md](Web-Development.md) — AuthProvider pattern - ---- - ## TASK-005 — `session_cookie_secure` defaults to `false` **Severity:** Medium diff --git a/backend/app/config.py b/backend/app/config.py index c5c0f5d..7dc1b37 100644 --- a/backend/app/config.py +++ b/backend/app/config.py @@ -98,9 +98,10 @@ class Settings(BaseSettings): ), ) session_cookie_secure: bool = Field( - default=False, + default=True, description=( - "Set the session cookie Secure flag when the backend is served over HTTPS." + "Set the session cookie Secure flag when the backend is served over HTTPS. " + "Defaults to True for security. Set to False only for local development over HTTP." ), ) cors_allowed_origins: str | list[str] = Field(