session in nodejs express - node.js

I' m using const SessionStore = require('express-session-sequelize')(expressSession.Store); for storing the sessions.
I would like to save in session currenty user, which log to site.
here is a configuration for store:
const expressSession = require('express-session');
const SessionStore = require('express-session-sequelize')(expressSession.Store);
const Sequelize = require('sequelize');
const myDatabase = new Sequelize('analytic', 'root', '', {
host: 'localhost',
dialect: 'mysql'
});
const sequelizeSessionStore = new SessionStore({
checkExpirationInterval: 15 * 60 * 1000, // The interval at which to cleanup expired sessions in milliseconds.
expiration: 24 * 60 * 60 * 1000, // The maximum age (in milliseconds) of a valid session.
db: myDatabase
});
const cookieParser = require('cookie-parser');
app.use(cookieParser());
app.use(expressSession({
secret: '412415415415415121212121',
store: sequelizeSessionStore,
name: 'session_id',
resave: false,
saveUninitialized: false
}));
So, now for login I have this:
var express = require('express');
var url = require('url');
var router = express.Router();
var User = require('../../model').User;
var jwt = require('jsonwebtoken');
var app = require("../../application");
router.post('/authenticate', function(req, res) {
User.doLogin(req).then((result)=> {
if (result) {
if (result.error) {
if (result.error.hasOwnProperty("email")) {
res.send(400, { success: false, message: "Incorrect user / password"});
} else if (result.error.hasOwnProperty("activated")) {
res.send(400, {success: false, message: "You are not activated yet"});
}
} else {
//app.createSession(req);
req.session.user = result;
res.send(200, result);
}
}
});
});
module.exports = router;
Now, after this req.session.user = result; I have in db session table with current user data.
Now,
How can I verify is this user authenticated?
and I notice that for every request I get diferrent sessionID (is this ok)
Thanks

Hi there for user manager you can use passportjs
it's a great user manager for express and provide a high quality for handle with your user manager logic .

Related

`req.session.user` is `undefined` when using `express-session` and `connect-mongo`

I've created a react app that runs on port:3000 and an express app that runs on port:3001.
I am using express-session and connect-mongo to handle user sessions. When I set a user session in /login it was recorded in MongoDB as expected. But when I query for req.session.user later in a different path/route, for example /channels it returns undefined.
This is how my app.js looks
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const {Server} = require("socket.io");
const io = new Server(server);
const port = process.env.PORT || 3001;
const cors = require("cors");
const path = require('path');
const session = require('express-session');
const bodyParser = require('body-parser');
const oneDay = 1000 * 60 * 60 * 24;
const MongoStore = require('connect-mongo');
const md5 = require('md5');
const hash = '=:>q(g,JhR`CK|acXbsDd*pR{/x7?~0o%?9|]AZW[p:VZ(hR%$A5ep ib.&BLo]g';
app.use(session({
secret: hash,
saveUninitialized: false,
resave: false,
store: MongoStore.create({
mongoUrl: 'mongodb://localhost:27017/chat',
ttl: 14 * 24 * 60 * 60 // = 14 days. Default
})
}));
app.use(
cors({
origin: true,
credentials: true,
optionsSuccessStatus: 200
}));
// create application/json parser
const jsonParser = bodyParser.json({limit: '50mb'})
// create application/x-www-form-urlencoded parser
const urlencodedParser = bodyParser.urlencoded({limit: '50mb', extended: false})
app.post('/login', jsonParser, (req, res) => {
db.users.find({email: req.body.email}).toArray().then(user => {
if (user.length < 1) {
res.send({success: false, error: 'NOT_FOUND', message: 'Invalid login info!'});
} else {
user = user[0];
if (user.password === req.body.password) {
db.users.updateOne({"email": user.email}, {$set: {"online": "1"}}).then(ret => {
req.session.user = user.email;
req.session.userdata = user;
res.json(<=user data=>);
});
}
}
})
});
app.post('/channels', async (req, res) => {
if (!req.session.user) {// THIS IS ALWAYS TRUE; EVEN AFTER SUCCESSFUL LOGIN
res.json({logout: true});
return;
}
const user = JSON.parse(req.session.userdata);
const channels = db.channels.find({contacts: {$all: [user._id]}}).toArray().then(channels => {
let allch = {};
channels.map(function (channel) {
channel.id = channel._id.toString();
channel.notif = 0;
allch[channel.id] = channel;
});
res.json(allch);
});
});
When You fetch from front-end for specific route, don't forget to include in options: "credentials: "include" ", like here:
const options = {
method: "POST",
headers: {
"content-type": "application/json",
},
body: JSON.stringify(searchInput),
credentials: "include",
};
fetch("http://localhost:4000/sendSearchInput", options)
.then((res) => res.json())
.then((data) => {
console.log(data);
});
Edit:
Note - This should be included in each request from the client that either sets or reads the 'express-session' middleware (req.session.x).
(Not just reads)
I think you will need to call req.session.save() yourself when you want to update the session store with the current data.

swagger not preserving sessions

I am trying to set up a simple login endpoint in swagger:
//login.js
'use strict';
function login(req, res){
const userId = req.swagger.params.user_id.value;
const user = {
_id: userId
}
if(req.session.userId){
return res.json([req.session.userId, 'hello']);
}
global.app.db.collection('users').insertOne(user, function(err, b){
req.session.userId = userId;
return res.json([req.session]);
});
}
module.exports = {
login: login
};
It seems the if statement is never true, and the userId is never set permanently (it shows up in just the second return statement after the insert statement).
Not sure what is wrong here. My app.js has the typical express-session setup.
//app.js
'use strict';
const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');
const mongoDbUrl = 'mongodb://localhost:27017';
const dbName = 'my_db';
var SwaggerExpress = require('swagger-express-mw');
var app = require('express')();
var session = require('express-session')
const MongoStore = require('connect-mongo')(session);
app.set('trust proxy', 1) // trust first proxy
app.use(session({
secret: 'some secret',
store: new MongoStore({url:mongoDbUrl}),
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}))
module.exports = app; // for testing
global.app = app;
var config = {
appRoot: __dirname // required config
};
SwaggerExpress.create(config, function(err, swaggerExpress) {
if (err) { throw err; }
// install middleware
swaggerExpress.register(app);
var port = process.env.PORT || 10010;
app.listen(port);
if (swaggerExpress.runner.swagger.paths['/hello']) {
console.log('try this:\ncurl http://127.0.0.1:' + port + '/hello?name=Scott');
}
});
MongoClient.connect(mongoDbUrl, function(err, client) {
assert.equal(null, err);
console.log("Connected successfully to server");
const db = client.db(dbName);
app.db = db;
});
Looks like the problem was this line:
cookie: { secure: true }
secure should have been false because I wasn't using https on my local machine.

express-session session is not consistent

In my project i am using nodejs (express), react js and socket.io to develop a chatting application. But i am not able to get "correct sessionid" inside my socket function (io.use).
In server.js file there are routes and functions to handle socket connections.
In my project i had started my express-session inside login.js file.
Then after successfull login...i am redirecting to home.js, which intern returns home.html.
home.html contains js file, which is having react code and also have socket connections.
server.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var path = require('path');
var DIST_DIR = path.join(__dirname, "bin");
var express = require('express');
//Getting session store
var session = require('express-session');
var cookieParser = require('cookie-parser');
var sessionStore = new session.MemoryStore();
var handshakeData ={};
var cookie = require('cookie');
//Importing routes
var login = require('./routes/login.js');
var registration = require('./routes/registration.js');
var home = require('./routes/home.js');
//Getting cookies from request header. so that from it we can get sessionid.
io.use(function(socket, next) {
handshakeData = socket.request;
var cookies = cookie.parse(handshakeData.headers.cookie);
//Bringing sessionid and storing in a global variable
console.log("***********************Server*********************");
console.log("");
console.log('All cookies parsed in io.use ( %s )', JSON.stringify(cookies));
handshakeData.sessionID = cookies['connect.sid'].split('.')[0].split(':'[1];
console.log('All cookies parsed at server ( %s )', JSON.stringify(cookies));
console.log('Session id at server cookie value in io.use( %s )',
JSON.stringify(handshakeData.sessionID));
next();
});
//Bringing session data by sending "sessionid" to sessionStore
(MemoryStore)place
io.on('connection', function(socket){
sessionStore.get(handshakeData.sessionID, function (err, session) {
handshakeData.session = session;
//Now we can retrieve all session data. But sessionID sent was
not correct
});
console.log('user connected');
socket.on('new message', function(msg){
console.log('Server recieved new message: '+msg);
io.emit('new message', msg);
});
socket.on('disconnect', function(){
console.log('user disconnected');
});
});
app.use('/', login);
app.use('/registration', registration);
app.use('/home', home);
http.listen(8080, function(){
console.log("listening on port 8080");
});
login.js
var bodyParser = require('body-parser');
var urlencodedParser = bodyParser.urlencoded({ extended: false })
var cookieParser = require('cookie-parser');
var session = require('express-session');
var sessionStore = new session.MemoryStore();
var login_success = 0;
router.use(cookieParser());
router.use(session({ cookie: {
maxAge : 24*60*60*1000
},
store: sessionStore,
saveUninitialized: true,
resave: true,
secret: '1234567890QWERT'
}));
router.get('/', function(req, res){
console.log("Actual session id before login: "+ req.sessionID);
//Clearing cookies at client side.
res.clearCookie("login_message");
res.clearCookie("connect.sid");
res.clearCookie("io");
res.clearCookie("user_name");
res.clearCookie("user_id");
if (login_success == 2)
{
res.cookie('login_message', 'incorrectCredentials');
login_success = 0;
}
res.sendFile(path.join(SRC_DIR,"login.html"));
// res.sendFile(path.join(__dirname, '../bin', 'login.html'));
});
router.post('/', urlencodedParser, function(req, res){
console.log("database called");
//Fetching form data
var username = req.body.loginusername;
var password = req.body.loginpassword;
//Connection string to datanbase
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/WebChat";
//Comparing username and password.
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var query = { email: username, password: password };
db.collection("Profile").find(query).toArray(function(err, result) {
if (err) throw err;
console.log(result);
db.close();
if (result.length != 0)
{
console.log("login success");
login_success = 1;
//Setting session variables
req.session.userid = username;
req.session.username= result[0].firstname;
console.log("***********************Login*********************");
console.log("");
console.log("Actual session id at login: "+ req.sessionID);
console.log("Session userid at server set to :"+ req.session.userid);
console.log("Session name at server set to :"+ req.session.username);
//res.sendFile(path.join(SRC_DIR,"home.html"));
// res.status(200).send(req.session);
console.log("Session reload called");
res.redirect('/home');
}
else
{
//**It is for when user come to login page with entering wrong credentials
login_success = 2;
console.log("login failed");
res.redirect('http://localhost:8080');
}
});
});
});
//export this router to use in our server.js
module.exports = router;
home.js
var express = require('express');
var router = express.Router();
var path = require("path");
var SRC_DIR=path.join(__dirname, "../src/views");
var session = require('express-session');
cookie = require('cookie');
var cookieParser = require('cookie-parser');
var sessionStore = new session.MemoryStore();
var handshakeData ={};
router.use(cookieParser());
router.use(session({ cookie: {
maxAge : 24*60*60*1000
},
store: sessionStore,
saveUninitialized: true,
resave: true,
secret: '1234567890QWERT'
}));
router.get('/', function(req, res){
//setting cookie at client side
res.clearCookie("user_id");
res.clearCookie("user_name");
res.cookie('user_id', req.session.userid);
res.cookie('user_name', req.session.username);
// res.status(200).send(req.session);
console.log(" session reload called");
setTimeout(function(){
res.sendFile(path.join(SRC_DIR,"home.html"));
}, 5000);
console.log("***********************Home*********************");
console.log("");
console.log("Actual session id at home: "+ req.sessionID);
console.log("Cookie userid at client set to :"+ req.session.userid);
console.log("Cookie username at client set to :"+ req.session.username);
});
//export this router to use in our server.js
module.exports = router;
home.jsx (client side file)
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {messages: [],socket: io.connect('http://localhost:8080')};
this.send = this.send.bind(this)
}
}
export default Home
Ouput when exicuting "node server.js":
output
In the above output...
1. login page we got two different session ids (before login and after login).I don't know why this is happening
2. While accessing the session variable inside "server.js", in "io.use" function... we again getting old session id, which was set before login.But with this i can't get my session variable. Because i need to pass new session variable in order to access session variable inside sessionStore.get.
Please help. i have been trying this for 3 days.
Thanks in advance.

Persistent sessions with connect-session-sequelize

I am making a website with a login system and I would like the users to be able to stay logged in even after the browser has been closed. Only destroy the session when the user logs out. I have searched online for the solution and came across with the suggestion to use connect-session-sequelize . I read the documentation and put my best effort to make the code work but my lack of experience in this gets in a way.
Problem:
My code does not give me the result of keeping a user logged in after the server restart. My code is:
var express = require('express');
var app = express();
var cookieParser = require('cookie-parser');
var session = require('express-session');
var SequelizeStore = require('connect-session-sequelize')(session.Store);
var pug = require('pug');
var bodyParser = require('body-parser');
var bcrypt = require('bcrypt');
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(express.static('public'));
app.use(cookieParser());
app.set('views', './views');
app.set('view engine', 'pug');
var Sequelize = require('sequelize');
var db = new Sequelize('postgres://'+ process.env.POSTGRES_USER + ':' +
process.env.POSTGRES_PASSWORD + '#localhost/terranova', {
host: 'localhost',
dialect: 'postgres',
storage: './session.postgres',
define: {
timestamps: true
}
});
var sessionStore = new SequelizeStore({
db: db,
checkExpirationInterval: 15 * 60 * 1000,
expiration: 24 * 60 * 60 * 60 * 1000
});
app.use(session({
secret: 'salajhgdusdajss',
store: sessionStore,
resave: false,
saveUninitialized: false,
proxy: true
}));
sessionStore.sync()
var Session = db.define('Session', {
sid: {
type: Sequelize.STRING,
primaryKey: true
},
userId: Sequelize.STRING,
expires: Sequelize.DATE,
data: Sequelize.STRING(50000)
});
var User = db.define('user', {
username: Sequelize.STRING,
password: Sequelize.STRING,
});
function extendDefaultFields(defaults, session) {
return {
data: defaults.data,
expires: defaults.expires,
userId: session.userId
};
}
var store = new SequelizeStore({
db: db,
table: 'Session',
extendDefaultFields: extendDefaultFields
});
Subproblems:
The documentation indicates to add 'var store = new SessionStore' instead of 'var store = new SequelizeStore' but it gives me an error: 'SessionStore is not defined'. Not sure if I'm doing something wrong?
I can see inside 'users' table, but for some reason, I cannot look inside the table of 'Sessions', with 'select * from Sessions;' I get the response of 'relation "sessions" does not exist'. Why is this so?
expiration: 24 * 60 * 60 * 1000 --> default expiry of 24 hours. Does this indicate the time of the session? If yes, what would be the maximum possible time (in case unlimited is impossible)?
Could someone please explain me what do I need to do/add/remove from my code to be able to achieve my goal?
For more info, here is the login page...
app.get('/login', function(req,res) {
res.render('login')
})
app.post('/login', function(req,res) {
var username = req.body.username
var password = req.body.password
User.findOne({
where: {
username: username
}
}).then(function(user) {
if(username.length === 0 || password.length === 0) {
res.render('login', {
message: "Username or password missing"
});
return;
};
if(user == null) {
res.render('login', {
message: "User not in the system, please register"
});
return;
} else {
var hash = user.password
bcrypt.compare(password, hash, function(err, result) {
if (err) {
res.render('login', {
message: 'Invalid email or password, please try again or register'
})
};
if(result === true) {
req.session.user = user;
res.redirect('/home');
}
else {
res.render('login', {
message: "Something went wrong, please try again"
});
};
});
};
});
})
...and here is the home page.
app.get('/home', function(req,res) {
var user = req.session.user
if (user === undefined) {
res.render('login', {
message: 'Please log in to have the access'
});
} else {
res.render('home', {
user: user
});
}
})
Big thanks in advance for helping me!

Session variables are undefined out of the scope it is set to a value in nodejs

I am using nodejs and I am trying to access a session variable in a route which is not the same route where the session variable is defined and set. It keeps telling me that the session variable is not defined!
This is where I set the session variable:
var http = require('http');
var express = require('express');
var bodyParser = require('body-parser');
var mysql = require('mysql');
var urlencodedParser = bodyParser.urlencoded({ extended: false })
var app = express();
var dateFormat = require('dateformat');
var nodemailer = require('nodemailer');
var cookieParser = require('cookie-parser')
var session = require('express-session');
app.use(cookieParser());
app.use(session({
secret: "This_is_a_secret",
resave: false,
}));
app.post('/auth',urlencodedParser,function (req, res) {
conn.query('SELECT * FROM users WHERE user_name="'+req.body.username+'" AND user_pass="'+req.body.password+'"',function(err,res1){
if(err) {
console.log("Error!");
res.send('-2');
}
else{
if(res1.length==0) {
console.log("No matching!");
res.send('-2');
}
else if(res1.length==1){
req.session.username = req.body.username; //This is my session variable
console.log("Successful login with: " + req.session.username); //This works fine
res.send('1');
}
}
});
});
This is the second route where I am trying to access req.session.username:
app.post('/privilage',urlencodedParser,function (req, res) {
console.log("privilage: " + req.session.username); //Here is where I need to check and it says "undefined"
if(!req.session.username){
res.send('-2');
}
else res.send('1');
});
What is wrong exactly??
Thanks for all :)
You don't use store to session. It's means that sessions store in memory and reset on application restart.
app.use(session({
secret: "This_is_a_secret",
resave: false,
store: ...
}));
Be sure that you don't restart application between login and check requests.
Also I recommend to make some changes in your code
conn.query('SELECT * FROM users WHERE user_name="'+req.body.username+'" AND user_pass="'+req.body.password+'"', function(err, qres){
if(err) {
console.log("Error!", err.message);
return res.send('-2'); // Maybe best way is res.status(401).end()?
}
if (qres.length == 0) {
console.log("No matching!");
return res.send('-2');
}
if (qres.length != 1) // unbelievable case, but check it
throw new Error("Smth wrong");
req.session.username = req.body.username;
console.log("Successful login with: " + req.session.username);
res.send('1');
}

Resources