fix(csrf): enable newsletter subscription from mobile
CRITICAL FIX: Newsletter subscription was returning "Forbidden" error because the CSRF protection was incorrectly configured. Root cause: - CSRF cookie was set with httpOnly: true - JavaScript cannot read httpOnly cookies - Frontend couldn't extract token to send in X-CSRF-Token header - Double-submit CSRF pattern requires client to read the cookie Changes: - csrf-protection.middleware.js: Set httpOnly: false (required for double-submit pattern) - blog.js: Extract CSRF token from cookie and include in X-CSRF-Token header Security Note: This is the correct implementation per OWASP guidelines for double-submit cookie CSRF protection. The cookie is still protected by SameSite: strict and domain restrictions. Fixes: #newsletter-subscription-forbidden-mobile
This commit is contained in:
parent
ca8edb383b
commit
cfc4347e9b
2 changed files with 9 additions and 2 deletions
|
|
@ -571,10 +571,17 @@ function setupNewsletterModal() {
|
||||||
submitBtn.textContent = 'Subscribing...';
|
submitBtn.textContent = 'Subscribing...';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Get CSRF token from cookie
|
||||||
|
const csrfToken = document.cookie
|
||||||
|
.split('; ')
|
||||||
|
.find(row => row.startsWith('csrf-token='))
|
||||||
|
?.split('=')[1];
|
||||||
|
|
||||||
const response = await fetch('/api/newsletter/subscribe', {
|
const response = await fetch('/api/newsletter/subscribe', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json',
|
||||||
|
'X-CSRF-Token': csrfToken || ''
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
email,
|
email,
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ function setCsrfToken(req, res, next) {
|
||||||
const isSecure = req.secure || req.headers['x-forwarded-proto'] === 'https';
|
const isSecure = req.secure || req.headers['x-forwarded-proto'] === 'https';
|
||||||
|
|
||||||
res.cookie('csrf-token', token, {
|
res.cookie('csrf-token', token, {
|
||||||
httpOnly: true,
|
httpOnly: false, // Must be false for double-submit pattern (client needs to read it)
|
||||||
secure: isSecure && process.env.NODE_ENV === 'production',
|
secure: isSecure && process.env.NODE_ENV === 'production',
|
||||||
sameSite: 'strict',
|
sameSite: 'strict',
|
||||||
maxAge: 24 * 60 * 60 * 1000 // 24 hours
|
maxAge: 24 * 60 * 60 * 1000 // 24 hours
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue