Skip to content

Commit ea457f2

Browse files
committed
Fix admin session cookie Secure flag breaking localhost access
Skip the Secure flag on the session cookie when the request comes from a loopback address (localhost, 127.0.0.1, ::1). The Docker image sets NODE_ENV=production which always enabled Secure, but browsers silently drop Secure cookies on plain HTTP — breaking the admin panel for self-hosted users accessing http://localhost:3000. Fixes #129
1 parent d6c5a94 commit ea457f2

File tree

1 file changed

+6
-4
lines changed
  • frontend/src/app/api/admin/session

1 file changed

+6
-4
lines changed

frontend/src/app/api/admin/session/route.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ const NO_STORE_HEADERS = {
1212
Pragma: 'no-cache',
1313
};
1414

15-
function cookieOptions() {
15+
function cookieOptions(req: NextRequest) {
16+
const host = req.headers.get('host') ?? '';
17+
const isLoopback = /^(localhost|127\.0\.0\.1|\[::1\])(:\d+)?$/.test(host);
1618
return {
1719
httpOnly: true,
1820
sameSite: 'strict' as const,
19-
secure: process.env.NODE_ENV === 'production',
21+
secure: process.env.NODE_ENV === 'production' && !isLoopback,
2022
path: '/',
2123
maxAge: COOKIE_MAX_AGE,
2224
};
@@ -80,7 +82,7 @@ export async function POST(req: NextRequest) {
8082
}
8183
const sessionToken = createAdminSessionToken(adminKey, COOKIE_MAX_AGE);
8284
const res = NextResponse.json({ ok: true }, { headers: NO_STORE_HEADERS });
83-
res.cookies.set(COOKIE_NAME, sessionToken, cookieOptions());
85+
res.cookies.set(COOKIE_NAME, sessionToken, cookieOptions(req));
8486
return res;
8587
}
8688

@@ -91,7 +93,7 @@ export async function DELETE(req: NextRequest) {
9193
}
9294
const res = NextResponse.json({ ok: true }, { headers: NO_STORE_HEADERS });
9395
res.cookies.set(COOKIE_NAME, '', {
94-
...cookieOptions(),
96+
...cookieOptions(req),
9597
maxAge: 0,
9698
});
9799
return res;

0 commit comments

Comments
 (0)