vrghost
vrghost

Reputation: 1224

passing objects (passport) between routes

Think what I am trying to do should be relatively easy, but I am loosing the thread, and potentially the will to do this.

Setting up a node application using node and express 4. And I use passport for authentication. Followed an absolutely amazing guide by scott.io which did the trick nicely https://scotch.io/tutorials/easy-node-authentication-setup-and-local

And it works a charm. However, I want to separate my routes, because I like keeping things tidy (thats a lie, but I intend to keep the lie living).

My plan was to have four sets of routes. api (mapped to /api, using the file ./routes/api.js) index (mapped to /, using the file ./routes/index.js) auth (mapped to /auth, keeps track of all authentication, callbacks as well as some activator and other bits)

Now to my issue, I need to make the passport available to app (or get api.js and indes.js to be able to call functions in passport.js) and I can't quite figure out how.

My plan was to initiate passport like so:

var passport = require('passport');
app.use(session({secret: 'Not-telling-you)',
    saveUninitialized: true,
    resave: true
})); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session
//Configuring the passports
require('./config/passport')(passport);

That should give me passport available in app

Next to load the route modules

var auth = require('./routes/auth')(app, passport);
var users = require('./routes/users')(app,passport);
var activator = require('./routes/activator')(app,passport);

This SHOULD allow me to access them in the modules?

Map all toutes in app

app.use('/api', api);
app.use('/auth', auth);
app.use('/', index);

And then write the modules as follows (this is a super simple version of auth)

var bodyParser = require('body-parser');
var activator = require('activator');
var express = require('express');
var router = express.Router();


//Lets read the configuration files we need
var activatorCfg = require('../config/activator.js')
var cfgWebPage = require('../config/webpage.js');

//So we can read the headers easily
router.use(bodyParser.json()); // support json encoded bodies
router.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies

//Activating activator, so we can actively activate the actives
activator.init({user: activatorCfg, transport: activatorCfg.smtpUrl , from: activatorCfg.fromEmail, templates: activatorCfg.templatesDir});


router.get('/login', function(req, res) {
    res.render('login.ejs', { title: 'Betchanow - Social betting as it should be' , loginUrl: cfgWebPage.loginUrl, trackingID: cfgWebPage.googleTracking.trackingID, message: req.flash('loginMessage') });
});


module.exports=function(app, passport) {
    router
}

My problem is that if I do that, express complains that

      throw new TypeError('Router.use() requires middleware function but got a
            ^
TypeError: Router.use() requires middleware function but got a undefined

If I just return the router (skip wrapping it in a function) I end up with a
var search = 1 + req.url.indexOf('?'); ^ TypeError: Cannot read property 'indexOf' of undefined

So is there a right, simple or preferably right and simple way of achieving this? Think the trick would be to pass app and passport (or only passport), think is I need access to either data or functions from passport in all three, and as I was planning to play with ACL as well, wanted to add that to auth to make my life simple as well.

============== EDIT =============

So here is my issue. If I now do a post to the authentication route (code below)

//Lets load the modules, note the missing passport
var bodyParser = require('body-parser');
var activator = require('activator');
var express = require('express');
var router = express.Router();


//Lets read the configuration files we need
var activatorCfg = require('../config/activator.js')
var cfgWebPage = require('../config/webpage.js');

//So we can read the headers easily
router.use(bodyParser.json()); // support json encoded bodies
router.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies

//Activating activator, so we can actively activate the actives
activator.init({user: activatorCfg, transport: activatorCfg.smtpUrl , from: activatorCfg.fromEmail, templates: activatorCfg.templatesDir});

//Lets start with our routes
// process the login form
router.post('/login', passport.authenticate('local-login', {
    successRedirect : '/', // redirect to the secure profile section
    failureRedirect : '/login', // redirect back to the signup page if there is an error
    failureFlash : true // allow flash messages
}));

module.exports=function(app, passport) {
    return router;
}

I end up with the issue that the route code (./routes/auth.js) have no clue what passport is. (loded in the app as follows):

app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session
//Configuring the passports
require('./config/passport')(passport);

Upvotes: 1

Views: 1960

Answers (1)

justcompile
justcompile

Reputation: 3542

You'll be getting the error because you're not returning the router.

module.exports=function(app, passport) {
    return router;
}

EDIT:

You won't be able to access the passport property because you're not passing it around or setting it anywhere. As I'm not sure how passport works (whether it acts as a singleton or not), so you have a couple of options in your routes file:

var passport = require('passport')

which may "just work", or

var passport; // at the top of your routes file

// your routes

module.exports = function(app, _passport) {
    passport = _passport;
    return router;
}

A third option is to wrap your entire routes in the exports method:

// your requires here

module.exports = function(app, passport) {
    //So we can read the headers easily
    router.use(bodyParser.json()); // support json encoded bodies
    router.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies

    //Activating activator, so we can actively activate the actives
    activator.init({user: activatorCfg, transport: activatorCfg.smtpUrl , from: activatorCfg.fromEmail, templates: activatorCfg.templatesDir});

    //Lets start with our routes
    // process the login form
    router.post('/login', passport.authenticate('local-login', {
        successRedirect : '/', // redirect to the secure profile section
        failureRedirect : '/login', // redirect back to the signup page if there is an error
        failureFlash : true // allow flash messages
    }));
    return router;
}

Upvotes: 3

Related Questions