DanyZift
DanyZift

Reputation: 687

NodeJS Passport

I setup passport on nodejs and have it working with mongoose for allowing users to login and create new accounts.

app.js:

var express = require('express')
  , app = module.exports = express.createServer()
  , passport = require('passport')
  , LocalStrategy = require('passport-local').Strategy
  , routes = require('./routes/index')(app) //index loads in multiple routes
  , MongoDBConnection = require('./database/DatabaseConnector').MongoDBConnection;

// Configuration
app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.cookieParser());
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.session({ secret: 'justdoit' }));
  app.use(passport.initialize());
  app.use(passport.session());
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});

var mongoDbConnection = new MongoDBConnection();

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

passport.deserializeUser(function(id, done) {
    mongoDbConnection.findUserById(id, function(err, user){
       done(err, user);
    });
});

passport.use(new LocalStrategy(
    function(username, password, done) {
        process.nextTick(function () {
            mongoDbConnection.findUser(username, function(err, user) {
                //conditions....
            });
        });
    }
));

app.get('/', function(req, res){
    res.render('index', { title: "Index", user: req.user });
});

app.get('/account', ensureAuthenticated, function(req, res){
    res.render('account', { title: "Account", user: req.user });
});

app.get('/login', function(req, res){
    res.render('login', { title: "Login", user: req.user, message: req.flash('error') });
});

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

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

My problem is the app.js (which is where the passport code is) file is getting a bit large and I tried to move the passport sections into its own script and have the routes outside the app.js and in its own auth.js route file and then reference the routes via the app.js. It works for other routes but for passport related ones such as login it doesnt appear to fire the passport.authenicate() function.

Is there anyway I can put passport routes and functions into its own file and call it/load it from app.js?

auth.js:

module.exports = function(app){

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

passport.deserializeUser(function(id, done) {
    mongoDbConnection.findUserById(id, function(err, user){
        done(err, user);
    });

});

passport.use(new LocalStrategy(
    function(username, password, done) {
        process.nextTick(function () {

            mongoDbConnection.findUser(username, function(err, user) {

                if (err) {
                    return done(err);
                }
                if (!user) {
                    return done(null, false, { message: 'Unknown user ' + username });
                }

                if (user.password != password) {
                    return done(null, false, { message: 'Invalid password' });
                }

                return done(null, user);
            });
        });
    }
));

app.get('/', function(req, res){
    res.render('index', { title: "Index", user: req.user });
});

app.get('/account', ensureAuthenticated, function(req, res){
    console.log("directing to the account page....");
    res.render('account', { title: "Account", user: req.user });
});

app.get('/login', function(req, res){
    res.render('login', { title: "Login", user: req.user, message: req.flash('error') });
});

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

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

Upvotes: 24

Views: 12461

Answers (5)

Tyrese Williams
Tyrese Williams

Reputation: 31

Adding on to Legendre's answer. module.exports = function() is a way in nodejs to make a file, a variable or a certain functionality globally available to the entire application.

// anyfile.js
  module.exports = function(){ 
    //global code.
}

Upvotes: 1

Anton Stafeyev
Anton Stafeyev

Reputation: 2859

module.exports = function(app){

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

Maybe it doesnt work because u do not have a reference to a passport object ?

Upvotes: 0

Sunil More
Sunil More

Reputation: 248

For this I'll suggest to do this In app.js

 require('./mypassport')(app);

And mypassport.js

var passport = require('passport')
, LocalStrategy = require('passport-local').Strategy

, MongoDBConnection = require('./database/DatabaseConnector').MongoDBConnection;

  module.exports = function(app){

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

  passport.deserializeUser(function(id, done) {
   mongoDbConnection.findUserById(id, function(err, user){
    done(err, user);
  });

});

passport.use(new LocalStrategy(
function(username, password, done) {
    process.nextTick(function () {

        mongoDbConnection.findUser(username, function(err, user) {

            if (err) {
                return done(err);
            }
            if (!user) {
                return done(null, false, { message: 'Unknown user ' + username });
            }

            if (user.password != password) {
                return done(null, false, { message: 'Invalid password' });
            }

              return done(null, user);
        });
      });
} 
));
}

Upvotes: 4

WallMobile
WallMobile

Reputation: 1959

This github repo also has a good example of this.

https://github.com/madhums/nodejs-express-mongoose-demo

The server.js file would be your app.js. And the /config/passport.js is the included passport setup.

Upvotes: 6

Legendre
Legendre

Reputation: 3156

This is what I do. Please comment if you need more help tailoring it to your code.

First Step

Put your passport code in a separate file. e.g. pass.js. (I see you have already done that) Then, in that file, put all the code inside this:

module.exports = function(passport, LocalStrategy){

};

Remember to add to the function input anything else that you are using. In your case, besides passport and LocalStrategy, you will probably need to add mongoDbConnection as an input too.

Second Step

In your app.js, include this line. Just before "app.listen" if possible to ensure that everything has been properly defined/declared/included.

require('./pass.js')(passport, LocalStrategy);

Explanation

The "wrapper" in step one defines the chunk of code you will be including into your app. The "require" in step two is the code that actually includes it. You are basically defining the entire "pass.js" file as a function and passing it the tools it needs to carry out the code (passport, LocalStrategy etc)

In your case, you will probably need to modify my code to:

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

};

require('./pass.js')(passport, LocalStrategy, mongoDbConnection);

This should works. I googled about this a while ago and this appears to be the "correct" way to break up your app.js (I say this with great trepidation though :) ). Feel free to comment if you need anymore help.

Upvotes: 39

Related Questions