fix(auth): remove manual session.save() — was suppressing Set-Cookie header
Login was returning 200 + correct user JSON + writing a row to the sessions table, but emitting zero Set-Cookie headers. Root cause: session.regenerate() → set fields → session.save() → res.json() Calling session.save() manually writes the store but bypasses express-session's res.end() hook, which is the only path that adds the Set-Cookie header to the response. The cookie was never sent to the browser even though the session existed server-side — hence the redirect loop. Fix: remove the manual save(). Set the session fields and call res.json() directly inside regenerate()'s callback; express-session handles store write + Set-Cookie automatically on res.end().
This commit is contained in:
parent
5de1e3dc3d
commit
e71c330bdd
1 changed files with 11 additions and 16 deletions
|
|
@ -127,10 +127,11 @@ router.post('/login', async (req, res, next) => {
|
||||||
// Successful login — clear any accumulated failed attempts
|
// Successful login — clear any accumulated failed attempts
|
||||||
clearAttempts(req, username);
|
clearAttempts(req, username);
|
||||||
|
|
||||||
// Regenerate session ID to prevent fixation attacks.
|
// Regenerate session ID to prevent fixation attacks, then let
|
||||||
// Explicit save() + log on success/failure so a broken session store
|
// express-session write Set-Cookie on its own res.end() hook.
|
||||||
// (missing table, PG read-only, etc.) doesn't silently 200 with no
|
// Do NOT call session.save() manually — that writes the store but
|
||||||
// persisted session — the symptom that caused the redirect loop.
|
// bypasses the middleware's header-writing path, which is why the
|
||||||
|
// Set-Cookie header was missing even though the session row existed.
|
||||||
req.session.regenerate((err) => {
|
req.session.regenerate((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error('[auth] session.regenerate failed:', err);
|
console.error('[auth] session.regenerate failed:', err);
|
||||||
|
|
@ -139,18 +140,12 @@ router.post('/login', async (req, res, next) => {
|
||||||
req.session.userId = user.id;
|
req.session.userId = user.id;
|
||||||
req.session.username = user.username;
|
req.session.username = user.username;
|
||||||
req.session.role = user.role;
|
req.session.role = user.role;
|
||||||
req.session.save((saveErr) => {
|
console.log(`[auth] login ok user=${user.username} sid=${req.sessionID?.slice(0,8) || '?'} secure=${req.secure} proto=${req.protocol}`);
|
||||||
if (saveErr) {
|
res.json({
|
||||||
console.error('[auth] session.save failed:', saveErr);
|
id: user.id,
|
||||||
return next(saveErr);
|
username: user.username,
|
||||||
}
|
display_name: user.display_name,
|
||||||
console.log(`[auth] login ok user=${user.username} sid=${req.sessionID?.slice(0,8) || '?'} secure=${req.secure} proto=${req.protocol}`);
|
role: user.role,
|
||||||
res.json({
|
|
||||||
id: user.id,
|
|
||||||
username: user.username,
|
|
||||||
display_name: user.display_name,
|
|
||||||
role: user.role,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue