SessionStore causes error on CSRF token
charles-dejager opened this issue · comments
charles-dejager commented
I am using ExpressJS with csurf, express-session, and connect-session-sequelize. When I set up express-session with no store (ie use memstore) all works as it should. When I use connect-session-sequelize I get a
403 - ForbiddenError: invalid csrf token
at csrf (/Users/djagercd/dev/mm-edds/node_modules/csurf/index.js:113:19)
My config looks as follows:
// **session-connect.js**
const
session = require('express-session'),
sessionStore = require('connect-session-sequelize')(session.Store),
{logger} = require('./logger');
function init(server, config, db) {
const sequelizeSessionStore = new sessionStore({
db: db.sequelize,
checkExpirationInterval: config.session.expireInterval,
expiration: config.session.expiration
});
// sequelizeSessionStore.sync();
server.use(session({
secret: config.session.secret,
store: sequelizeSessionStore,
resave: config.session.reSave,
proxy: config.session.proxy,
saveUninitialized: config.session.saveUninitialized
}));
// sequelizeSessionStore.sync();
}
// **index.js (main module of my server).**
'use strict';
const
express = require('express'),
bodyParser = require('body-parser'),
{logger, expressErrorLogger, expressLogger} = require('./logger'),
process = require('process'),
routes = require('./routes'),
db = require('./models'),
cookieParser = require('cookie-parser'),
path = require('path'),
compression = require('compression'),
helmet = require('helmet'),
csrf = require('csurf'),
session = require('./session-connect'),
knex = require('./db'),
server = express();
function shutDown() {
logger.log('info', 'Shutting Down Server');
db.sequelize.close()
.then(result => {
return knex.destroy();
})
.then(result => {
return session.clear();
})
// .then(result => {
// return server.close();
// })
.then(result => {
logger.log('info', 'Successful Shutdown');
return true;
})
.catch(err => {
logger.log('error', `Shutdown failed ${err.toString()}`);
return false;
})
}
module.exports = function () {
let create,
start;
create = function (config) {
const staticDir = path.join(__dirname, '..', 'public');
// const csrfProtection = csrf();
server.set('env', config.env);
server.set('port', config.port);
server.set('hostname', config.hostname);
server.set('viewDir', config.viewDir);
server.set('staticDir', staticDir);
server.set('db', db);
// Setup view engine
server.set('view engine', 'ejs');
server.set('views', server.get('viewDir'));
// server.use(express.json);
// server.use(express.urlencoded);
server.use(helmet());
server.use(helmet.xssFilter({setOnOldIE: true}));
server.use(helmet.frameguard('deny'));
server.use(helmet.hsts({maxAge: 7776000000, includeSubdomains: true}));
server.use(helmet.hidePoweredBy());
server.use(helmet.ieNoOpen());
server.use(helmet.noSniff());
server.use(helmet.noCache());
server.use(bodyParser.json());
server.use(bodyParser.urlencoded({extended: false}));
server.use(express.static(staticDir));
server.use(compression());
server.use(cookieParser());
server.use(expressLogger);
// Setup session handling
session.init(server, config, db);
server.use(csrf({cookie: false}));
server.use((req, res, next) => {
res.locals.csrfToken = req.csrfToken();
console.log(`req csrf: ${res.locals.csrfToken}`);
res.locals.isAuthenticated = req.session.isLoggedIn;
res.locals.current_user = req.session.current_user;
res.locals.message = '';
next();
});
routes.init(server);
server.use(expressErrorLogger);
};
start = function () {
const hostname = server.get('hostname'),
port = server.get('port');
server.listen(port, function () {
logger.log('info', `Starting Server for ${server.get('env')} configuration`);
logger.log('info', `Express server listening on: http://${hostname}:${port}`)
});
};
return {
create: create,
start: start,
shutDown: shutDown
};
};
My login.ejs file does have the hidden input field called _csrf.
You help would be appreciated.
Michael Weibel commented
It'd be easiest if you create a quick repo with how to reproduce it. Is that possible?
Jason Gerfen commented
@charles-dejager does your app work when you use server.use(csrf({cookie: true}));
?