Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modifying user.username in Session With PassportJS

I have a form that allows people to update their profile information, which is populated with data from req.user via PassportJS.

The problem is that whenever I update the value that corresponds to user.username I get the following error message:

TypeError: Cannot read property '_id' of null 

From line 6 in this snippet of code:

passport.deserializeUser(function(id, done) {
  mongo.connect("mongodb://localhost:27017/formulas", function(e, db){
  if (e) {return next(e);}
  var col = db.collection("users");
  col.findOne({"username": id}, function(err, user){
    done(err, {"id": user._id, "username": id, "activeEmail": user.activeEmail, "name": user.name, "password": user.password, "formulas": user.formulas});
    });
  });
});

I'm assuming it's because in serializeUser I'm using user.username to load it into session like so:

passport.serializeUser(function(user, done) {
  done(null, user.username);
});

Does anyone know how to go about getting around this or is it an intractable issue with Passport?

The code I have that does the update generically looks like this:

router.post('/update-profile', function(req, res) {
    var name = req.body.name;
    var username = req.body.username;
    var db = req.db.collection('users');

    db.updateOne({"username": username}, {
      $set: {
          "name": name,
          "username": username,
        }
      }, function(err, r) {
         assert.equal(null, err);
         assert.equal(null, r.matchedCount);
      }
    });
    res.render('profile', {
      user: req.user
    });
  });

UPDATE:

Per comment request, the error message from findOne in serializeUser is null when it's called, so it's not the query that's the problem.

like image 417
Jonathan Bechtel Avatar asked Aug 01 '17 19:08

Jonathan Bechtel


1 Answers

As username is changeable value, you should not use it as session cookie key.

I strongly recommend using user._id instead as it is unchanged value, so that server still "know" the current user even if username has been changed. Check official http://passportjs.org/docs, they are also using id as session cookie key.

Btw, even if you are using username, you should do NULL check for passport.deserializeUser():

col.findOne({"username": id}, function(err, user){
    if (user) {
        done(err, {"id": user._id, "username": id, "activeEmail": user.activeEmail, "name": user.name, "password": user.password, "formulas": user.formulas});
    } else {
        done(new Error('User not found'));
    }
});
like image 165
haotang Avatar answered Oct 04 '22 01:10

haotang