Search code examples
expressmongoosepassport-localpassport.jspassport-facebook

facebook passport /local passport conflict - Cannot log in with facebook


I've been trying to make a login with facebook and passport.js. My local login with passport worked just fine but together they are giving me trouble. I'm working with express, mongoose , passport and passport-facebook.
I've tried a number of things to fix it (so many that I forgot most of them) I'm just very lost now
I keep getting this error in my shell:

 GET /auth/facebook 302 4.876 ms - 0
{ _id: 5918a12f6ab8492354a3098c,
  facebook:
   { email: '[email protected]',
     name: 'John',
     token: 'EAABhTCea34sBAMkmOVWU0G62WUc3aNihjtWOdJDSD0XS9NwPPBXZChCTXEmeYe8xp0P5vT8WY0ZBaDwKUWojB96Bz661D9ZCZBxSKx8tfZBBmD3HycoqgsJxZAQykp358xJxoCU1TgUOViZB9JVzmP935r5bFQCoLOoEeZCTzEinvxMO8dqo8DzX',
     id: '10155442104714916' } }
(node:9044) DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html
events.js:165
      throw err;
      ^

Error: Uncaught, unspecified "error" event. (null)
    at Function.emit (events.js:163:17)
    at E:\Documenten\GitHub\webtech2-demoordie\node_modules\mongoose\lib\model.js:3739:13
    at E:\Documenten\GitHub\webtech2-demoordie\node_modules\mongoose\lib\services\model\applyHooks.js:146:20
    at _combinedTickCallback (internal/process/next_tick.js:73:7)
    at process._tickCallback (internal/process/next_tick.js:104:9) 

I've tried several things to fix it but can't put my finger on what the trouble is . Any help is much appreciated , when I close my connection and reconnect my user is in the mongo database but that's not how it should work.

My routes in index.js

var express = require('express');
var router = express.Router();
var passport = require('passport');
var expressvalidator = require('express-validator');
var mongoose = require('mongoose');
var schema = mongoose.Schema;

var users = require('../models/users');
//mongoose.connect('localhost:27017/DemoOrDIe');



/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index.pug', { title: 'Demo Or Die' });
});

router.get('/login',function(req, res, next) {
    res.render('login.pug', {message : req.flash('loginMessage') });
});

router.get('/signup', function(req, res) {
    res.render('signup.pug', { message: req.flash('signupMessage')/*,success: req.session.success, errors: req.session.errors */});
});

router.get('/profile', /*isLoggedIn,*/ function(req, res) {
    res.render('profile.pug', { user: req.user });
});

router.get('/logout', function(req, res) {
    req.logout();
    res.redirect('/');
});

router.post('/signup', passport.authenticate('local-signup', {
    successRedirect : '/profile', // redirect to the secure profile section
    failureRedirect : '/signup', // redirect back to the signup page if there is an error
    failureFlash : true
}));

/*router.post('/signup',function(req,res){
    var newUser = new users({
        name: req.body.name,
        email: req.body.email,
        password: req.body.password
    });
    newUser.save(function (err,error,users) {
        req.checkBody("email", "Enter a valid email address.").isEmail();
        req.checkBody("email", "You must enter an email").notEmpty();
        req.checkBody("name","you must enter a name.").notEmpty();
        req.checkBody("password", "You must enter a password").notEmpty();

        var errors = req.validationErrors();
        if (errors) {
            res.render('signup', { errors: errors });
            return;
        } else {
            res.send(users);
        }

    });
});*/

router.post('/login', passport.authenticate(['local-login'], {
    successRedirect: '/profile',
    failureRedirect: '/login',
    failureFlash : true
}));

// FACEBOOK ROUTES

// route for facebook authentication and login
router.get('/auth/facebook', passport.authenticate(['facebook'], { scope : ['email'] }));

// handle the callback after facebook has authenticated the user
router.get('/auth/facebook/callback',
    passport.authenticate('facebook', {
        successRedirect : '/profile',
        failureRedirect : '/'
    }));


module.exports = router;


function isLoggedIn(req, res, next) {
    if (req.isAuthenticated())
        return next();
    res.redirect('/');
}

My Model

var mongoose = require('mongoose');
var expressvalidator = require('express-validator');
var bcrypt   = require('bcrypt-nodejs');

var userSchema = mongoose.Schema({
    local:{
        email: String,


       /* name: { type: String,
        required: true
        },*/

        password: String


    },

    facebook         : {
        id           :String,
        token        : String,
        email        : String,
        name         : String
    }

}, {
    collection: 'DemoOrDie'
});

// generating a hash
userSchema.methods.generateHash = function(password) {
    return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
};

// checking if password is valid
userSchema.methods.validPassword = function(password) {
    return bcrypt.compareSync(password, this.local.password);
};

module.exports = mongoose.model('User', userSchema);

My passport.js

var LocalStrategy = require('passport-local').Strategy;
var User = require('../models/users.js');

var FacebookStrategy = require('passport-facebook').Strategy;

// load the auth variables
var configAuth = require('./auth');

module.exports = function(passport) {
    passport.serializeUser(function(user, done) {
        done(null, user.id);
    });
    passport.deserializeUser(function(id, done) {
        User.findById(id, function(err, user) {
            done(err, user);
        });
    });

    // FACEBOOK



    passport.use('facebook' ,new FacebookStrategy({

            // pull in our app id and secret from our auth.js file
           clientID        : configAuth.facebookAuth.clientID,
           clientSecret    : configAuth.facebookAuth.clientSecret,
           callbackURL     : configAuth.facebookAuth.callbackURL,
           profileFields: ["id","emails", "displayName"]
        },

        // facebook will send back the token and profile
        function(token, refreshToken, profile, done) {

            // asynchronous
            process.nextTick(function() {

                // find the user in the database based on their facebook id
                User.findOne({ 'facebook.id' : profile.id }, function(err, user) {

                    // if there is an error, stop everything and return that
                    // ie an error connecting to the database
                    if (err)
                        return done(err);

                    // if the user is found, then log them in
                    if (user) {
                        return done(null, user); // user found, return that user
                    } else {
                        // if there is no user found with that facebook id, create them
                        var newUser = new User();

                        // set all of the facebook information in our user model
                        newUser.facebook.id    = profile.id; // set the users facebook id
                        newUser.facebook.token = token; // we will save the token that facebook provides to the user
                        newUser.facebook.name  = profile.displayName; // look at the passport user profile to see how names are returned
                        newUser.facebook.email = profile.emails[0].value; // facebook can return multiple emails so we'll take the first
                        console.log(newUser);
                        // save our user to the database
                        newUser.save(function(err) {
                            if (err)
                                console.log(err);
                                throw err;

                            // if successful, return the new user
                            return done(null, newUser);
                        });
                    }

                });
            });

        }));

    //LOCAL

    passport.use('local-signup', new LocalStrategy({
            usernameField: 'email',
            passwordField: 'password',
            passReqToCallback: true
        },
        function(req, email, password, done) {
            process.nextTick(function() {
                User.findOne({ 'local.email':  email }, function(err, user) {
                    if (err)
                        return done(err);
                    if (user) {
                        return done(null, false,req.flash('signupMessage', 'That email is already taken.'));
                    } else {
                        var newUser = new User();
                        newUser.local.email = email;
                        newUser.local.password = newUser.generateHash(password);
                        newUser.save(function(err) {
                            if (err)
                                throw err;
                            return done(null, newUser);
                        });
                    }
                });
            });
        }));

    passport.use('local-login', new LocalStrategy({
            usernameField: 'email',
            passwordField: 'password',
            passReqToCallback: true
        },
        function(req, email, password, done) {
            User.findOne({ 'local.email':  email }, function(err, user) {
                if (err)
                    return done(err);
                if (!user)
                    return done(null, false,req.flash( 'loginMessage', 'No user found.'));
                if (!user.validPassword(password))
                    return done(null, false, req.flash('loginMessage', 'Wrong password.'));
                return done(null, user);
            });
        }));
};


Solution

  • When you trying to save the New user in the Facebook strategy you are always throwing an error.

        newUser.save(function(err, user){
    If(err) {
    console.log(err)
    throw err
    // return done (err)
    }
    return done(null, user)
    })
    

    Seems to be Just the '{}'. You forgot.

    Hope It help you.