Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passport.js local authentication with Express.js 4

I´m trying to use Passport.js with Express.js 4.0 but nothing is happening. I´m following below tutorial and trying to adapt it to fit Express.js 4.0 new routing features.

http://scotch.io/tutorials/javascript/easy-node-authentication-setup-and-local

So far I just want to try to login and get the failure redirect view with the proper message, as stated in the LocalStrategy.

This is what I´m doing in app.js:

1.- Pulling the required modules and creating the app variable

...
var session = require('express-session');
var mongoose = require('mongoose');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var flash = require('connect-flash');
var bcrypt = require('bcrypt-nodejs');

var app = express();

2.- Connecting to MongoDB database and ensure a Users Model to store users

require('./models/db')(mongoose, 'mongodb://localhost/cms');

var User = require('./models/user')(mongoose);

4.- Configure Passport

require('./config/passport')(passport, User, LocalStrategy);

5.- Making Sure to include all the required Middleware

app.engine('.html', require('ejs').__express);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'html');

app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());

app.use(session({
  secret: 'keyboardcat'
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());

app.use(express.static(path.join(__dirname, 'public')));

6.- Route Handling

var router = express.Router();

router.use(function (req, res, next) {

  if (req.method === 'POST' && req.url === '/login') {
    // Log #1
    console.log(passport);

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

  } else {

    next();

  }
});

router.route('/')
      .get(function (req, res) {
        res.render('index');
      });

router.route('/login')
      .post(function (req, res) {
        console.log('Post on /login');
      })
      .get(function (req, res) {
        res.render('login', {
          message: req.flash('loginMessage')
        });
      });

app.use('/', router);

... (Rest of app.js such as error handlers)

This is how the Configuration of the Passport Strategy is set in ./config/passport.js

module.exports = function (passport, User, LocalStrategy) {

  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('login', new LocalStrategy({
    usernameField : 'email',
    passwordField : 'password',
    passReqToCallback : true 
  }, function (email, password, done) {

      User.findOne({ email: email }, function (err, user) {

        if (err) { 

          return done(err);

        }

        if (!user) {

          return done(null, false, { message: 'Incorrect username.' });

        }

        if (!user.validPassword(password)) {

          return done(null, false, { message: 'Incorrect password.' });

        }

        return done(null, user);

      });

    }

  ));

};

The Login View looks like this

As we can see the input names are set properly like in the Strategy.

<% include header.html %>

<% if (message.length > 0) { %>
  <div><%= message %></div>
<% } %>

<form action="/login" method="post" enctype="multipart/form-data">
  <input type="text" name="email"/>
  <input type="password" name="password"/>
  <input type="submit" value="Log In"/>
</form>

<% include footer.html %>

Since there´s no users yet I was expecting to be redirected to '/' with the 'Incorrect username.' message when submitting the form but instead the browsers stays in a loading state and nothing happens.

A few thoughts...

Am I calling to:

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

Where it should be called? What I want it here is to call it as middleware when making a POST to the login route.

The Log#1 is actually showing the passport object.

I have a few days with this and I can´t figure out what´s happening... I hope someone can spot something, Thanks Much!.

like image 669
Ricardo Fornes Avatar asked Oct 31 '22 23:10

Ricardo Fornes


1 Answers

I see that you're not doing anything in your router.route('/login').post (except for console.loging a message)

Do this: http://passportjs.org/guide/

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

Or with a custom callback (if you wanna keep your console.log), you return the passport returned authentication method.

.post(function (req, res){
    console.log('Post on /login');
    return passport.authenticate('local-login', function(err, user, info){
        // PS: You can also inspect err/user here to see if everything else is working properly 
        console.log(err);
        console.log(user);
        console.log(info)
    })(req, res, next);
});
like image 157
laggingreflex Avatar answered Dec 05 '22 00:12

laggingreflex