feat: enhance session management by adding secure cookie handling based on HTTPS detection

This commit is contained in:
Anders Böttcher
2026-05-13 13:27:36 +02:00
parent 9dbbf814b4
commit 37e916594e
2 changed files with 14 additions and 3 deletions
+8 -1
View File
@@ -86,6 +86,13 @@ export async function POST(request: Request) {
}
clearAttempts(ip)
await createSession({ userId: user.id, username: user.username, role: user.role })
// Detect whether the client is on HTTPS (via reverse-proxy header or direct TLS).
// CasaOS and most self-hosted setups run over plain HTTP, so the cookie must
// NOT be marked Secure or the browser will silently drop it.
const proto = request.headers.get('x-forwarded-proto') ?? ''
const isHttps = proto.split(',')[0].trim() === 'https'
await createSession({ userId: user.id, username: user.username, role: user.role }, isHttps)
return NextResponse.json({ ok: true, username: user.username, role: user.role })
}
+6 -2
View File
@@ -30,7 +30,7 @@ export function getSecretKey(): Uint8Array {
}
/** Creates and stores a session JWT in an httpOnly cookie. */
export async function createSession(payload: SessionPayload): Promise<void> {
export async function createSession(payload: SessionPayload, secure?: boolean): Promise<void> {
const expiresAt = new Date(Date.now() + SESSION_DURATION_MS)
const token = await new SignJWT({ ...payload })
.setProtectedHeader({ alg: 'HS256' })
@@ -38,10 +38,14 @@ export async function createSession(payload: SessionPayload): Promise<void> {
.setExpirationTime(expiresAt)
.sign(getSecretKey())
// If the caller explicitly passes a value, honour it.
// Otherwise fall back to NODE_ENV (safe default for fully-HTTPS deploys).
const isSecure = secure !== undefined ? secure : process.env.NODE_ENV === 'production'
const cookieStore = await cookies()
cookieStore.set(SESSION_COOKIE, token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
secure: isSecure,
sameSite: 'lax',
expires: expiresAt,
path: '/',