Daniel
Daniel

Reputation: 23

Node + Passport - multiple users

When trying to implement the example code from the passport guide, I'm running into an issue where the most recently logged in user "replaces" all others. For example:

user1 logs in and leaves a note as user1
user2 logs in
now when user1 leaves a note, it's posted as user2

Do the user sessions need to be stored in a database with something like connect-mongo or does passport keep track of individual sessions? It seems like the API calls are always getting the req.user for the most recent user, regardless of which user makes it.

A similar question had a problem with the serializer. I'm not sure where my problem lies so I'll just post it all.

// Express setup
var http = require('http');
var express = require('express');
var app = express();
var signedIn = false;


// Mongoose setup
var mongoose = require('mongoose');
mongoose.connect('');

var UserSchema = mongoose.Schema({
    username: String,
    password: String
});

var NoteSchema = mongoose.Schema({
    text: String,
    user: String
});

// Used for password authorization
UserSchema.methods.validPassword = function (pwd) {
    return (this.password === pwd);
};

var Users = mongoose.model('Users', UserSchema);
var Notes = mongoose.model('Notes', NoteSchema);


// Passport setup
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;


// Passport Serialize
passport.serializeUser(function (user, done) {
    done (null, user.id);
});

passport.deserializeUser(function (id, done) {
    Users.findById(id, function (err, user) {
        done (err, user);
    });
});

// Use Local Strategy
passport.use(new LocalStrategy(
    function(username, password, done) {
        Users.findOne({ username: username }, function (err, user) {
            if (err) { 
                return done(err); }
            if (!user) {
                return done(null, false, {message: 'Incorrect username' });
            }
            if (!user.validPassword(password)) {
                return done(null, false, { message: 'Incorrect password' });
            }
            console.log(user.username + " is signed in");
            return done(null, user);
        });
        }
    ));

// App configuration

app.configure(function () {

    app.set('port', process.env.PORT || 5000);
    app.set('views', __dirname + '/views');
    app.set('view engine', 'jade');

    app.use(express.static(__dirname + '/public'));

    app.use(express.cookieParser());
    app.use(express.bodyParser());
    app.use(express.methodOverride());

    app.use(express.session({ secret: 'keyboard cat' }));
    app.use(passport.initialize());
    app.use(passport.session());
    app.use(app.router);
})


// Passport Authentication
app.post('/login',
  passport.authenticate('local', { successRedirect: '/notes',
                                   failureRedirect: '/login',
                                   /*failureFlash: true*/ })
);

// API
// Notes
app.get('/api/notes', function (req, res) {
    Notes.find({}, function (err, note) {
        if (err) {
            res.send(err);
        }

        res.json(note);
    })
})

app.post('/api/notes', function (req, res) {
    Notes.create({
        text : req.body.text,
        user : req.user.username,
        done : false

    }, function (err, note) {
        if (err) {
            res.send(err);
        }

        Notes.find(function (err, note) {
            if (err) {
                res.send(err);
            }

            res.json(note);
        })
    })
})

app.delete('/api/notes/:note_id', function (req, res) {
    Notes.remove({ _id : req.params.note_id },
        function (err, req) {
            if (err) {
                res.send(err);
            }

        Notes.find(function (err, note) {
            if (err) {
                res.send(err);
            }

            res.json(note);
        });
    });
});

// Users
// Create New User
app.post('/api/users', function (req, res, next) {
    Users.create({
        username : req.body.username,
        password : req.body.password,
        done : false
    }, function (err, user) {
        if (err) {
            res.send(err);
        } else {
            res.redirect('/login');
        }
    });
});


// Routes

app.get('/', function (req, res) {
    res.render('login');
});

app.get('/login', function (req, res) {
    res.render('login');
})

app.get('/newuser', function (req, res) {
    res.render('newuser');
})

app.get('/notes', function (req, res) {
    if (req.user != null) {
        console.log(req.user);
        res.render('index',  { 'userName' : req.user.username });
    } else {
        res.send("Not signed in!")
    }
});

// HTTP Server

http.createServer(app).listen(app.get('port'), function() {
    console.log("Express server listening on: " + app.get('port'));
})

Upvotes: 2

Views: 3300

Answers (1)

robertklep
robertklep

Reputation: 203304

I can think of several reasons why this might happen:

  • when you (mistakenly) create a global variable to hold some form of state information, like your suspicious looking signedIn variable (you don't seem to be doing that in the posted code though);
  • using app.locals where you meant to be using res.locals (you're also not doing that, but still worth a mention);
  • you're logging in as a second user from a different tab/window from the same browser; sessions are shared across tabs/windows, so when you log in as UserA from one tab, and subsequently log in as UserB from another, you can't perform actions as UserA anymore before that session was overwritten by the UserB session; try logging in as UserB from a different browser;

Upvotes: 3

Related Questions