Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

404 not found error setting up Passport in Express 4

I am really having troubles getting passport to work in my Node.js application. I tried reordering my requirements in my app.js but I still can't get it to work. This is the error I'm getting:

Not Found

404

Error: Not Found
    at /home/salma/Desktop/my-project/app.js:56:13
    at Layer.handle [as handle_request] (/home/salma/Desktop/my-project/node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (/home/salma/Desktop/my-project/node_modules/express/lib/router/index.js:312:13)
    at /home/salma/Desktop/my-project/node_modules/express/lib/router/index.js:280:7
    at Function.process_params (/home/salma/Desktop/my-project/node_modules/express/lib/router/index.js:330:12)
    at next (/home/salma/Desktop/my-project/node_modules/express/lib/router/index.js:271:10)
    at /home/salma/Desktop/my-project/node_modules/express/lib/router/index.js:618:15
    at next (/home/salma/Desktop/my-project/node_modules/express/lib/router/index.js:256:14)
    at next (/home/salma/Desktop/my-project/node_modules/express/lib/router/route.js:121:14)
    at complete (/home/salma/Desktop/my-project/node_modules/passport/lib/middleware/authenticate.js:250:13)
    at /home/salma/Desktop/my-project/node_modules/passport/lib/middleware/authenticate.js:257:15
    at pass (/home/salma/Desktop/my-project/node_modules/passport/lib/authenticator.js:421:14)
    at Authenticator.transformAuthInfo (/home/salma/Desktop/my-project/node_modules/passport/lib/authenticator.js:443:5)
    at /home/salma/Desktop/my-project/node_modules/passport/lib/middleware/authenticate.js:254:22
    at /home/salma/Desktop/my-project/node_modules/passport/lib/http/request.js:60:7
    at pass (/home/salma/Desktop/my-project/node_modules/passport/lib/authenticator.js:267:43)
    at serialized (/home/salma/Desktop/my-project/node_modules/passport/lib/authenticator.js:276:7)
    at /home/salma/Desktop/my-project/config/passport.js:9:9
    at pass (/home/salma/Desktop/my-project/node_modules/passport/lib/authenticator.js:284:9)
    at Authenticator.serializeUser (/home/salma/Desktop/my-project/node_modules/passport/lib/authenticator.js:289:5)
    at IncomingMessage.req.login.req.logIn (/home/salma/Desktop/my-project/node_modules/passport/lib/http/request.js:50:29)
    at Strategy.strategy.success (/home/salma/Desktop/my-project/node_modules/passport/lib/middleware/authenticate.js:235:13)

Here's my code:

app.js:

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var flash    = require('connect-flash');
var passport = require('passport');
var session  = require('express-session');
var routes   = require('./routes/index');
var userRoutes   = require('./routes/user');
var adminRoutes   = require('./routes/admin');
var config = require('./config/index.js');
var MongoStore = require('connect-mongo')(session);

var app = express();

mongoose.Promise = global.Promise;
var db = mongoose.connect(config.dbUrl, config.dbOpts);

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

var store = new MongoStore({
  mongooseConnection: db.connection
});

app.use(session({
  secret: config.sessionSecret,
  store: store,
  resave: true,
  saveUninitialized: true
}));

app.use(flash());
app.use(passport.initialize());
app.use(passport.session());
require('./config/passport')(passport);

app.use('/', routes);
app.use('/', userRoutes);
app.use('/admin', adminRoutes);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

mongoose.connection.on('open', function(){
  mongoose.connection.db.listCollections(function(error, names) {
    if (error) {
      throw new Error(error);
    } else {
      names.map(function(name) {
        console.log('found collection %s', name);
      });
    }
  });
});

mongoose.connection.on('error', function(error){
  throw new Error(error);
});

module.exports = app;

and this is my log in route:

routes/user.js:

var express = require('express');
var User = require('../controllers/user');
var passport = require('passport');
var router = express.Router();

router.get('/', function(req, res, next) {
    res.send('respond with a resource');
});

router.post('/login', passport.authenticate('local',
  { successFlash: 'Success!',
    failureFlash : 'Login failed' }));

and this is the file where I handle my passport authentication strategies:

config/passport.js:

var LocalStrategy = require('passport-local').Strategy;
var User = require('../models/user').model;
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);
        });
    });
    passport.use('local', new LocalStrategy({
        usernameField : 'email',
        passwordField : 'password',
        passReqToCallback : true
    },
    function(req, email, password, done) {
        User.findOne({ email :  email }, function(err, user) {
            if (err) return done(err);
            if (!user)
                return done(null, false, req.flash('loginMessage', 'This email does not exist.'));
            if (!user.validPassword)
                return done(null, false, req.flash('loginMessage', 'Oops! The password entered is incorrect.'));
            return done(null, user);
        });
    }));
    passport.use(new FacebookStrategy({
        clientID: configAuth.facebookAuth.clientID,
        clientSecret: configAuth.facebookAuth.clientSecret,
        callbackURL: configAuth.facebookAuth.callbackURL,
        profileFields: ["emails", "displayName", "name"]
    }
}

I have tried other routes in the same route file to make sure the routes are seen by app.js and they work fine. Only this one doesn't. Can someone please tell what I'm doing wrong?

like image 646
SalmaFG Avatar asked Mar 11 '23 08:03

SalmaFG


1 Answers

The problem was in the route options successFlash and failureFlash. The passport.authenticate() function was expecting different options that must be used exactly that way otherwise they don't work. So when I replaced the options to match the documentation exactly as such:

app.post('/login',
  passport.authenticate('local', { successRedirect: '/',
                                   failureRedirect: '/login',
                                   failureFlash: true })
);

or

 passport.authenticate('local', function(err, user, info) {
            if (err) return res.status(500).send();
            if (!user) return res.status(400).json({error:info.message});
            req.logIn(user, function(err) {
                if (err) return next(err);
                return res.status(200).json(info.message);
            });
        })(req, res, next);

it worked. There are also other ways to call the function, they are listed in the documentation here: http://passportjs.org/docs/authenticate

like image 72
SalmaFG Avatar answered Mar 23 '23 13:03

SalmaFG