Express session getting cleared between routes - node.js

I have below two routes in which I have used express-session to manage user session.
app.post('/login',function(req,res){
//all variables defined here
if(usernm&&passwd){
connection.query("select * from session where username=?;",[usernm],function(err,result){
if(err) throw err;
else if(result.length!=0){
res.send("Already signed in with username "+usernm);
}
else{
connection.query("select * from signup where username=? and passwd=?;",credentials, function(err1, result){
if(err1) throw err1;
if(result.length!=0)
{
req.session.loggedin=true;
req.session.username=usernm;
var sql1="insert into session values('"+usernm+"','"+req.sessionID+"');";
connection.query(sql1,function(err, result){
if(err) throw err;
else{
console.log(req.sessionID);
res.send('Logged in successfully with username '+req.session.username);
}
});
}
else{
obj={'status':'error','message':'Incorrect Username and/or Password'};
obj=JSON.stringify(obj);
res.send(obj);
}
});
}
});
}
});
app.get('/logout',(req,res)=>{
var sessionId=req.sessionID;
var username=req.session.username;
console.log(sessionId,username);
req.session.loggedin=false;
req.session.username=null;
req.session.destroy();
connection.query("Delete from session where sessionID=? or username=?;",[sessionId,username],function(err,result){
if(err) throw err;
else{
res.send("User signed out successfully!");
}
});
});
I am using curl to test my api endpoints. So, the problem is that when I send a post http request to login, I get a sessionID on console. But when I hit logout using curl, the sessionID printed here is different from the one printed in login route, which means the sessionID gets changed in between the routes.
Also, the console.log in logout prints req.session.username as undefined, which it shouldn't do.
As far as I know, this problem relates to session data getting cleared between two page requests.
I wonder why it is happening. Please help me to find the reason of above behaviour so that I can go ahead with my application.
Thank You!

Related

Connecting a different user using mongoClient connexion pool

I 'm using a MongoClient connexion pool at the top of my app.js node.js back end, it works well:
var db;
MongoClient.connect("mongodb://localhost:27017", function(err, client) {
if (err) throw err;
db = client.db('myDb');
// Start the application after the database connection is ready
app.listen(3000);
console.log("Listening on port 3000");
});
app.post('/getEvaluations', function(req, res) {
db.collection('evaluations').find().toArray(function(err, docs) {
if (err) throw err;
res.send(docs);
});
})
I want to build a html form, for getting the login password, but how can I change the MongoClient connexion with the new login password afterwards ?
For example, as long as John logs in, he needs to have READ rights to be able to call the getEvaluations web service.
Do I have to always make the connexion with no user , then only check the user session inside each of the web services ?
Or Is it possible to change the pool connexion , each time a mongoDb user logs in ( he might only have READ rights)?
Something like this ?
MongoClient.connect("mongodb://john:passwd#localhost:27017", function(err, client) {
if (err) throw err;
db = client.db('myDb');
// Start the application after the database connection is ready
app.listen(3000);
console.log("Listening on port 3000");
});
For example, let's say "John" with the password "passwd" wants to log in, how could I do ? Is there any standard code somewhere using a connexion pool ?
I also use express-session but dont understand how to use it with the connexion pool.
I can't find a mongoDb auth code using the connexion pool. There are some moogoose examples but, it is not the same .
This is the idea I've got :
The user logs in via HTTP, then if the login is ok, so a session is created, but how could i check afterwards if the user only has READ rights during all of his session ?
This is a pseudo code, from a moongoose example, but this is not what i need, i'm using mongoClient.
app.get('/getAuth', function(req, res) {
var email = req.param('email');
var password = req.param('password');
//authenticate input against database
UserSchema.statics.authenticate = function (email, password, callback) {
User.findOne({ email: email })
.exec(function (err, user) {
if (err) {
return callback(err)
} else if (!user) {
var err = new Error('User not found.');
err.status = 401;
return callback(err);
}
bcrypt.compare(password, user.password, function (err, result) {
if (result === true) {
return callback(null, user);
} else {
return callback();
}
})
});
}
})
If somebody has an example code, i would really appreciate it, I don't use moogoose , but mongoClient Thank you.
or maybe, this auth web service would be better :
app.get('/getAuth', function(req, res) {
var user = req.param('user');
var password = req.param('password');
db.authenticate(user, password, function(err, res) {
// callback
});
})
but then, what should I do with the connexion pool ? How could I reload it ?
I can't understand how to do.
EDIT 1: This is what I got for now : I've built a getAuth web service, with a pool connexion starting inside of it, is it the right way to do ?
var db;
app.get('/getAuth', function(req, res) {
var user = "jose";
var password = "passwd";
MongoClient.connect("mongodb://"+user+":"+password+"#localhost:27017", function(err, client) {
if (err) {console.log(err)}
else{
db = client.db('myDb');
// Start the application after the database connection is ready
console.log("correct log in");
}
});
})
how could I use a session now?
EDIT 2 : Seems to be working code with express-session using this doc :
https://codeforgeek.com/manage-session-using-node-js-express-4/
//use sessions for tracking logins
app.use(session({secret: 'ssshhhhh',saveUninitialized: true,resave: true}));
sess ={};
// ---------------------------------------------------------------------AUTH USER
app.get('/getAuth', function(req, res) {
var user = "jose";
var password = "passwd";
MongoClient.connect("mongodb://"+user+":"+password+"#localhost:27017", function(err, client) {
if (err) {console.log(err)}
else{
db = client.db('myDb');
sess = req.session;
/*
* Here we have assign the 'session' to 'sess'.
* Now we can create any number of session variable we want.
* in PHP we do as $_SESSION['var name'].
* Here we do like this.
*/
sess.email = "jose.golo#gmail.com"; // equivalent to $_SESSION['email'] in PHP.
sess.username = "jose"; // equivalent to $_SESSION['username'] in PHP.
res.end('done');
}
});
})
Then, in my getEvaluations web service, i 'm checking if sess contains an email, otherwize, it means that he's not logged in, so he can't access the evaluations node.js web service :
app.post('/getEvaluations', function(req, res) {
if (!sess.hasOwnProperty("email") ){
console.log('not logged in ');
}else{
db.collection('evaluations').find().toArray(function(err, docs) {
if (err) throw err;
res.send(docs);
});
}
})
If you have a better solution, please let me know . This app is front end Ionic 1 app .
Question :
Is it a normal behavior :
I get authenticated inside of firefox, so i can access my evaluations.
Now, I go to chrome, on the same computer , i don't have to authenticate to view the evaluations ?
Is it because it is a user Id based session ?
This is how I would do it:
Let the user log in via a HTTP form using the POST method.
Try and find the user's document inside your mongo database (eg. by username). This will result in a user object containing your user's credentials and whatever rights he/she has.
Compare the credentials with the input provided by the log-in form (which is contained within the request object's body).
If the given input and previously stored credentials are equal to each other you can create a session and assign the user object to it.
Check if there's a session object inside the request when the user navigates to '/getEvaluations'. This session object will contain user object of the currently logged in user.
Respond with your Evaluations object if and only if the user has the appropriate
rights.
You could try out authentication middleware like Passport.js. These will handle the sessions and its user data object for you. Here's an example using the local strategy: https://github.com/passport/express-4.x-local-example

Can I use res.redirect and res.send simultaneously in Node.js?

I want to print user's info on the landing page after they get logged in. I am using res.redirect to redirect to landing page i.e index1.html after a user get successfully logged in.
Now I want to get user info. Here is my node.js code:
app.post('/login-feedback', function (req, res) {
dbConn.then(function(db) {
delete req.body._id; // for safety reasons
var dd = db.db("customermanagement");
dd.collection('admin').findOne({username: req.body.username, password: req.body.password}, function(err, user){
if(err) {
console.log(err);
}
else if(user){
req.session.user = user;
console.log( req.session.user.username);
res.status(200);
res.redirect('/index1.html');
}
else {
res.redirect('/login1.html');
}
});
});
});
I would love if you will tell me explicitly everything step by step.
If you want to send data to a static file, like an html file, you should use res.render :
res.render('/login1.html', {user: req.session.user.username})

Preventing shared session with usergrid authentication

I have a node site using Usergrid as the backend. I have created a login form screen, however when one user logs in it then shows that user being logged in to all other users who are on the site. If someone else logs in then it will overwrite the previously logged in user. How can I prevent the authenticated session from being shared across all users? I want each user to have their own authenticated session while browsing the site.
Login Code:
app.post("/login", function(req, res) {
if (client.isLoggedIn()) {
console.log("already logged in");
res.send({"status": "success"});
} else {
client.login(req.body.username, req.body.password, function(err) {
logger.debug("After Log In");
if (err) {
logger.error('Login Failed');
logger.error(err);
} else {
logger.debug(client.token);
client.authType = Usergrid.AUTH_APP_USER;
var options = {
method: 'GET',
endpoint: 'users/me'
};
client.request(options, function(err,data) {
if (err) {
console.log(err);
} else {
req.session['current_user'] = data.entities[0];
console.log(data);
console.log("SESSION");
console.log(req.session);
}
res.send({"status": "success"});
});
}
});
}
});
I think the problem is that you are using one instance of the Usergrid.Client object to serve many users. Instead, you should do what Usergrid does: when a user logs in, you give them the Usergrid access_token. You could send it back in a cookie, or in JSON data or whatever you choose.
Then you would expect subsequent HTTP request from the user to include the access_token in the URL or in a cookie, or whatever. On each request you create a new instance of the Usergrid.Client and pass in the token from the user, e.g.
var client = new Usergrid.Client({'token':'abcd5764adf...');

Passport deserialize function is removing user from the session

To be frank, I just started learning passport today. I feel I understand some of how passport is working, but I'm still trying to familiarize myself. My problem here (I think) is that my user is getting removed from the session, which is preventing me from reaching my authenticated routes. I console.logged the user id in the deserialize function to check if it was getting stored in the session, and it is ...
//serialize user into the session
passport.serializeUser(function(user,done){
done(null,user.id);
});
//deserialize the user from the session
passport.deserializeUser(function(id,done){
console.log('user id is: ' + id); //works and logs user id
User.findById(id, function(err,user){
done(err,user);
});
});
Here are my routes and passport middleware ...
app.post('/login', function(req,res,next){
passport.authenticate('local-login', function(err,user,info){
if(err){
console.log("we have an internal error!");
return next(err);
}
if(!user){
return res.send({success:false, message:'failed to login!'});
}else{
req.login(user, function(err){
if(err){
return next(err);
}
return res.send({ success : true, message : 'authentication succeeded' });
});
}
})(req,res,next);
});
//route middleware to make sure that a user is logged in
function isLoggedIn(req,res,next){
//if the user is authenticated in the session, carry on
if(req.isAuthenticated()){
next();
}
//if they are not authenticated in the session, redirect them to the home page
res.redirect('/');
}
Any help, insights, advice is greatly appreciated; thanks!
It's because you're always redirecting the user to the index page in your isLoggedIn middleware. Need to use return:
function isLoggedIn(req,res,next){
if(req.isAuthenticated()){
next();
// STOPS further execution of this function and prevents redirecting the user
return;
}
res.redirect('/');
}
Keep in mind that it's just JavaScript - no framework does any changes - Express, Passport, even Promises are pure JS and they don't modify the way the virtual machine works. GL!
p.s.
If things go wrong, especially in the beginning, I recommend using if-else statement. You wouldn't have problems this way:
if (req.isAuthenticated()) {
next();
} else {
res.redirect('/');
}

sails session writing bug

I'm using sails 0.10.4 and stumbled with one pretty annoying bug. When user logs in I write his data into the req.session.user then in policies I can retrieve his data such as his role, password etc. But the req.session.user becomes undefined when I go out of the login action. Do you have any ideas how to handle this? Here's the code:
api/controllers/User.js :
module.exports = {
login: function (req, res) {
Users.findOneByEmail(req.param('email'))
.exec(function (err, user) {
if ((err) || (!user)) {
res.send({
error: 'User not found'
});
return;
}
if (!passwordHash.verify(req.param('password'), user.password)) {
res.send({
error: 'Incorrect passwpord'
});
return;
}
req.session.user = user;//I write user into the session
res.send({
user: user
});
});
}
}
api/policies/isLoggedIn.js
module.exports = function (req, res, next) {
if (req.headers.authentication) {
var credentials = JSON.parse(req.headers.authentication);
if(req.session.user.login === credentials.login)//User doesn't exist in session
return next();
}
}
In a testing environment , this issue can happen when testing with Supertest and not defining an agent
var agent = request.agent(app);
agent.post('/api/login',{email:'foo#bar.com',password:'foobar})
.end(function(err,res){...; done();});
It is the correct way to work with sessions, simply using request.post would not work as it would reinit the session variable as soon as the response is sent, even if we are chaining requests inside the same test.
Learnt it the hard way, so I hope it can help some lost developper.

Resources