I've been stuck on this for two days. I got it working last night, and this morning I updated some stuff and removed some unnecessary code, which ended up not working. The error persists on the passport serialization, "TypeError: Cannot set properties of undefined (setting 'user')"
app.js
const mongoose = require("mongoose"); //Mongo driver
var session = require('express-session');
const passport = require('passport');
const MongoStore = require('connect-mongo');
var express = require("express");
const bodyParser = require('body-parser'); //For parsing post requests
//Route files
const mainRoutes = require("./routes/main");
const authRoutes = require("./routes/auth");
require("./passport")(passport);
//Express setup
var app = express();
app.set("view engine", "ejs");
app.use(express.static("public"));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.json());
mongoose
.connect
....
//Express Session
app.use(session({
resave: true,
saveUninitialized: false,
secret: 'SECRET',
store: new MongoStore({ mongoUrl: process.env.MONGO_URI, ttl: 12 * 60 * 60 * 1000 })
}));
//Passport Middleware
app.use(passport.initialize());
app.use(passport.session());
app.use(mainRoutes);
app.use(authRoutes);
passport.js
const bcrypt = require("bcrypt");
const localStrategy = require("passport-local").Strategy;
const FacebookStrategy = require("passport-facebook").Strategy;
... Twitter, Google ..
const Users = require("./models/userModel");
module.exports = function (passport) {
passport.serializeUser(function(user, done){
done(null, user._id);
});
passport.deserializeUser(function(id, done){
Users.findById(id, function(err, user){
done(err, user);
});
});
//..Not including local or the other strategies as they all lead to the same thing
passport.use(new FacebookStrategy({
clientID: process.env.FACEBOOK_APP_ID,
clientSecret: process.env.FACEBOOK_APP_SECRET,
callbackURL: "http://localhost:3000/auth/facebook/callback",
// passReqToCallback : true, //Tried with both these two commented lines
// profileFields: ['id', 'emails']
},
function (req, accessToken, refreshToken, profile, done) {
console.log(profile);
Users.findOrCreate({ "platform.id": profile.id, "platform.name": profile.provider, "email": profile.emails[0].value }, function (err, user) {
console.log(user);
return done(null, user);
});
}));
};
routes/auth.js
const passport = require('passport');
const router = require("express").Router();
...
router.get('/auth/facebook', passport.authenticate('facebook'));
router.get('/auth/facebook/callback', passport.authenticate('facebook', {
successRedirect : '/',
failureRedirect: '/' })
);
...
userModel.js
const mongoose = require("mongoose");
const findOrCreate = require('mongoose-findorcreate');
const {usernameGen} = require("../utils/functions");
const userSchema = new mongoose.Schema({
platform: {
name: String,
id: String
},
email: {
type: String
},
username: {
type: String,
min: 4,
max: 20,
default: usernameGen
},
password: {
type: String,
min: 6
},
isAvatarImageSet: {
type: Boolean,
default: false
},
avatarImage: {
type: String,
default: ""
},
authLevel: {
type: String,
enum: ["admin", "moderator", "member", "anon"],
default: "anon"
},
});
userSchema.plugin(findOrCreate);
module.exports = mongoose.model("Users", userSchema);
Sorry for dumping out most of the stuff here, but passportjs's documentation has been driving me crazy. Found similar issues from other people, but the solutions were to downgrade passportJS to a REALLY older version, or wrong stuff initializing at the wrong place, or just wrongly serializing the user.
Console logging the user going into passport.serializeUser(), reveals all the user data correctly along with the user's _id. Any help would be greatly appreciated, and thanks for checking my issue out!