Add ALLOW_INSECURE_COOKIES env flag for HTTP access in production
Browsers drop Secure cookies on plain-http origins, so logging into the admin over a LAN/VPN IP (e.g. during server migration, before TLS is in front) silently failed every authenticated request. Setting ALLOW_INSECURE_COOKIES=true omits the Secure flag; default behavior in production is unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
import { createHash, randomUUID, timingSafeEqual, createHmac, randomFillSync } from 'node:crypto'
|
import { createHash, randomUUID, timingSafeEqual, createHmac, randomFillSync } from 'node:crypto'
|
||||||
import { readFile, writeFile } from 'node:fs/promises'
|
import { readFile, writeFile } from 'node:fs/promises'
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import { parseCookies } from './helpers.js'
|
import { parseCookies, cookieSecureFlag } from './helpers.js'
|
||||||
import { DATA_DIR } from './paths.js'
|
import { DATA_DIR } from './paths.js'
|
||||||
|
|
||||||
const TOTP_SECRET_FILE = path.join(DATA_DIR, 'totp-secret.json')
|
const TOTP_SECRET_FILE = path.join(DATA_DIR, 'totp-secret.json')
|
||||||
@@ -18,7 +18,7 @@ const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD
|
|||||||
const adminSessions = new Map()
|
const adminSessions = new Map()
|
||||||
|
|
||||||
function cookieFlags() {
|
function cookieFlags() {
|
||||||
return process.env.NODE_ENV === 'production' ? '; Secure' : ''
|
return cookieSecureFlag()
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sha256(value) {
|
export function sha256(value) {
|
||||||
|
|||||||
+10
-2
@@ -505,10 +505,18 @@ export function hasVisitorConsent(req) {
|
|||||||
return cookies['vbn_analytics_consent'] === 'yes'
|
return cookies['vbn_analytics_consent'] === 'yes'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Secure cookies are required in production unless explicitly disabled with
|
||||||
|
// ALLOW_INSECURE_COOKIES=true — needed when the app is reached over plain
|
||||||
|
// HTTP (e.g. by LAN/VPN IP during a server migration, before TLS is set up),
|
||||||
|
// because browsers silently drop Secure cookies on http:// origins.
|
||||||
|
export function cookieSecureFlag() {
|
||||||
|
if (process.env.ALLOW_INSECURE_COOKIES === 'true') return ''
|
||||||
|
return process.env.NODE_ENV === 'production' ? '; Secure' : ''
|
||||||
|
}
|
||||||
|
|
||||||
export function setConsentCookie(res, consent) {
|
export function setConsentCookie(res, consent) {
|
||||||
const value = consent ? 'yes' : 'no'
|
const value = consent ? 'yes' : 'no'
|
||||||
const secureFlag = process.env.NODE_ENV === 'production' ? '; Secure' : ''
|
res.append('Set-Cookie', `vbn_analytics_consent=${value}; Max-Age=31536000; Path=/; SameSite=Lax${cookieSecureFlag()}`)
|
||||||
res.append('Set-Cookie', `vbn_analytics_consent=${value}; Max-Age=31536000; Path=/; SameSite=Lax${secureFlag}`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isPrivateOrLocalIp(ip) {
|
export function isPrivateOrLocalIp(ip) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { createHash, randomUUID } from 'node:crypto'
|
import { createHash, randomUUID } from 'node:crypto'
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import { parseCookies } from './helpers.js'
|
import { parseCookies, cookieSecureFlag } from './helpers.js'
|
||||||
import {
|
import {
|
||||||
STUDY_SESSION_COOKIE,
|
STUDY_SESSION_COOKIE,
|
||||||
STUDY_SESSION_TTL_MS,
|
STUDY_SESSION_TTL_MS,
|
||||||
@@ -131,7 +131,7 @@ export function getStudyAvatarUrl(subject) {
|
|||||||
// ── Session management ─────────────────────────────────────────────────────
|
// ── Session management ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
export function cookieFlags() {
|
export function cookieFlags() {
|
||||||
return process.env.NODE_ENV === 'production' ? '; Secure' : ''
|
return cookieSecureFlag()
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createStudySession(userId) {
|
export function createStudySession(userId) {
|
||||||
|
|||||||
Reference in New Issue
Block a user