diff --git a/docker-compose.yml b/docker-compose.yml index de97f1f..15cb2d6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,7 +15,7 @@ services: ports: - "3001:3001" 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 retries: 5 start_period: 20s diff --git a/src/routes/auth.js b/src/routes/auth.js index 7b6ff81..a8cd665 100644 --- a/src/routes/auth.js +++ b/src/routes/auth.js @@ -6,10 +6,14 @@ const DOMAIN = process.env.DOMAIN || 'localhost' const SESSION_DAYS = parseInt(process.env.SESSION_DAYS || '30') 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 { httpOnly: true, - secure: process.env.NODE_ENV !== 'development', + secure: proto === 'https', sameSite: 'lax', domain: DOMAIN === 'localhost' ? undefined : `.${DOMAIN}`, path: '/', @@ -61,13 +65,13 @@ export async function authRoutes(app) { apps: full.apps.map(a => a.slug), }) - reply.setCookie('hnf_session', token, cookieOpts()) + reply.setCookie('hnf_session', token, cookieOpts(request)) return full }) // POST /api/auth/logout app.post('/logout', async (request, reply) => { - reply.clearCookie('hnf_session', cookieOpts(true)) + reply.clearCookie('hnf_session', cookieOpts(request, true)) return { ok: true } })