← back to NationalPaperHangers
auth: regenerate session on OAuth sign-in (fixation defense — match claim.js)
f240b01e8c3c1cd91a5480ef4a9b87bfad84ce8b · 2026-05-06 11:11:42 -0700 · Steve
Files touched
M routes/auth-google.jsM routes/auth-linkedin.js
Diff
commit f240b01e8c3c1cd91a5480ef4a9b87bfad84ce8b
Author: Steve <steve@designerwallcoverings.com>
Date: Wed May 6 11:11:42 2026 -0700
auth: regenerate session on OAuth sign-in (fixation defense — match claim.js)
---
routes/auth-google.js | 12 +++++++++++-
routes/auth-linkedin.js | 9 ++++++++-
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/routes/auth-google.js b/routes/auth-google.js
index 64f2c5b..845f345 100644
--- a/routes/auth-google.js
+++ b/routes/auth-google.js
@@ -18,6 +18,15 @@ const db = require('../lib/db');
const router = express.Router();
+// Match the installer-auth pattern in claim.js — regenerate session on sign-in
+// so a hijacked pre-auth session ID can't ride through to the authenticated
+// identity (session-fixation defense).
+function regenerateSession(req) {
+ return new Promise((resolve, reject) => {
+ req.session.regenerate(err => err ? reject(err) : resolve());
+ });
+}
+
const CLIENT_ID = process.env.NPH_GOOGLE_OAUTH_CLIENT_ID || '';
const CLIENT_SECRET = process.env.NPH_GOOGLE_OAUTH_CLIENT_SECRET || '';
const SCOPE = 'openid email profile';
@@ -165,9 +174,10 @@ router.get('/auth/google/callback', async (req, res, next) => {
);
id = ins.id;
}
+ // Regenerate before assigning the authenticated identity (session fixation).
+ await regenerateSession(req);
req.session.consumerAccountId = id;
req.session.consumer = { id, email: profile.email, name: profile.name || null, picture_url: profile.picture || null };
- req.session.gOAuth = null;
res.redirect(sessionNext);
} catch (err) { next(err); }
});
diff --git a/routes/auth-linkedin.js b/routes/auth-linkedin.js
index 96ca322..9a3f2f4 100644
--- a/routes/auth-linkedin.js
+++ b/routes/auth-linkedin.js
@@ -22,6 +22,13 @@ const db = require('../lib/db');
const router = express.Router();
+// Session-fixation defense — match claim.js + auth-google.js pattern.
+function regenerateSession(req) {
+ return new Promise((resolve, reject) => {
+ req.session.regenerate(err => err ? reject(err) : resolve());
+ });
+}
+
const CLIENT_ID = process.env.LINKEDIN_CLIENT_ID || '';
const CLIENT_SECRET = process.env.LINKEDIN_CLIENT_SECRET || '';
const SCOPE = 'openid profile email';
@@ -164,9 +171,9 @@ router.get('/auth/linkedin/callback', async (req, res, next) => {
);
id = ins.id;
}
+ await regenerateSession(req);
req.session.consumerAccountId = id;
req.session.consumer = { id, email: profile.email, name: profile.name || null, picture_url: profile.picture || null, provider: 'linkedin' };
- req.session.liOAuth = null;
res.redirect(sessionNext);
} catch (err) { next(err); }
});
← f65e1d4 fix(public/installer): coerce market_segments/materials elem
·
back to NationalPaperHangers
·
watch the work: YT + IG reels + TikTok embeds via partial ac a9f49d0 →