You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

用户序列化失败及Passport登录问题求助

Troubleshooting User Serialization Failures in Passport.js

Hey there, let's break down your two questions and fix that serialization issue step by step!

1. Why does logging user return true instead of the user object?

This is a classic mix-up with what you're passing to Passport's done function. Look at this section of your Local Strategy code:

bcrypt.compare(password, user_obj.password, (err, varifiedUser) => {
  if (err) throw new Error(err);
  else if (varifiedUser) {
    return done(null, varifiedUser); // ← Here's the mistake!
  } else {
    return done(null, false, { message: "Incorrect password!" });
  }
});

The varifiedUser variable from bcrypt.compare() is just a boolean (true/false) that confirms if the password matches—it's not the actual user object. When you pass this boolean to done(), Passport takes that true value and passes it straight to serializeUser, which is why your logs show true instead of a user document.

Quick Fix: Pass the actual user object (user_obj) to done() when authentication succeeds:

else if (varifiedUser) {
  return done(null, user_obj); // Pass the full user object here
}

2. Why pass user.id instead of MongoDB's default user._id in serializeUser?

First, let's clarify: MongoDB uses _id as the default primary key for all documents. If you haven't explicitly added a virtual id field to your Mongoose schema, user.id doesn't exist—you should be using user._id instead.

Looking at your deserializeUser code, there are a couple more critical errors amplifying this confusion:

passport.deserializeUser((user, done) => { // Parameter name is wrong
  usermodel.findById(user.id, (err, id) => { // Querying for a non-existent `user.id`
    if (!err) {
      done(null, user); // Passing the ID back instead of the fetched user
    } else {
      done(err);
    }
  });
});
  • The first parameter to deserializeUser is the ID you passed from serializeUser, not a user object—rename it to id for clarity.
  • You're trying to query by user.id, but if you serialized user._id, you should use that value directly in findById().
  • Finally, you're passing the original ID back instead of the actual user document you fetched from the database.

Corrected serializeUser and deserializeUser:

passport.serializeUser((user, done) => {
  console.log("user object serialize", user);
  done(null, user._id); // Use MongoDB's default _id field
});

passport.deserializeUser((id, done) => {
  usermodel.findById(id, (err, foundUser) => {
    if (err) {
      done(err);
    } else {
      done(null, foundUser); // Pass the fetched user object to done()
    }
  });
});

If you do want to use user.id (a common practice for cleaner API responses), you can add a virtual field to your Mongoose schema to map _id to id:

const userSchema = new mongoose.Schema({
  // Your existing schema fields (email, password, etc.)
});

// Add virtual `id` field that returns a string version of _id
userSchema.virtual('id').get(function() {
  return this._id.toHexString();
});

// Ensure virtual fields are included when converting documents to JSON
userSchema.set('toJSON', { virtuals: true });

const usermodel = mongoose.model('User', userSchema);

With this setup, user.id will work exactly like user._id but as a plain string, which plays nicely with Passport.

Full Corrected Authentication Code

Here's your code with all fixes applied, plus a small improvement to error handling:

passport.use(new passportLocal({ usernameField: 'email' }, (email, password, done) => {
  console.log(email, password);
  usermodel.findOne({ email: email }, (err, user_obj) => {
    console.log("user object get by database", user_obj)
    if (err) return done(err); // Use done() instead of throwing errors (Passport expects this)
    if (!user_obj) {
      return done(null, false, { message: "There is no user with that email." });
    }
    bcrypt.compare(password, user_obj.password, (err, isMatch) => {
      if (err) return done(err);
      if (isMatch) {
        return done(null, user_obj); // Pass the full user object
      } else {
        return done(null, false, { message: "Incorrect password!" });
      }
    });
  });
}));

passport.serializeUser((user, done) => {
  console.log("user object serialize", user);
  done(null, user._id);
});

passport.deserializeUser((id, done) => {
  usermodel.findById(id, (err, foundUser) => {
    done(err, foundUser); // Simplified error handling
  });
});

router.post("/login", passport.authenticate('local', { 
  successRedirect: '/auth/quiz', 
  failureRedirect: '/auth/login' 
}));

内容的提问来源于stack exchange,提问作者Priyanshu Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 12:43:14