I reviewed similar questions that have been asked before, but I have not been able to resolve my issue. Currently, users are able to login to the application without any issue, but sometimes during the session, req.user will be undefined. I am not sure if this is just a configuration issue, or if there is something else going on.
Right now, I am using the local strategy for passport with a MySQL database. I am also using a MySQLStore for the session store.
Here is the code I currently have in my index.js file:
/******************************************
* Modules *
******************************************/
require('dotenv').config();
var flash = require('connect-flash');
var express = require('express');
var app = express();
var request = require('request');
var http = require('http').Server(app);
var io = require('socket.io')(http);
var fs = require('fs');
var mysql = require('mysql');
var passport = require('passport');
var Strategy = require('passport-local').Strategy;
var ensureLogin = require('connect-ensure-login');
var winston = require('winston');
var session = require('express-session');
var MySQLStore = require('express-mysql-session')(session);
var passportSocketIo = require("passport.socketio");
var cookieParser = require('cookie-parser');
var helmet = require('helmet');
var RateLimit = require("express-rate-limit");
var csrf = require('csurf');
var bcrypt = require('bcrypt');
const saltRounds = 10;
app.use(flash());
app.use(helmet());
app.set('port', (process.env.PORT || 5000)); // the port number for the application
app.use(express.static(__dirname + '/public')); // directory for the css, images, and js files
app.set('views', __dirname + '/views'); // views is directory for all template files
app.set('view engine', 'ejs'); // our templating engine
app.use(require('body-parser').urlencoded({ extended: true }));
winston.configure({
transports: [
new (winston.transports.File)({ filename: 'error.log' })
]
});
var csrfProtection = csrf();
var MsgAgent = require('./lib/MsgAgent');
/******************************************
* MySQL Setup *
******************************************/
var connection = mysql.createConnection({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
port: process.env.DB_PORT
});
connection.connect(function(err) {
if (err) {
console.error('error connecting: ' + err.stack);
}
});
app.use(cookieParser());
var sessionStore = new MySQLStore({expiration: 36000000, checkExpirationInterval: 900000}/* session store options */, connection);
app.use(session({
secret: process.env.SESSION_SECRET,
rolling: true,
resave: true,
saveUninitialized: false,
store:sessionStore,
cookie: {
secure: false,
httpOnly: true,
sameSite: true,
domain: process.env.COOKIE_DOMAIN // needs to be updated once pushed to aws
}
}));
/******************************************
* Passport Session Setup *
******************************************/
passport.serializeUser(function(user, cb) {
cb(null, user.agent_id);
});
passport.deserializeUser(function(id, cb) {
var query = "SELECT agent_id, "+
"CAST(AES_DECRYPT(rt_user_data.name, UNHEX(SHA2('Rt17ix90',512))) AS CHAR) name, "+
"CAST(AES_DECRYPT(rt_user_data.username, UNHEX(SHA2('Rt17ix90',512))) AS CHAR) username, "+
"CAST(AES_DECRYPT(rt_user_data.password, UNHEX(SHA2('Rt17ix90',512))) AS CHAR) password, "+
"CAST(AES_DECRYPT(rt_user_data.role, UNHEX(SHA2('Rt17ix90',512))) AS CHAR) role, "+
"CAST(AES_DECRYPT(rt_user_data.maxChats, UNHEX(SHA2('Rt17ix90',512))) AS CHAR) maxChats, "+
"CAST(AES_DECRYPT(rt_user_data.locked, UNHEX(SHA2('Rt17ix90',512))) AS CHAR) locked, "+
"CAST(AES_DECRYPT(rt_user_data.failedAttempts, UNHEX(SHA2('Rt17ix90',512))) AS CHAR) failedAttempts "+
"FROM rt_user_data WHERE agent_id = " + connection.escape(id) + ";";
connection.query(query, function(error, results, fields) {
if(error){
console.log("error deserializeUser: ", error);
cb(error);
}else{
cb(null, results[0]);
}
});
});
passport.use(new Strategy(
function(username, password, cb) {
var query = "SELECT agent_id, "+
"CAST(AES_DECRYPT(rt_user_data.name, UNHEX(SHA2('Rt17ix90',512))) AS CHAR) name, "+
"CAST(AES_DECRYPT(rt_user_data.username, UNHEX(SHA2('Rt17ix90',512))) AS CHAR) username, "+
"CAST(AES_DECRYPT(rt_user_data.password, UNHEX(SHA2('Rt17ix90',512))) AS CHAR) password, "+
"CAST(AES_DECRYPT(rt_user_data.role, UNHEX(SHA2('Rt17ix90',512))) AS CHAR) role, "+
"CAST(AES_DECRYPT(rt_user_data.maxChats, UNHEX(SHA2('Rt17ix90',512))) AS CHAR) maxChats, "+
"CAST(AES_DECRYPT(rt_user_data.locked, UNHEX(SHA2('Rt17ix90',512))) AS CHAR) locked, "+
"CAST(AES_DECRYPT(rt_user_data.failedAttempts, UNHEX(SHA2('Rt17ix90',512))) AS CHAR) failedAttempts "+
"FROM rt_user_data WHERE username = AES_ENCRYPT("+ connection.escape(username) +", UNHEX(SHA2('Rt17ix90',512)));";
connection.query(query, function(error, results, fields) {
if(error){
console.log(error);
return cb(error);
}
if(!results.length){
return cb(null, false, {message: "username"});
}else if(results[0].locked == 1){
return cb(null, false, {message: "locked"});
}else {
bcrypt.compare(password, results[0].password, function(err, res2) {
if(res2){
return cb(null, results[0]);
}else{
failedPasswordAttempt(results[0], function(){
return cb(null, false, {message: "password"});
});
}
});
}
});
}
));
// Initialize Passport and restore authentication state, if any, from the session.
app.use(passport.initialize());
app.use(passport.session());
/******************************************
* URL Endpoints *
******************************************/
/* URL to login to the rollover tool */
app.get('/', /*csrfProtection,*/ function(req, res){
res.render('pages/login', { user: null, message: req.flash('error'), csrfToken: "temp"/*req.csrfToken()*/ }); // renders the index page of the application
});
/* URL to login to the rollover tool */
app.get('/login', /*csrfProtection,*/ function(req, res){
res.render('pages/login', { user: null, message: req.flash('error'), csrfToken: "temp"/*req.csrfToken()*/ }); // renders the index page of the application
});
/* URL for logging in to the rollover tool - form data is posted here */
app.post('/login', /*loginLimiter,*/ passport.authenticate('local', {failureRedirect: '/login', failureFlash: true}), function(req, res) {
res.redirect('/loading');
});
/* URL for logging the user out of the rollover tool */
app.get('/logout', function(req, res){
//logoutAllLEUsers(req.user.agent_id); // logout all LiveEngage users for this agent
req.logout(); // force logout the session
res.redirect('/login'); // redirect to the login page
});
/* URL to access the main dashboard of the rollover tool */
app.get('/dashboard', /*csrfProtection,*/ ensureLogin.ensureLoggedIn('/login'), function(req, res){
//console.log(req.user);
res.render('pages/index', { user: req.user, csrfToken: "temp"/*req.csrfToken()*/ });
});
/******************************************
* Socket IO *
******************************************/
io.use(passportSocketIo.authorize({
cookieParser: cookieParser, // the same middleware you registrer in express
key: 'connect.sid', // the name of the cookie where express/connect stores its session_id
secret: process.env.SESSION_SECRET, // the session_secret to parse the cookie
store: sessionStore, // we NEED to use a sessionstore. no memorystore please
success: onAuthorizeSuccess, // *optional* callback on success - read more below
fail: onAuthorizeFail, // *optional* callback on fail/error - read more below
}));
io.on('connection', function(socket){
var arrayIndex = findWithAttr(agentDetail, "id", socket.request.user.agent_id);
if(arrayIndex != -1){
agentDetail[arrayIndex].disconnected = false;
}
socket.request.user.socketID = socket.id;
var userId = socket.request.user;
//console.log("Your User ID is", userId);
updateAgentObjectWithSocket(socket.request.user.agent_id, socket.id); // update the agent object with the new socket information
socket.on('disconnect', function(){
/* Get the user that just left the page and update their disconnect to true */
var tempArrayIndex = findWithAttr(agentDetail, "id", socket.request.user.agent_id);
if(tempArrayIndex != -1){
agentDetail[tempArrayIndex].disconnected = true;
}
/* Set a timeout in case user refreshs the pages or leaves and comes back. This is used to make sure we are logging out the correct users */
setTimeout(function() {
var tempArrayIndex2 = findWithAttr(agentDetail, "id", socket.request.user.agent_id);
if(tempArrayIndex2 != -1){
if(agentDetail[tempArrayIndex2].hasOwnProperty("disconnected")){
if(agentDetail[tempArrayIndex2].disconnected){
if(socket.request.user.hasOwnProperty("agent_id")){
logoutAllLEUsers(socket.request.user.agent_id); // logout all LiveEngage users for this agent
}
socket.request.logout();
sessionStore.destroy(socket.request.sessionID, function(data) {
//console.log("Callback called: ", data);
});
}
}
}
}, 5000);
/* end of setTimeout */
});
});
function onAuthorizeSuccess(data, accept){
accept(null, true);
}
function onAuthorizeFail(data, message, error, accept){
if(error)
throw new Error(message);
console.log('failed connection to socket.io:', message);
accept(null, false);
}
/******************************************
* Start Server *
******************************************/
http.listen(app.get('port'), function(){
console.log('Node app is running on port', app.get('port'));
});
I tried updating the order of the middleware, but the issue still persists. Any help would be much appreciated.
Also, here are the versions of the modules that I am currently using:
- Express - 4.15.2
- Passport - 0.3.2
- Passport.Socket.io - 3.7.0
- Express-mysql-session - 1.2.0
via Scott
No comments:
Post a Comment