I am trying to have multi strategy auth working with Facebook and the Local strategy. The facebook auth is generally working and my db gets updated, but the local strategy gives me the following error:
TypeError: undefined is not a function
at allFailed (/Users/r/Desktop/jb/node_modules/passport/lib/middleware/authenticate.js:111:15)
at attempt (/Users/r/Desktop/jb/node_modules/passport/lib/middleware/authenticate.js:160:28)
at Strategy.strategy.fail (/Users/r/Desktop/jb/node_modules/passport/lib/middleware/authenticate.js:277:9)
at Strategy.authenticate (/Users/r/Desktop/jb/node_modules/passport-local/lib/strategy.js:75:17)
at attempt (/Users/r/Desktop/jb/node_modules/passport/lib/middleware/authenticate.js:341:16)
at authenticate (/Users/r/Desktop/jb/node_modules/passport/lib/middleware/authenticate.js:342:7)
at Layer.handle [as handle_request] (/Users/r/Desktop/jb/node_modules/express/lib/router/layer.js:82:5)
at next (/Users/r/Desktop/jb/node_modules/express/lib/router/route.js:110:13)
at Route.dispatch (/Users/r/Desktop/jb/node_modules/express/lib/router/route.js:91:3)
at Layer.handle [as handle_request] (/Users/r/Desktop/jb/node_modules/express/lib/router/layer.js:82:5)
at /Users/r/Desktop/jb/node_modules/express/lib/router/index.js:267:22
at Function.proto.process_params (/Users/r/Desktop/jb/node_modules/express/lib/router/index.js:321:12)
at next (/Users/r/Desktop/jb/node_modules/express/lib/router/index.js:261:10)
at SessionStrategy.strategy.pass (/Users/r/Desktop/jb/node_modules/passport/lib/middleware/authenticate.js:318:9)
at SessionStrategy.authenticate (/Users/r/Desktop/jb/node_modules/passport/lib/strategies/session.js:67:10)
at attempt (/Users/r/Desktop/jb/node_modules/passport/lib/middleware/authenticate.js:341:16)
here is the code itself:
'use strict';
var passport = require('passport');
var FacebookStrategy = require('passport-facebook').Strategy;
var LocalStrategy = require('passport-local').Strategy;
module.exports = function(app, User) {
app.use(passport.initialize());
// Enable sessions
app.use(passport.session());
passport.use(new LocalStrategy(
function(username, password, done) {
User.findOne({ username: username }, function (err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false); }
if (!user.verifyPassword(password)) { return done(null, false); }
return done(null, user);
});
}
));
passport.use(new FacebookStrategy({
clientID: 1234544646,
clientSecret: "sertysehtrhr345345345234234",
callbackURL: "http://localhost:5000/auth/facebook/callback"
},
function(accesstoken, tokenSecret, profile, done) {
// Could be an existing user or a new user
// profile.username is used as the username
User.findOrCreate({
where: {
username: profile.id,
email: profile.emails[0].value,
displayName: profile.displayName
}
}).spread(function(user) {
return done(null, user);
});
}));
// This just stores the username is an encrypted browser cookie
passport.serializeUser(function(user, done) {
done(null, user.username);
});
// This fetches the user by username retrieved from the
// cookie that was set during serializeUser
passport.deserializeUser(function(uname, done) {
console.log(uname)
User.find({
where: {
username: uname
}
}).then(function(user) {
if (!user) return done(new Error('Invalid user'));
return done(null, user);
});
});
// Redirect the user to facebook for authentication. When complete, Facebook
// will redirect the user back to the application at /auth/facebook/callback
//app.get('/auth/facebook', passport.authenticate('facebook'));
app.get('/auth/facebook',
passport.authenticate('facebook', { scope: ['email']}),
function(req, res){
});
// Facebook will redirect the user to this URL after approval. Finish the
// authentication process by attempting to obtain an access token. If access
// was granted, the user will be logged in. Otherwise, authentication has failed.
app.get('/auth/facebook/callback',
passport.authenticate('facebook', {
failureRedirect: '/login'
}),
function(req, res) {
res.cookie('signIn', 'true');
res.redirect('/');
}
);
app.get('/api/users', function(req, res) {
res.render({
message: req.flash('loginMessage')
});
});
app.post('/api/users',
passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/login',
failureFlash: true
})
);
// This is the middleware that needs to be used for
// protecting APIs that require authorization
return function(req, res, next) {
// if user is authenticated in the session, carry on
if (req.isAuthenticated())
return next();
// if they aren't redirect them to the login page /auth/twitter
res.redirect('/');
};
};
I am doing a post to /api/users. Any idea whats going on?
You have set
failureFlash
true. This requires theconnect-flash
middleware.Express 2.x
had this with itself, while inExpress 3.x
it comes in a separate module. So either set thefailureFlash
option to false or use connect-flash.This is what the Passport docs have to say about this