Persistent login cookie: fix random iOS/PWA logouts

Session cookie had no maxAge, so browsers dropped it on their own
schedule and the store's default 1-day TTL expired idle sessions —
logging people out unpredictably. Set a 400-day maxAge (the browser
cap) with rolling:true so the window slides forward on each visit,
and gate Secure cookies + trust-proxy behind NODE_ENV=production so
local http dev still works. Deploy script now sets NODE_ENV too.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Your Name 2026-08-22 11:14:18 -04:00
parent 5d7bcddcd1
commit 3a7031e462
2 changed files with 34 additions and 1 deletions

View file

@ -66,13 +66,30 @@ app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(express.static("public"));
app.use(fileUpload());
// In production we sit behind an HTTPS-terminating proxy (Cloudflare/nginx) that
// forwards plain HTTP to Node, so trust its X-Forwarded-Proto header — otherwise
// Express thinks every request is HTTP and a Secure cookie would never be sent.
// Locally there's no proxy and no HTTPS, so Secure must stay off or login breaks.
const isProd = process.env.NODE_ENV === "production";
if (isProd) app.set("trust proxy", 1);
app.use(
session({
store: new SQLiteStore({ client: db, expired: { clear: true } }),
secret: SESSION_SECRET,
resave: false,
saveUninitialized: true,
cookie: { secure: false },
// Persistent login: without a maxAge this is a session cookie and iOS/PWAs
// drop it on their own schedule, logging people out at random. Browsers cap
// persistent cookies to ~400 days, so we set a long window and roll it
// forward on every request — visit within 400 days and you stay logged in.
rolling: true,
cookie: {
secure: isProd, // HTTPS-only in prod; off locally so http://localhost works
sameSite: "lax",
maxAge: 1000 * 60 * 60 * 24 * 400,
},
}),
);