I've asked a similar question before, but I noticed it was in the Javascript section. I have more specific ideas of what might be going wrong now, as well.
Basically, req.session.passport is empty in my logs. Whenever I start navigating around my site, req.user becomes undefined because the session doesn't have Passport's logged in user anymore.
I would like to know if anyone knows how to solve this? Maybe it's just an error in the configuration of Passport, or the entire Express setup?
App.js:
var express = require("express"),
bodyParser = require("body-parser"),
mongodb = require("mongodb"),
mongoose = require("mongoose"),
uriUtil = require("mongodb-uri"),
morgan = require("morgan"),
session = require("express-session"),
passport = require("passport"),
flash = require("connect-flash"),
ip = "hidden",
port = process.env.PORT || 80
var app = express()
app.disable("x-powered-by")
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
extended: true
}))
app.use(morgan("dev")); // log every request to the console
// required for passport
app.use(session({
secret: "hidden",
key: 'asdasdasd',
cookie: { maxAge: 60000, secure: false },
resave: true,
saveUninitialized: false
})); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session
app.set("view engine", "jade")
app.use(express.static(__dirname + "/views"))
require("./includes/passport")(passport)
require("./includes/subject")
require("./includes/user")
Passport.js:
var LocalStrategy = require("passport-local").Strategy,
User = require("./user"),
bCrypt = require('bcrypt-nodejs')
module.exports = function(passport) {
// used to serialize the user for the session
passport.serializeUser(function(user, done) {
done(null, user._id);
});
// used to deserialize the user
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
// =========================================================================
// LOCAL SIGNUP ============================================================
// =========================================================================
// we are using named strategies since we have one for login and one for signup
// by default, if there was no name, it would just be called "local"
passport.use('signup', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField : "email",
passwordField : "password",
passReqToCallback : true // allows us to pass back the entire request to the callback
},
function(req, email, password, done) {
// asynchronous
// User.findOne wont fire unless data is sent back
process.nextTick(function() {
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
User.findOne({ "email" : email }, function(err, user) {
// if there are any errors, return the error
if (err)
return done(err);
// check to see if theres already a user with that email
if (user) {
return done(null, false, req.flash("message", "Dit e-mail-adres is al bezet"));
} else {
// if there is no user with that email
// create the user
var newUser = new User();
// set the user's local credentials
newUser.email = email;
newUser.password = createHash(password);
newUser.firstname = req.param('firstname');
newUser.lastname = req.param('surname');
newUser.year = parseInt(req.param('year'));
newUser.study = req.param('study');
newUser.courses = req.param('courses');
newUser.phone = req.param('phone');
newUser.availability = req.param('availability');
newUser.description = req.param('descText');
// save the user
newUser.save(function(err) {
if (err)
throw err;
return done(null, newUser);
});
}
});
});
}));
// =========================================================================
// LOCAL LOGIN =============================================================
// =========================================================================
// we are using named strategies since we have one for login and one for signup
// by default, if there was no name, it would just be called 'local'
passport.use("login", new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField : "email",
passwordField : "password",
passReqToCallback : true // allows us to pass back the entire request to the callback
},
function(req, email, password, done) { // callback with email and password from our form
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
User.findOne({ "email" : email }, function(err, user) {
// if there are any errors, return the error before anything else
if (err)
return done(err);
// if no user is found, return the message
if (!user) {
console.log('No user found with email ' + email)
return done(null, false, req.flash('message', 'Gebruiker niet gevonden')); // req.flash is the way to set flashdata using connect-flash
}
if (!isValidPassword(user, password)){
console.log('Incorrect Password');
return done(null, false, req.flash('message', 'Onjuist wachtwoord')); // redirect back to login page
}
// all is well, return successful user
return done(null, user);
});
}));
var isValidPassword = function(user, password){
return bCrypt.compareSync(password, user.password);
}
// Generates hash using bCrypt
var createHash = function(password){
return bCrypt.hashSync(password, bCrypt.genSaltSync(10), null);
}
};
The routes:
api.post("/signup", passport.authenticate("signup", {
successRedirect: "/profile",
failureRedirect: "/",
failureFlash: true
}))
api.post("/login", passport.authenticate("login", {
successRedirect: "/profile",
failureRedirect: "/login"//,
failureFlash: true
}))
router.get("/", function(req, res) {
// serve index.html
res.render("index", {
title: 'Home',
user: req.user,
message: req.flash("message")
})
})
It works on the page that is accessed directly after logging in, which I control as follows:
router.get("/profile", isLoggedIn, function(req, res) {
res.render("profile", {
title: 'Gebruikersprofiel van ' + req.user.firstname + " " + req.user.lastname,
user: req.user // get the user out of session and pass to template
})
})
function isLoggedIn(req, res, next) {
console.log(req.session)
// if user is authenticated in the session, carry on
if (req.isAuthenticated())
return next()
// if they aren't redirect them to the home page
res.redirect("/login")
}
So far, I've tried adding middleware to add req.user to req.session, and doing the same thing in the login POST. Also I've tried changing the order in which I initialize the middleware in app.js. I am using the new express-session version, without CookieParser, as I read that CookieParser is no longer needed.
If anyone can help me in any way, it would be much appreciated! I've been stuck for a while (as have others).
The problem was not anything I did wrong in setting up the session, or Passport in general, but rather in my links. I read somewhere that someone was accidentally working in multiple domains (his platform was apparently multi-server), and that made me look through my links this morning.
Apparently, I was linking to my website with www. prefixed, but the session was initialized where there was no www. in front of the URL. I saw this in the cookies. The solution was, therefore, to link through the website consistently, either having www. prefixed everywhere or nowhere.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.