node.jsmongoosepassport.jsmongoose-plugins

Passport-Local-Mongoose – When I Update A Record's Username, I'm Logged Out, Why?


I'm using the MEAN stack with passport and the Passport-Local-Mongoose plugin. However, whenever I update a User record's username, I am logged out of my current session. What is the correct way to update a username with Passport-Local-Mongoose?

// Update User -- Tied to Usernames or will log out
exports.update = function(req, res) {
    user     = req.user;
    user     = _.extend(user, req.body);
    user.save(function(err, user) {
                if(err) { 
                    console.log(err); 
                    // Error handling for uniqueness violations
                    if (err.code === 11001) {
                        if (err.err.indexOf("email") != -1) {
                            return next(new Error("Email Address Already In Use"));
                        } else if (err.err.indexOf("username") != -1) {
                            return next(new Error("Username Already In Use"));
                        }
                    }
                };
     });
};

Solution

  • The reason for this behavior is the serialize/deserialize implementation shipped with passport-local-mongoose:

    schema.statics.serializeUser = function() {
        return function(user, cb) {
            cb(null, user.get(options.usernameField));
        }
    };
    
    schema.statics.deserializeUser = function() {
        var self = this;
    
        return function(username, cb) {
            self.findByUsername(username, cb);
        }
    };
    

    This implementation uses the username field for serialization and deserialization. As a consequence a change to the username will fail if the username value changed. You can prevent this behavior by using a custom serialization/deserialization strategy like this:

    schema.statics.serializeUser = function() {
        return function(user, cb) {
            cb(null, user.id);
        }
    };
    
    schema.statics.deserializeUser = function() {
        var self = this;
    
        return function(id, cb) {
            self.findOne(id, cb);
        }
    };