I am new to Express.js but I want to learn it the right way. Hence I've started with using Peter Lyon's suggested code structure introduced here: https://github.com/focusaurus/express_code_structure . I am following a passport.js tutorial which requires me to pass the passport object to my router and I am stuck there
This is my index.js:
appCommon.head(app, passport)
// Load all Routers
app.use('/', require('./pages/router'))
app.use('/projects', require('./projects/router'))
app.use('/', require('./authentication/router'))(passport) // Pass passport to router
My authentication/router.js:
var express = require('express')
var join = require('path').join
var router = new express.Router()
// I removed the other functions
function processSignup (req, res) {
passport.authenticate('local-signup', {
successRedirect : '/profile', // redirect to the secure profile section
failureRedirect : '/signup', // redirect back to the signup page if there is an error
failureFlash : true // allow flash messages
})
}
router.use(express.static(join(__dirname, '../../wwwroot')))
router.get('/login', login)
router.get('/signup', signup)
router.post('/signup', processSignup)
router.get('/profile', isLoggedIn, profile)
router.get('/logout', logout)
module.exports = router
Questions:
Did I pass the passport object correctly to my router?
How can I add the passport object to my router so that the processSignup function is aware of it?
You should really not send any passport object to router. What you should do is use the Strategies in your main file like this:
// load passport strategies
const localStrategy = require('./server/passport')
passport.use('local-signup', localStrategy.Signup)
passport.use('local-login', localStrategy.Login)
After you use this strategy in passport you can use this strategy to authenticate right away in your any routes like below:
const passport = require('passport');
router.post('/login',
passport.authenticate('local-login', { successRedirect: '/',
failureRedirect: '/login',
failureFlash: true })
);
Related
i have a some problem
i'm using express-session middleware in my app
it work
but
It did not work on any particular router.
my code is follows
//app.js
app.use(session({
secret: 'D$YTRH#%#$#^$#YR',
resave: false,
saveUninitialized: true,
}))
//assign session in outside
app.get(/*, (req, res, next)=>{
req.session.outSide = "outSideBlah"
next()
}
//my session Check middleware
app.get('/*', (req, res, next)=>{
console.log(req.session._inSide)
console.log(req.session._outSide)
next()
}
const auth = require('./routes/auth.js')(express)
app.use('/auth', auth)
//auth.js (my router)
//assign session in router ( inside)
module.exports = (express) => {
const auth = express.Router()
auth.post('/login', (req, res)=>{
req.session._inside = 'insideBlah' //Assign a session here
............some auth code ......
}
return auth
}
after login
in my session Check middleware
console.log(req.session.inSide) // undefined
console.log(req.session.outSide) // "outSideBlah"
Even though I assigned req.session.inSide in auth.js
req.session.inside is undefined
What is the problem?
Why can not I access a session assigned by my router (auth.js)?
somebody help me.. thank you...
Also I think you should use * instead of /*.
I am trying to use passport-local to restrict access of a website.
For this I am using login_app for running passport-local, however this is in itself a route that is called from the main app.js.
While trying to route on a 2nd level (passport-files/routes) I find that my code is found, but the functions inside are not called.
This is my login_app code:
var express = require('express');
var router = express.Router();
var mongoose = require ('mongoose');
var flash = require('connect-flash');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var morgan = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
let app = express();
// pass passport for configuration
require('./passport-files/passport')(passport);
//For express application
app.use(morgan('dev'));
app.use(cookieParser()); // read cookies (needed for auth)
app.use(bodyParser()); // get information from html forms
//Initialize passport session
app.use(session({ secret: 'secret' })); // session secret
app.use(passport.initialize());
app.use(passport.session());
app.use(flash()); // use connect-flash for flash messages stored in session
// load our routes and pass in our app and fully configured passport
require('./passport-files/routes')(app, passport);
module.exports = router;
To simplify the question I am only putting the routes.js file here:
var express = require('express');
var router = express.Router();
let app = express();
module.exports = function (app, passport) {
//function views (app, passport) {
/* GET users listing. */
// HOME PAGE (with login links) ========
app.get('/', function(req, res) {
res.render('login-welcome', {});
});
// LOGIN ===============================
// show the login form
app.get('/log-in', function(req, res) {
res.render('login', { message: req.flash('loginMessage') });
});
// process the login form
app.post('/log-in', passport.authenticate('local-login', {
successRedirect : '/admin', // redirect to the secure profile section
failureRedirect : '/log-in', // redirect back to the signup page if there is an error
failureFlash : true // allow flash messages
}));
// we will use route middleware to verify this (the isLoggedIn function)
app.get('/profile', isLoggedIn, function(req, res) {
res.render('profile', {
user : req.user // get the user out of session and pass to template
});
});
app.get('/logout', function(req, res) {
req.logout();
res.redirect('/');
});
};
// route middleware to make sure a user is logged in
function isLoggedIn(req, res, next) {
// if user is authenticated in the session, carry on
if (req.isAuthenticated())
return next();
// if they aren't redirect them to the hosme page
res.redirect('/');
};
I pretty much built this using the example from scotch.io ( https://scotch.io/tutorials/easy-node-authentication-setup-and-local ), however I cannot get it to work this way.
If i write the routes directly into login_app, they are recognized, even though the authentification still does not work.
Do any of you have an idea how to solve this? Is more information required?
This may be the problem: in your login_app module you're exporting router, however you haven't actually defined any routes on router, they're all defined on a new instance of an app.
A simple example creating a router in one file, and exporting it to use in a main app.js file, would be like this:
/** app.js */
var express = require('express');
var app = express();
var myRoutes = require('./routes');
app.use(myRoutes);
app.listen(3000);
/** routes.js */
// instaniate a new router, add routes/middleware on it, and export it
var router = require('express').Router();
// define your routes and middleware here
// router.use( ... )
module.exports = router;
Another pattern, which I think the scotch.io tutorial is using, is to have the routes file export a function into which you pass your main app instance. Then the two files would look like this:
/** app.js */
var express = require('express');
var app = express();
require('./routes')(app); // pass your main `app` instance into the function
app.listen(3000);
/** routes.js */
module.export = function(app) {
// define all your routes and middleware here directly on the `app` that gets passed in
// app.use( ... )
}
I am doing a react project using express and passport-local for the authentication part based on this tutorial :
https://scotch.io/tutorials/easy-node-authentication-setup-and-local
The authentification work very well, I added the express router to define my routes for my api, but when I call for example "/api/myroute" the router of express creates an other session and I lose the user, so my function isLoggedIn blocks the call of my controllers because there is no user in this new session. So my question is : Why the router recreate a session ? What it is wrong in my configuration ? Here is my code :
//server.js
var path = require('path');
var webpack = require('webpack');
var webpackDevMiddleware = require('webpack-dev-middleware');
var webpackHotMiddleware = require('webpack-hot-middleware');
var config = require('./webpack.config');
var express = require('express');
var app = express();
var port = process.env.PORT || 8080;
var mongoose = require('mongoose');
var passport = require('passport');
var flash = require('connect-flash');
var morgan = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var configDB = require('./config/database.js');
var router = express.Router();
// configuration ===============================================================
mongoose.connect(configDB.url); // connect to our database
require('./config/passport')(passport); // pass passport for configuration
// set up our express application
app.use(morgan('dev')); // log every request to the console
app.use(cookieParser()); // read cookies (needed for auth)
app.use(bodyParser()); // get information from html forms
app.set('view engine', 'ejs'); // set up ejs for templating
// required for passport
app.use(session({ secret: 'secret' })); // 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
var compiler = webpack(config);
app.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: config.output.publicPath }));
app.use(webpackHotMiddleware(compiler));
app.use('/plugins/bootstrap', express.static(path.join(__dirname, './plugins/bootstrap')));
app.use('/plugins/jquery', express.static(path.join(__dirname, './plugins/jquery')));
app.use('/plugins/font-awesome', express.static(path.join(__dirname, './plugins/font-awesome')));
// all of our routes will be prefixed with /api
app.use('/api', router);
// routes ======================================================================
require('./api/routes.js')(app, passport,router); // load our routes and pass in our app and fully configured passport
// launch ======================================================================
app.listen(port, function(error) {
if (error) {
console.error(error)
} else {
console.info("==> 🌎 Listening on port %s. Open up http://localhost:%s/ in your browser.", port, port)
}
});
console.log('The magic happens on port ' + port);
And here is my routes.js :
module.exports = function(app, passport,router) {
var MyController = require("../api/controllers/mycontroller");
// =====================================
// HOME PAGE (with login links) ========
// =====================================
app.get('/', function(req, res) {
console.log("welcome")
res.render('index.ejs', { message: ""}); // load the index.ejs file
});
// =====================================
// LOGIN ===============================
// =====================================
// show the login form
app.get('/login', function(req, res) {
console.log("login")
// render the page and pass in any flash data if it exists
res.render('index.ejs', { message: req.flash('loginMessage') });
});
app.post('/login', passport.authenticate('local-login', {
successRedirect : '/welcome', // redirect to the secure profile section
failureRedirect : '/login', // redirect back to the signup page if there is an error
failureFlash : true // allow flash messages
}));
// =====================================
// SIGNUP ==============================
// =====================================
// show the signup form
app.get('/signup', function(req, res) {
console.log("signup")
// render the page and pass in any flash data if it exists
res.render('signup.ejs', { message: req.flash('signupMessage') });
});
// process the signup form
app.post('/signup', passport.authenticate('local-signup', {
successRedirect : '/welcome', // redirect to the secure profile section
failureRedirect : '/signup', // redirect back to the signup page if there is an error
failureFlash : true // allow flash messages
}));
// process the signup form
// app.post('/signup', do all our passport stuff here);
// =====================================
// LOGOUT ==============================
// =====================================
app.get('/logout', function(req, res) {
console.log("logout")
req.logout();
res.redirect('/');
});
router.get('/myroute', isLoggedIn, function(req, res) {
//HERE the router recreate a session and req.user is now undefined why ?
MyController.getAllObjects(req,res);
});
// =====================================
// HOME SECTION =====================
// =====================================
// we will want this protected so you have to be logged in to visit
// we will use route middleware to verify this (the isLoggedIn function)
app.get('*', isLoggedIn, function(req, res) {
console.log("HOME")
res.render('home.ejs', {
user : req.user // get the user out of session and pass to template
});
});
};
// route middleware to make sure a user is logged in
function isLoggedIn(req, res, next) {
// if user is authenticated in the session, carry on
if (req.isAuthenticated())
return next();
console.log("redirect because not log in")
// if they aren't redirect them to the home page
res.redirect('/');
}
The function for login, logout, signin... are a copy paste of the tutorial.
You seem to be using the fetch library. This library does not include the domain cookies by default, so in order to work your request should look like this:
fetch('/api/myroute', {
credentials: 'same-origin' // This is the line you are missing
}).then(response => response.json())
.then(json => {
dispatch({
type: types.MY_ACTION, forms: json, receivedAt: Date.now()
})
})
See this link for more information.
Since from Express 4 you're not supposed to do
require('./app/routes.js')(app, passport); // load our routes and pass in our app and fully configured passport
module.exports = function(app, passport) {
// =====================================
// FACEBOOK ROUTES =====================
// =====================================
// route for facebook authentication and login
app.get('/auth/facebook', passport.authenticate('facebook', { scope : 'email' }));
// handle the callback after facebook has authenticated the user
app.get('/auth/facebook/callback',
passport.authenticate('facebook', {
successRedirect : '/profile',
failureRedirect : '/'
}));
// route for logging out
app.get('/logout', function(req, res) {
req.logout();
res.redirect('/');
});
};
Instead, you're supposed to be using express.Route() function and
var routes = require('./app/routes.js');
app.use('/', routes);
How to pass the configured passport into the routes modules in Express 4?
The function export can still be used to pass the passport reference between modules. It would just create and return a Router rather than modifying the app directly.
var express = require('express');
module.exports = function(passport) {
var router = express.Router();
router.get('/auth/facebook', passport.authenticate('facebook', { scope : 'email' }));
// etc.
return router;
};
And, the app can then use it with:
var routes = require('./app/routes.js')(passport);
app.use('/', routes);
So I'm trying to separate all my routes and organize them. I've manage to do that, but I face an issue. Using express 4, and the router I am having a problem passing an instance of something to a particular route. For example I want to pass passport to the login.js file. How would I do that? Am I doing this the correct way, or is there a better more cleaner solution?
//app.js
var express = require('express');
var passport = require('passport');
var app = express();
require('./routes')(app, passport);
//routes.js
module.exports = function (app, passport) {
app.use('/', require('./routes/index'));
app.use('/', require('./routes/login')(passport));
app.use('/', require('./routes/register')(passport));
};
//login.js
Here passport is undefined.
var express = require('express');
var router = express.Router();
router.get('/login', function (req, res) {
res.render('login', {
title: 'login',
message: req.flash('loginMessage')
});
});
router.post('/login', passport.authenticate('local-login', {
successRedirect : '/profile',
failureRedirect : '/login',
failureFlash : true
}));
module.exports = router;
So there's two ways folks do this, and there's pros and cons to each.
Easiest is to have your passport config in a file of your own (i.e. where you setup all your passport strategies, etc), and that file exports the passport object after setting it up.
e.g.
/* in ./lib/passport.js */
module.exports = passport;
Then in some other file that needs it, you just require your passport file (code in there only gets called once, and the exported module is cached after that).
/* in some other file */
var passport = require('./lib/passport');
this has the advantage of simplicity, but a lot of folks feel (rightly so) that it's not quite as testable if you're doing unit tests, b/c you can't isolate the file under test as easily, etc.
so in that case, each module file will export a function which takes its dependencies in through a function. For example,
/* in your router file */
var router = require('express').Router();
var loginRoutes = function(passport){
router.post('/login', passport.authenticate('local-login', {
successRedirect: '/profile',
failureRedirect: '/login'
}));
return router;
};
module.exports = loginRoutes;
then wherever you're pulling the routes into the app, that process just requires the route file and calls the function, passing it the passport instance. which looks like what you did in routes.js.