Skip to content

fix(auth): keep sessions across reloads on plain-HTTP deployments (COOKIE_SECURE)#19

Merged
dsbaars merged 1 commit into
mainfrom
fix/cookie-secure-plain-http
Jun 24, 2026
Merged

fix(auth): keep sessions across reloads on plain-HTTP deployments (COOKIE_SECURE)#19
dsbaars merged 1 commit into
mainfrom
fix/cookie-secure-plain-http

Conversation

@dsbaars

@dsbaars dsbaars commented Jun 24, 2026

Copy link
Copy Markdown
Owner

Problem

The refresh-token cookie is marked Secure whenever NODE_ENV=production. A Secure cookie is silently dropped by the browser when the app is served over plain HTTP on a non-localhost host (e.g. http://mini7:8080). The access token is kept in memory so the app works while navigating, but a full page reload — which can only restore the session by exchanging the refresh cookie at /api/auth/refresh — finds no cookie and bounces the user to /login. So on such deployments every reload logs the user out.

Fix

Introduce a COOKIE_SECURE override, secure-by-default:

  • unset → falls back to NODE_ENV === 'production' (HTTPS deployments unchanged);
  • COOKIE_SECURE=true / false → explicit.

Operators serving over plain HTTP on a trusted network (e.g. a LAN-only http://host:port) set COOKIE_SECURE=false. Serving over HTTPS remains the recommended setup.

Changes

  • isCookieSecure() in auth.controller.ts, used by the shared refresh-cookie attributes (set + clear stay in sync).
  • 2 unit tests asserting the Secure flag follows COOKIE_SECURE.
  • Wired through docker-compose.yml and documented in .env.example.

Verification

Server build 0 issues, auth controller suite 32 tests pass, format:check clean. The existing refresh-cookie e2e (httpOnly + SameSite=Lax) is unaffected (it asserts no secure flag).

Split out of #18 so it can be merged ahead of the permissions work.

…E_SECURE

The refresh cookie was marked Secure whenever NODE_ENV=production. A Secure cookie
is silently dropped by the browser when the app is served over plain HTTP on a
non-localhost host (e.g. http://mini7:8080), so the in-memory access token worked
while navigating but every full page reload — which can only restore the session by
exchanging the refresh cookie at /api/auth/refresh — found no cookie and bounced the
user to /login.

Add a COOKIE_SECURE override (secure-by-default: unset falls back to
NODE_ENV==='production'). Operators serving over plain HTTP on a trusted network set
COOKIE_SECURE=false; HTTPS deployments are unaffected. Documented in .env.example and
wired through docker-compose.yml.
@dsbaars dsbaars merged commit 1635cb8 into main Jun 24, 2026
4 checks passed
@dsbaars dsbaars deleted the fix/cookie-secure-plain-http branch June 24, 2026 22:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant