Cookie: Secure only over HTTPS (works on LAN HTTP); healthcheck 127.0.0.1

This commit is contained in:
jtricerolph 2026-07-01 14:42:28 +00:00
parent e194e736d0
commit b7589b702a
2 changed files with 9 additions and 5 deletions

View file

@ -15,7 +15,7 @@ services:
ports: ports:
- "3001:3001" - "3001:3001"
healthcheck: healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:3001/health || exit 1"] test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:3001/health || exit 1"]
interval: 10s interval: 10s
retries: 5 retries: 5
start_period: 20s start_period: 20s

View file

@ -6,10 +6,14 @@ const DOMAIN = process.env.DOMAIN || 'localhost'
const SESSION_DAYS = parseInt(process.env.SESSION_DAYS || '30') const SESSION_DAYS = parseInt(process.env.SESSION_DAYS || '30')
const COOKIE_MAX_AGE = SESSION_DAYS * 24 * 60 * 60 const COOKIE_MAX_AGE = SESSION_DAYS * 24 * 60 * 60
function cookieOpts(clear = false) { function cookieOpts(request, clear = false) {
// Mark the cookie Secure only when the request actually arrived over HTTPS
// (via NPM's X-Forwarded-Proto). Over plain HTTP on the LAN, a Secure cookie
// is silently dropped by the browser — so adapt to the real scheme.
const proto = request?.headers?.['x-forwarded-proto'] || request?.protocol
return { return {
httpOnly: true, httpOnly: true,
secure: process.env.NODE_ENV !== 'development', secure: proto === 'https',
sameSite: 'lax', sameSite: 'lax',
domain: DOMAIN === 'localhost' ? undefined : `.${DOMAIN}`, domain: DOMAIN === 'localhost' ? undefined : `.${DOMAIN}`,
path: '/', path: '/',
@ -61,13 +65,13 @@ export async function authRoutes(app) {
apps: full.apps.map(a => a.slug), apps: full.apps.map(a => a.slug),
}) })
reply.setCookie('hnf_session', token, cookieOpts()) reply.setCookie('hnf_session', token, cookieOpts(request))
return full return full
}) })
// POST /api/auth/logout // POST /api/auth/logout
app.post('/logout', async (request, reply) => { app.post('/logout', async (request, reply) => {
reply.clearCookie('hnf_session', cookieOpts(true)) reply.clearCookie('hnf_session', cookieOpts(request, true))
return { ok: true } return { ok: true }
}) })