Calling passport.authenticate in a separate function isn't working - javascript

I'm relatively new to Node and Passport and I was experimenting with login forms using OAuth. I had no problems with setting up Passport and it was completely functional.
It only broke down when I started cleaning up the code to separate the routes from the middlewares.
I've included a part of my code before and after the changes.
So, this works:
module.exports = function(app, passport) {
app.get('/login', loginIndex)
app.post('/login', passport.authenticate('local-login', {
successRedirect : '/profile',
failureRedirect : '/login',
failureFlash : true
}))
function loginIndex(req, res) {
res.render('login.ejs', {message: req.flash('loginMessage')})
}
}
But this does not:
module.exports = function(app, passport) {
app.get('/login', loginIndex)
app.post('/login', loginAuth)
function loginIndex(req, res) {
res.render('login.ejs', {message: req.flash('loginMessage')});
}
function loginAuth(){
passport.authenticate('local-login', {
successRedirect : '/profile',
failureRedirect : '/login',
failureFlash : true
})
}
}
So, the only difference between the two is that I've moved the passport.authenticate() call into the function loginAuth().
I guess it has to do with the internal working of passport.authenticate(), but I'm not sure.
Thanks.

Try this:
app.post('/login', loginAuth())
...
function loginAuth(){
return passport.authenticate('local-login', {
successRedirect : '/profile',
failureRedirect : '/login',
failureFlash : true
})
}
In your original code, you are executing passport.authenticate and in the second version you are just passing a function without executing the passport logic.

Related

Passport Authenticate doesn't redirect

I was writing a local-signup strategy and noticed that it doesn't work so I stepped back and tried to authenticate against my empty collection. Every time I submit the form it takes ~30-40s until it results in a timeout. I ensured passport.authenticate() is called but it seems ike it's not doing any redirects and hence it is timing out because I am not rendering something either.
Questions:
I expected that it would do a redirect to the failureUrl (which is '/signup'), but instead nothing is happening. What am I doing wrong here?
Why there is no single log message coming from passport? This is driving me crazy because I have absolutely no idea what is going wrong there.
I am new to node.js and as far as I got I don't need to pass the configured passport object to the router but instead I can just do const passport = require('passport') is that correct?
This is my function handler for the /signup route:
function processSignup (req, res) {
logger.info("POST request received")
logger.info(req.body)
passport.authenticate('local', {
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
})
}
Winston prints:
7:32:04 PM - info: POST request received 7:32:04 PM - info:
username=dassd#dass.de, password=dasdsa, submit=Register
My passport.js file looks like this:
const LocalStrategy = require('passport-local').Strategy
const User = require('./user-model')
const passport = require('passport')
// expose this function to our app using module.exports
function config() {
passport.serializeUser(function(user, done) {
done(null, user.id)
})
// used to deserialize the user
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user)
})
})
passport.use(new LocalStrategy(
function(username, password, done) {
User.findOne({ username: username }, 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);
});
}
));
}
module.exports = {
config: config
}
The relevant snipped of my app.js:
// required for passport
require('./authentication/passport').config();
app.use(cookieParser())
app.use(bodyParser())
app.use(session({
secret: 'secretToBeChanged',
saveUninitialized: false,
resave: false
}))
app.use(passport.initialize())
app.use(passport.session()) // persistent login sessions
app.use(flash()) // use connect-flash for flash messages stored in session
After a quick look at the documentation for passportjs, I think you need to do something like this:
function processSignup (req, res, next) {
logger.info("POST request received")
logger.info(req.body)
const handler = passport.authenticate('local', {
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
});
handler(req, res, next);
}
passport.authenticate() returns a function that is meant to be used as the route handler function.
Normally, you would type something like:
app.post('/login', passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/login',
failureFlash: true
}));
But since you have abstracted with your own route handler function, you need to invoke the one returned from passport.authenticate().
In the end Mikael Lennholm was right and he pointed me into the right direction. I couldn't find that in any passport.js tutorials. However the passport.js documentation contains this code snippet which represents the same but I prefer it's code style:
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.redirect('/login'); }
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.redirect('/users/' + user.username);
});
})(req, res, next);

How to convert passport.authenticate username to lower case before submitting?

I'm using passport in my nodejs app for authentication like so
router.post("/login", passport.authenticate("local", {
successRedirect: "/",
failureRedirect: "/login"
}), function (req, res) {
})
and I'm having a problem because I don't know how to convert a person's username to lowercase since when they register I convert their usernames to all lowercase using .toLowerCase() before storing in my database.
How can I do the same thing when they enter their username for the login?
You can add middleware that runs before passport's action
router.post("/login", usernameToLowerCase, passport.authenticate("local", {
successRedirect: "/",
failureRedirect: "/login"
}), function (req, res) {
});
function usernameToLowerCase(req, res, next){
req.body.username = req.body.username.toLowerCase();
next();
}

Reconciling Express (Passport) and AngularJS Routes

I am building a MEAN-stack application and am finally getting to the point of creating a user authentication. To do so, I followed this tutorial: http://code.tutsplus.com/tutorials/authenticating-nodejs-applications-with-passport--cms-21619
Now, when I incorporate this into my project it works, but only partially. Namely, it seems that the only page I can navigate to properly is the app's home page. If I click on any links or type something other than home in the address bar, it takes me back to the login screen.
What are some possible reasons for that?
My routes/index.js file looks as follows:
var express = require('express');
var router = express.Router();
var isAuthenticated = function (req, res, next) {
// if user is authenticated in the session, call the next() to call the next request handler
// Passport adds this method to request object. A middleware is allowed to add properties to
// request and response objects
if (req.isAuthenticated())
return next();
// if the user is not authenticated then redirect him to the login page
res.redirect('/');
}
module.exports = function(passport){
/* GET login page. */
router.get('/', function(req, res) {
// Display the Login page with any flash message, if any
res.render('index', { message: req.flash('message') });
});
/* Handle Login POST */
router.post('/login', passport.authenticate('login', {
successRedirect: '/home',
failureRedirect: '/',
failureFlash : true
}));
/* GET Registration Page */
router.get('/signup', function(req, res){
res.render('register',{message: req.flash('message')});
});
/* Handle Registration POST */
router.post('/signup', passport.authenticate('signup', {
successRedirect: '/home',
failureRedirect: '/signup',
failureFlash : true
}));
/* GET Home Page */
router.get('/home', isAuthenticated, function(req, res){
res.render('home', { user: req.user });
});
/* Handle Logout */
router.get('/signout', function(req, res) {
req.logout();
res.redirect('/');
});
return router;
}
I also have some AngularJS routes specified in another file (application worked perfectly with these before I started adding authentication).
app.config(['$routeProvider', function($routeProvider){
$routeProvider
.when('/', {
templateUrl: 'partials/home.html',
controller: 'HomeCtrl'
})
.when('/calendar',{
templateUrl: 'partials/calendar.html',
//controller: 'Calendar'
})
.when('/add-activity', {
templateUrl: 'partials/activity-form.html',
controller: 'AddActivityCtrl'
})
.when('/activity/:id',{
templateUrl: 'partials/activity-form.html',
controller: 'EditActivityCtrl'
})
.when('/activity/delete/:id', {
templateUrl: 'partials/activity-delete.html',
controller: 'DeleteActivityCtrl'
})
.otherwise({
redirectTo: '/'
});
}]);
Is there something I am missing?
P.S. I noticed that currently my URL of home page is
http://localhost:3000/home#/
whereas previously it was
http://localhost:3000/#/
I added "home" to differentiate from "/" which is the authentication page; however, I am unsure about how "#" is tacked onto the path in the first quote.
I was able to resolve this as follows. I changed the Express routing to contain a
"login"
route and changed the home route to just
"/"
As a result, the home path became
http://localhost:3000/#/
The hash sign is tacked on by and for the Angular. From my understanding, the Angular treats such path as "/". Then, the remaining routing is done by Angular and I have a single-page AngularJS app.
Working code:
Express
var express = require('express');
var router = express.Router();
module.exports = function(passport){
var isAuthenticated = function (req, res, next) {
// if user is authenticated in the session, call the next() to call the next request handler
// Passport adds this method to request object. A middleware is allowed to add properties to
// request and response objects
if (req.isAuthenticated()){
//console.log(next());
return next();
}
// if the user is not authenticated then redirect him to the login page
res.redirect('/login');
}
/* GET login page. */
router.get('/login', function(req, res) {
// Display the Login page with any flash message, if any
res.render('login', { message: req.flash('message') });
});
/* Handle Login POST */
router.post('/login', passport.authenticate('login', {
successRedirect: '/',
failureRedirect: '/login',
failureFlash : true
}));
/* GET Registration Page */
router.get('/signup', function(req, res){
res.render('register',{message: req.flash('message')});
});
/* Handle Registration POST */
router.post('/signup', passport.authenticate('signup', {
successRedirect: '/',
failureRedirect: '/signup',
failureFlash : true
}));
/* GET Home Page when logged in */
router.get('/', isAuthenticated, function(req, res){
res.render('index', { user: req.user });
});
/* GET Home Page */
router.get('/', isAuthenticated, function(req, res){
res.render('index', { user: req.user });
});
/* Handle Logout */
router.get('/signout', function(req, res) {
req.logout();
res.redirect('/login');
});
return router;
}
Working code: Angular
app.config(['$routeProvider', function($routeProvider){
$routeProvider
.when('/', {
templateUrl: 'partials/home.html',
controller: 'HomeCtrl'
})
.when('/calendar',{
templateUrl: 'partials/calendar.html',
//controller: 'Calendar'
})
.when('/add-activity', {
templateUrl: 'partials/activity-form.html',
controller: 'AddActivityCtrl'
})
.when('/activity/:id',{
templateUrl: 'partials/activity-form.html',
controller: 'EditActivityCtrl'
})
.when('/activity/delete/:id', {
templateUrl: 'partials/activity-delete.html',
controller: 'DeleteActivityCtrl'
})
.otherwise({
redirectTo: '/'
});
}]);

passport.authenticate is not a function

Hello I am new in NodeJs and I have been following this tutorial http://code.tutsplus.com/tutorials/authenticating-nodejs-applications-with-passport--cms-21619 to create a app with authenticating.
I tried to follow all the structre and code from the tutorial (code is on github https://github.com/tutsplus/passport-mongo) but when I open my app in browser
i get error this error
TypeError: passport.authenticate is not a function
at module.exports (C:\myApp\routes\index.js:24:34)
This is my index.js route file
var express = require('express');
var router = express.Router();
var passport = require('passport');
var isAuthenticated = function (req, res, next) {
// if user is authenticated in the session, call the next() to call the next request handler
// Passport adds this method to request object. A middleware is allowed to add properties to
// request and response objects
if (req.isAuthenticated())
return next();
// if the user is not authenticated then redirect him to the login page
res.redirect('/');
}
module.exports = function(passport){
/* GET login page. */
router.get('/', function(req, res) {
// Display the Login page with any flash message, if any
res.render('index', { message: req.flash('message') });
});
/* Handle Login POST */
router.post('/login', passport.authenticate('login', {
successRedirect: '/home',
failureRedirect: '/',
failureFlash : true
}));
/* GET Registration Page */
router.get('/signup', function(req, res){
res.render('register',{message: req.flash('message')});
});
/* Handle Registration POST */
router.post('/signup', passport.authenticate('signup', {
successRedirect: '/home',
failureRedirect: '/signup',
failureFlash : true
}));
/* GET Home Page */
router.get('/home', isAuthenticated, function(req, res){
res.render('home', { user: req.user });
});
/* Handle Logout */
router.get('/signout', function(req, res) {
req.logout();
res.redirect('/');
});
return router;
}
Probabbly the problem is there, maybe routing was change in some version of express, but I cant figure out what is the problem.
Can you help pme please ?
I had same problem. Look at app.js. There must be:
var routes = require('./routes/index')(passport);
You have just put the parenthesis at the wrong place.
It should be
router.post('/login', passport.authenticate('login'), {
successRedirect: '/home',
failureRedirect: '/',
failureFlash : true
});

Get POST request when using Router middleware

I'm using Passport to authenticate my users on NodeJS. Currently I'm using ExpressJS and I'm trying to route my traffic. I currently use the following code:
website.js (main file)
require("./routes.js")(app);
routes.js
var pages = {
home: require("./pages/home"),
about: require("./pages/about"),
register: require("./pages/register"),
login: require("./pages/login"),
api: require("./api/index")
};
module.exports = function(app) {
app.use("/", pages['home']);
for (page in pages) {
app.use("/" + page, pages[page]);
}
app.get("/logout", function(req, res) {
req.logout();
req.redirect("/");
});
}
register.js
var express = require('express');
var router = express.Router();
var app = express();
router.get("/", function(req, res) {
res.render("register", { page: "Register", message: req.flash("registerMessage") });
});
app.post("/", passport.authenticate("register", {
successRedirect: "/about/",
failureRedirect: "/register/",
failureFlash: true,
successFlash: "Logged in!"
}));
module.exports = router;
The problem I am facing is that POST requests to this will result in a 404. The page is not found. The GET request (so /register) properly shows the registration form, but upon submitting I get a 404. If I change router.get("/", function(req,res){}) to router.use("/", function(req, res, next) {}), I will get HTTP 500 errors when I call "Next()" (Can't set headers after they are sent.), and POST still doesn't work.
Could anyone tell me how to correctly catch POST requests behind router middleware?
I solved my issue
I solved my issue by using the following:
router.route("/")
.get(function(req, res, next) {
res.render("register", { page: "Register", message: req.flash("registerMessage") });
})
.post(passport.authenticate("register", {
successRedirect: "/about/",
failureRedirect: "/register/",
failureFlash: true,
successFlash: "Logged in!"
}));

Categories

Resources