Variable added to Node.js express-session is undefined in next request - node.js

I am implementing a simple login functionality and storing the data in the express-session but not able to get it back.
In loginDb.js file in login function i am storing the userId in session variable and in getLoginStatus function i am trying to access the userId but it is returing as undefined.
I have gone through many post related to similar issue but nothing helped in my case. Don't know what i am doing wrong here. Below is the code.
server.js
var express = require('express');
var pg = require('pg');
var cookieParser = require('cookie-parser');
var bodyparser = require('body-parser');
var session = require('express-session');
var path = require('path');
const port = 3000;
const loginroute = require('./Routes/login');
var app=express();
app.use(bodyparser.json());
app.use(bodyparser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({
secret: 'This is a secret',
resave: true,
saveUninitialized:true,
cookie: {
secure: false,
maxAge: 60000
}
}));
//Routes
app.use('/api/loginroute',loginroute);
app.listen(port,function(){
console.log('app listening to port:'+port);
});
login.js
const express = require('express');
const router = express.Router();
const db = require('../DataAccessLayer/loginDb');
router.get('/getLoginStatus', db.getLoginStatus);
router.post('/login', db.login);
module.exports = router;
loginDb.js
var config = require('../Config/config');
var session = require('express-session');
var pg = require('pg');
var pool = new pg.Pool(config.development.db);
function getLoginStatus(req, res, next){
var userId = req.session.userId;
};
function login(req, res, next) {
pool.connect(function(err, client, done) {
if (err) {
console.log("not able to get connection "+ err);
res.status(400).send(err);
}
var q = "select id from nodetest.users where name=$1 and password=$2";
client.query(q, [req.body.username, req.body.password], function(err, result) {
done();
if(err) {
return console.error('error running query', err);
}
if(result.rowCount>0){
req.session.userId = result.rows[0].id;
}
res.send(result.rows);
});
});
};
module.exports = {
login:login,
getLoginStatus:getLoginStatus
};

Set cookieParser secret key similar as that of express-session secret key will fix the issue.
app.use(cookieParser('This is a secret'))
Doc Says
Using cookie-parser may result in issues if the secret is not the same
between this module and cookie-parser.

Related

req.isAuthenticated() returns false after successRedirect

I know that there are numerous posts already referring to the same problem, however, I couldn't find a solution for my case. Here is the relevant code for the issue :
users.js (route)
The login form is submits a POST request to this route.
var express = require('express');
var router = express.Router();
// Require controllers
var usersController = require('../../controllers/usersController');
/* POST login */
router.post('/login', usersController.loginAccount);
module.exports = router;
usersController.js
The passport authentication is handled here.
req.isAuthenticated() returns false here as well. However, successRedirect is executed, which should mean that the user was successfully authenticated.
'use strict';
var bodyParser = require('body-parser');
var mysql = require('mysql');
var bcrypt = require('bcryptjs');
var Client = require('../models/Client');
var passport = require('passport');
var Sequelize = require('sequelize');
var urlencodedParser = bodyParser.urlencoded({ extended: false });
/* POST - Login */
module.exports.loginAccount = function (req, res, next) {
passport.authenticate('local', {
successRedirect: '../dashboard',
failureRedirect: '/users/login',
failureFlash: true
}) (req, res, next);
console.log("Exactly after authentication: " + req.isAuthenticated());
}
index.js (route)
Here, ensureAuthenticated always returns false
var express = require('express');
var router = express.Router();
// Require controllers
var indexController = require('../../controllers/indexController');
/* GET dashboard page */
router.get('/dashboard', ensureAuthenticated, indexController.dashboardPage);
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated())
{console.log("AUTHENTICATED"); return next();}
else{
console.log("NOT AUTHENTICATED");
req.flash('error_msg', 'Please log in to view this resource');
res.redirect('/users/login');
}
}
module.exports = router;
indexController.js
When submitting the login form, this code doesn't get executed, because ensureAuthenticated() is false.
'use strict';
var bodyParser = require('body-parser');
var mysql = require('mysql');
var urlencodedParser = bodyParser.urlencoded({ extended: false });
/* GET - Dashboard page */
module.exports.dashboardPage = function(req, res) {
// console.log(req.user);
// console.log(req.isAuthenticated());
res.render('dashboard');
};
passport.js
const LocalStrategy = require('passport-local').Strategy;
const Sequelize = require('sequelize');
const bcrypt = require('bcryptjs');
// Load User Model
const Client = require('../models/Client');
module.exports = function(passport) {
passport.use(
new LocalStrategy({ usernameField: 'username'}, function(username, password, done) {
// Match User
Client.findOne({ where: {username: username} })
.then(function(user) {
if(!user) {
return done(null, false, { message: 'That username is not registered'});
}
// Match password
bcrypt.compare(password, user.password, function(err, isMatch) {
if(err) throw err;
if(isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Password incorrect'});
}
});
})
.catch(function(err) { console.log(err) });
})
)
passport.serializeUser(function(user, done) {
console.log('Serializing user');
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
console.log('Deserializing user');
console.log('User ID:', id);
Client.findByPk(id)
.then(function(err, user) {
console.log('User ID:', id);
done(err, user);
});
});
}
All the required middleware is setup in the correct order (express-session -> passport.initialize -> passport.session). cookieParser and express-session are set with the same secret (which is otherwise a problem as other posts suggest).
app.js
var createError = require('http-errors');
var express = require('express');
var expressLayouts = require('express-ejs-layouts');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var mysql = require('mysql');
var flash = require('connect-flash');
var session = require('express-session');
var passport = require('passport');
var bodyParser = require('body-parser');
var cors = require('cors');
// Passport config
require('./config/passport')(passport);
var usersController = require('./controllers/usersController');
var indexRouter = require('./api/routes/index');
var usersRouter = require('./api/routes/users');
var roomsRouter = require('./api/routes/rooms');
var app = express();
app.use(cors());
// view engine setup
app.set('views', path.join(__dirname, 'views'));
// EJS
app.use(expressLayouts);
app.use(express.json());
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser('secret'));
app.use(express.static(path.join(__dirname, 'public')));
// Express Session
app.use(session({
secret: 'secret',
resave: true,
saveUninitialized: true,
cookie: { maxAge: 60000 }
}));
// Passport middleware
app.use(passport.initialize());
app.use(passport.session());
In your app.js the routes need to be defined after the passpor middleware is set up.
For Example:
var createError = require('http-errors');
var express = require('express');
var expressLayouts = require('express-ejs-layouts');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var mysql = require('mysql');
var flash = require('connect-flash');
var session = require('express-session');
var passport = require('passport');
var bodyParser = require('body-parser');
var cors = require('cors');
// Passport config
require('./config/passport')(passport);
var usersController = require('./controllers/usersController');
var app = express();
app.use(cors());
// view engine setup
app.set('views', path.join(__dirname, 'views'));
// EJS
app.use(expressLayouts);
app.use(express.json());
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser('secret'));
app.use(express.static(path.join(__dirname, 'public')));
// Express Session
app.use(session({
secret: 'secret',
resave: true,
saveUninitialized: true,
cookie: { maxAge: 60000 }
}));
// Passport middleware
app.use(passport.initialize());
app.use(passport.session());
var indexRouter = require('./api/routes/index');
var usersRouter = require('./api/routes/users');
var roomsRouter = require('./api/routes/rooms');
Try doing this and see the output

Protection csrf Nodejs Form

I have a little probleme with my Nodejs application. I want protect my forms with csrf token, but it's not work. I have an error like
ForbiddenError: invalid csrf token
POST http://localhost:3000/addfile 403 (Forbidden)
I want to create csrf token for all requests. I can create csrf token, but if I use the methods like : POST/PUT or DELETE it's not work.
I don't understand why I have this error. Thanks for yours answers.
app.js
var express = require("express");
var bodyParser = require("body-parser");
var mongoose = require('mongoose');
var fs = require('fs');
var path = require('path');
var logger = require('morgan');
var expressValidator = require('express-validator');
var csrf = require('csurf');
var session = require('express-session');
var passport = require('passport');
var PORT = 3000;
var config = require('./config/database');
var app = express();
// Connexion to MongoDb
mongoose.connect(config.database, function(err) {
if(err){
console.log(err);
}
else{
console.log("Connected to MongoDb");
}
});
// Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(expressValidator());
app.set('views',path.join(__dirname, ''));
app.set('view engine','pug');
app.use(express.static(path.join(__dirname, '')));
app.disable('x-powered-by');
app.use(session({
name: 'SESS_ID',
secret: config.secret,
resave: true,
saveUninitialized: true,
cookie: {
secure: false,
httpOnly: true,
maxAge: 5*60*1000 } //15minutes*60sec*1000ms
//cookie: {secure: false} //https = true, http=false
}));
app.use(csrf());
app.use(passport.initialize());
app.use(passport.session());
require('./config/passport')(passport);
app.use(function(req, res, next) {
res.locals._csrf = req.csrfToken();
next();
});
app.use('/', require('./routes/fileRoutes'));
app.use('/', require('./routes/authRoutes'));
app.listen(PORT,function(){
console.log("Server started at the port " + PORT);
});
routes/fileRoutes.js
app.get('/',function(req,res){
File.find(function(err, files){
res.render('views/layout',{files:files});
});
});
app.post('/addfile',upload,function(req,res){
if (req.fileValidationError) {
return res.end("Error PDF");
} else {
for (var i = 0; i < req.files.length; i++)
{
var files = new File ();
files.fieldname= req.files[i].fieldname;
files.originalname= req.files[i].originalname;
files.encoding= req.files[i].encodin;
files.path= req.files[i].path;
files.save(function(err, data){
});
}
res.redirect('/');
}
});
layout.pug
form#uploadForm(enctype='multipart/form-data', action='/addfile', method='post')
input(type='hidden', name='_csrf', value=_csrf)
input(type='file', name='userPhoto', multiple='')
input(type='submit', value='Upload Image', name='submit')
input#random(type='text', name='random')
I see you have:
input(type='hidden', name='_csrf', value=_csrf)
What is the value for if you console.log(_csrf)? I also noticed you didn't put that one in quotes.

Express and Vue. With axios, req.body is not working

Like i said in title. req.body don't work. I saw some examples and that use req.body(body-parser) well. But in my code, req.body is keep undefined. Also i found same problems and they said "app.use(bodyParser.json())" will work. But for me, no. So i ask how can i solve this error. Plz, help me.
This code is simple, Express and Vue login, signin test project. I think problem is in server file.
Server
var express = require("express");
var bodyParser = require("body-parser");
var path = require("path");
const mongoose = require("mongoose");
var index = require("./routes/index.js");
var login = require("./routes/login.js");
var signin = require("./routes/signin.js");
var app = express();
var http = require("http").Server(app);
mongoose.connect("mongodb://localhost:27017/test");
app.use('/', index);
app.use('/api/login', login);
app.use('/api/signin', signin);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.set("port", process.env.PORT || 3000);
app.use(express.static(path.join(__dirname, 'public')));
http.listen(app.get("port"), function() {
console.log("server start in " + app.get("port"));
})
Router
const express = require("express");
const router = express.Router();
const User = require("../models/user.js");
router.post("/", function(req, res, next) {
const id = req.body.id;
const password = req.body.password;
let info = {
error: "false",
words: "",
id: "",
password: ""
}
User.findOne({ id: id }, function(err, user) {
if(err) {
info.error = "true";
info.words = "Unknown Error Come Out.";
return res.send(info);
}
if(!user) {
info.error = "true";
info.words = "Please Check Your ID or Password";
return res.send(info);
}
info.id = id;
info.password = password;
console.log(info);
return res.send(info);
})
});
module.exports = router;
This body can not be resolved because of your middleware declaration order. You can check from the following blog about middleware execution sequence. Basically it equals to middleware declaration order.
https://derickbailey.com/2016/05/09/in-what-order-does-my-express-js-middleware-execute/
Declare bodyParser middleware before router middleware can solve your problem
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/api/login', login);

Express session is undefined when accessing from different route?

Im trying to implement infinite scroll. In my first route I load 5 elements from the data base and store the id of the last seen item. To load more data getNextHomeContent is called, but for some reason req.session.lastseen is undefined.
server.js
var express = require('express');
var session = require('express-session');
var app = express();
var mongoose = require('mongoose');
var logger = require('morgan');
var bodyParser = require('body-parser');
var cors = require('cors');
//imports database configuration
var databaseConfig = require('./config/database');
//defines route file to use
var router = require('./app/routes');
//connect to datbase
mongoose.connect(databaseConfig.url);
app.listen(process.env.PORT || 8080);
console.log("App listening on port 8080");
app.use(bodyParser.urlencoded({ extended: false })); // Parses urlencoded bodies
app.use(bodyParser.json()); // Send JSON responses
app.use(logger('dev')); // Log requests to API using morgan
app.use(cors());
app.use(session({
resave: true,
saveUninitialized: true,
secret: 'keyboard cat',
cookie: {
maxAge: 60000,
secure: false
}
}));
router(app);
And here is my controller for my routes in homeCtrl.js
exports.getHomeContent = function(req, res, next) {
req.session.lastseen = null;
homeContent.find({})
.sort({
"_id": -1
})
.limit(5)
.exec(function(err, content) {
if (err) {
res.send(err);
}
var last = content.slice(-1);
req.session.lastseen = last[0]._id;
console.log("lastseen first is " + req.session.lastseen);
res.json(content);
});
}
exports.getNextHomeContent = function(req, res, next) {
console.log("lastseen is " + req.session.lastseen);
homeContent.find({
"_id": { "$lt": req.session.lastseen }
})
.sort({
"_id": -1
})
.limit(5)
.exec(function(err, content) {
if (err) { res.send(err); }
console.log("WTF:" + content.slice(-1));
var lastitem = content.slice(-1);
req.session.lastseen = lastitem[0]._id;
res.json(content);
});
}
When get Home content runs, req.session.lastname is set to the ID of the last item. However req.session.lastitem becomes undefined when getNextHomeContent() runs. Can anyone help me with this?
Thanks!!

NodeJS module.exports does not work as expected

I am writing a web service in NodeJS using Express. My problem occurs when I want to use the app (Express instance) in other modules. The following configuration works just fine, but if I replace
var app = module.exports = express();
with
var app = express();
and then use
module.exports = app;
at the bottom of app.js, everything will break down. There will be an error when calling app.get() in the auth module (TypeError: app.get is not a function). Can somebody explain to me why it matters where I export the app object?
app.js
var mongoose = require('mongoose');
var express = require('express');
var bodyParser = require('body-parser');
var debug = require('debug')('app');
var morgan = require('morgan');
var config = require('./config');
var app = module.exports = express();
// --- globals ---
app.set('jwtTokenSecret', config.jwtTokenSecret);
// --- middleware ---
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(morgan('dev'));
// --- routes ---
var courses = require('./routes/courses');
var users = require('./routes/users');
var auth = require('./routes/auth');
app.use('/auth', auth);
app.use('/courses', courses);
app.use('/users', users);
// --- database connection ---
mongoose.set('debug', true);
mongoose.connect(config.database, function(err) {
if (err) {
debug('Could not establish connection to mongodb');
} else {
debug('Successfully connected to mongodb');
}
});
routes/auth.js
var express = require('express');
var router = express.Router();
var moment = require('moment');
var jwt = require('jwt-simple');
var User = require("../models/User");
var debug = require('debug')('app');
var app = require("../app");
// POST /auth
router.post('/', function(req, res, next) {
User.findOne({
'username' : req.body.username
}, function(err, user) {
if (err || !user) {
res.status(401).json({ error: "No user found"});
return;
}
if (user.password != req.body.password) {
res.send(401);
}
debug(app.get('database'));
var expires = moment().add(7, 'days').valueOf();
var token = jwt.encode({
user: user.username,
exp: expires
}, app.get('jwtTokenSecret'));
res.json({
success: true,
token: token
});
});
});
module.exports = router;
It's because you have a circular dependency between app.js and auth.js.
In your app.js file, you are requiring auth.js, and inside auth.js, you are requiring app.js. By moving module.exports = app to the bottom of app.js, it is being called AFTER var auth = require('./routes/auth');. This means that when var app = require("../app"); is called inside auth.js, module.exports will not be yet defined inside app.js, hence leading to the error.

Resources