pyprism
pyprism

Reputation: 3008

passport js local authentication using sequelize

I am trying to use passport local auth with sequelize . When I submit login form, the request/respond cycle never end and there is no error message in the terminal .

Here are all of my codes:

app.js

var Sequelize = require('sequelize'),
    express = require('express'),
    bodyParser = require('body-parser'),
    cookieParser = require('cookie-parser'),
    passport = require('passport'),
    LocalStrategy = require('passport-local').Strategy,
    User = require('./models/users');
    ........ and other imports.....

    //route import , model  injection
    var auth = require('./routes/auth')(User);

    .......................
app.use(session({
    store: new RedisStore(),
    secret: 'keyboard cat',
    resave: false,
    saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());

passport.serializeUser(function(user, done) {
    console.log(user);
    done(null, user.id);
});

passport.deserializeUser(function(id, done) {
    User.findById(id).then(function(user){
        done(null, user);
    }).catch(function(e){
        done(e, false);
    });
});

passport.use(new LocalStrategy(
    function(username, password, done) {
       User.findOne({where: {username: username}}).then(function(err, user) {
           if (err) { return done(err); }
           if (!user) {
               console.log('Incorrect username.');
               return done(null, false, { message: 'Incorrect username.' });
           } else if (password != user.password) {
               console.log('Incorrect password');
               return done(null, false, { message: 'Incorrect password.' });
           } else {
               console.log('ok');
               done(null, user);
           }
        });

    }

));

and routes/auth.js :

var express = require('express'),
    passport = require('passport');

var routes = function(User) {
    var router = express.Router();

    // routes for registration
    router.route('/register')
        .get(function(req, res) {
            res.render('register');
        })
        .post(function(req, res) {
           User.count().then(function(number) {
               if (number >= 1) {
                   res.redirect('/auth/login');
               } else {
                   User.create({
                       username: req.body.username,
                       password: req.body.password
                   });

                   res.redirect('/auth/login');
               }
           });
        });
    //routes for login
    router.route('/login')
        .get(function(req, res) {
            res.render('login');
        })
        .post(function(req, res) {
            passport.authenticate('local', { successRedirect: '/dashboard',
                failureRedirect: '/auth/login' });

        });
    return router;
};

module.exports = routes;

Upvotes: 1

Views: 3122

Answers (1)

cfogelberg
cfogelberg

Reputation: 1488

Why does the request/response cycle never end?

Your current middleware definition for './login' POST is incorrect and does not send a response, which is why it doesn't end (until it times out).

Instead of calling passport.authenticate in a middleware function, the result of calling passport.authenticate should be used as middleware itself. I suggest the following:

router.route('/login')
    .get(function(req, res) {
        res.render('login');
    })
    .post(passport.authenticate('local', { successRedirect: '/dashboard',
            failureRedirect: '/auth/login' });
    );

See http://passportjs.org/docs/authenticate for an example.

Race condition in registration code

You didn't ask about this, but there is a race condition in your middleware for './register' POST.

User.create returns a promise for saving the created user. Until that promise is resolved there is no guarantee that the user exists in the backing datastore. However, immediately after calling create, your code redirects to the login endpoint which would query the database for that user.

Here is some code that avoids this problem:

User.create({ ... })
.then(function() {
  res.redirect('/auth/login');
})
.catch(function(err) {
  // Handle rejected promise here 
})

The catch is included because it is always good practice to handle rejected promises and thrown exceptions.

Upvotes: 2

Related Questions