4

Initial question: I'm using passportJS in my backend, and MongoStore as the session store, with a react frontend.

What I'm trying to do is allow the user to have a persistent login session. There's already a cookie that's getting automatically set by express-session called connect.sid. However the session doesn't seem to be persistent because req.user is undefined on subsequent requests using the same cookie that was set on login. req.user keeps returning undefined which means that passport is not verifying the session cookie somehow.

According to passport's docs that shouldn't happen.

Each subsequent request will not contain credentials, but rather the unique cookie that identifies the session. In order to support login sessions, Passport will serialize and deserialize user instances to and from the session.

So what I'm trying to understand is how exactly does passportJS deal with cookies sent by the client?

Can someone help me by explaining the steps that passport takes when it comes to that?

I'm also using passport-local-mongoose plugin in my mongoose model which includes built in authenticate/serialize/deserialize methods used in auth.js below.

Relevant parts of my code for reference:

app.js: (didn't include the full file so it can be clear since it's 100+ lines, if someone suggests it could be an issue of middleware order I'll include the full code)

//session and passport initialization

const sessionStore = new MongoStore({
  mongooseConnection: mongoose.connection,
  collection: "sessions",
});

app.use(
  session({
    secret: process.env.SERVER_SECRET_KEY,
    resave: false,
    saveUninitialized: false, 
    store: sessionStore,
    cookie: {
      path:"/",
      httpOnly: true,
      expires: 9999999999999999
    }
  })
);

app.use(passport.initialize());
app.use(passport.session());

auth.js

const passport = require("passport");
const LocalStrategy = require("passport-local").Strategy;

const config = require("./config");
const User = require("./models/userModel");

passport.use(
  new LocalStrategy({ usernameField: "userName", passwordField: "password" }, User.authenticate())
);

passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());

exports.userLogin = passport.authenticate("local", {
  session: true,
  failureRedirect: '/users/loginfailed'
});

users.js (login request which returns the new cookie if successful)

usersRouter
  .route("/login")
  .post(auth.userLogin, (req, res, next) => {
    console.log(req.user); // returns a valid user on login
    res.statusCode = 200;
    res.setHeader("Content-Type", "application/json");
    res.json({ success: true, message: "Login successful!" });
  });

movies.js (separate request after login, previous cookie included in headers)

moviesRouter
  .route("/top")
  .get((req, res, next) => {
    console.log(req.user); // undefined
    //includes a mongodb query here and a corresponding server response
  })

UPDATE (thanks to this answer): I found the issue, it was as simple as removing the cookie option from the object that was passed to session().

changed to this:

app.use(
  session({
    secret: process.env.SERVER_SECRET_KEY,
    resave: false,
    saveUninitialized: false, 
    store: sessionStore,
  })
);

But I still don't understand why Passport likes to ignore my cookie options. What if I want to use secure or disable httpOnly or anything else I may want to try with my cookies?

ajjsiraj
  • 53
  • 3
  • 7
  • I usually use express-sessions with node and express and passport plus whatever authentication strategy you choose to offer. – Kasey Chang May 22 '20 at 06:59
  • @Kasey that's what I'm using, I'm just trying to understand what happens when the server receives the client cookie, where does it go and how does Passport process it? It's not keeping sessions persistent although passport's docs say it should. – ajjsiraj May 22 '20 at 16:28

0 Answers0