express passport check if user is authenticated - node.js

I am using passport to login and display '/home'.The login works and redirects to '/home'.But this end point is not protected and can be accessed by typing in the browser.I tried using req.isAuthenticated() (and went through multiple questions here) to no avail.
Routes//index.js
var express = require('express');
var router = express.Router();
var User = require('../models/user');
var passport = require('passport');
var session = require('express-session');
const LocalStrategy = require('passport-local').Strategy;
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);
}
if (user.password != password) {
return done(null, false);
}
return done(null, user);
});
}
));
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
router.get('/login', function(req, res, next) {
res.render('login');
});
router.post('/login', passport.authenticate('local', { failureRedirect : '/', successRedirect : '/home'}))
router.get('/register', function(req, res, next) {
res.render('register');
});
router.get('/logout', function(req, res){
req.logout();
res.redirect('/');
});
router.get('/home', ensureLocalAuthenticated, function(req, res){
res.render('home', { user: req.user });
});
function ensureLocalAuthenticated(req, res, next) {
console.log(req.isAuthenticated());
if (req.isAuthenticated()) { return next(); }
res.redirect('/login');
}
module.exports = router;
on my app.js file i have configued passport like this:
//passportconfig
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function(user, done){
done(null, user.id)
})
passport.deserializeUser(function(id, done){
User.findById(id, function(err, user){
done(err, user)
})
})
app.use('/', indexRouter);
app.use('/users', usersRouter);
isAuthenticated is always returning false,cant login with that middleware.If i remove it,i can login fine but then the '/home' is accessible by all users

Adding the following lines to app.js worked for me:
app.use(require('express-session')({
secret: 'keyboard cat',
resave: false,
saveUninitialized: false
}));
So passport is configured as follows:
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var passport = require('passport');
var mongoose = require('mongoose');
var User = require('./models/user')
const LocalStrategy = require('passport-local').Strategy;
Using them:
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(require('express-session')({
secret: 'keyboard cat',
resave: false,
saveUninitialized: false
}));
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(express.static(path.join(__dirname, 'public')));
//passportconfig
app.use(passport.initialize());
app.use(passport.session());
// used to serialize the user for the session
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);
});
});

Related

Cannot POST in Express + Passport app

I've read similar questions, but I couldn't find a solution.
In my server.js file:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var passport = require('passport');
var cookieParser = require('cookie-parser');
var expressSession = require('express-session');
var passportHelp = require('./config/passport');
var flash = require('connect-flash');
app.use(express.static(__dirname + '/public'));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.set('view engine', '.hbs');
app.set('views', path.join(__dirname, './app/views'))
app.use(expressSession({
secret: 'secret',
saveUninitialized: true,
resave: true
}));
passportHelp(passport);
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use(require('./app/controllers'));
app.listen(3000);
In ./app/controllers
var express = require('express');
var router = express.Router();
router.use(require('./signup'));
module.exports = router;
In ./controllers/signup
var express = require('express');
var passport = require('passport');
var router = express.Router();
router.get('/signup', function(req, res) {
res.render('signup');
});
router.post('/signup', passport.authenticate('local-signup', {
successRedirect: '/profile',
failureRedirect: '/signup',
failureFlash: true,
}));
module.exports = router;
Finally, in ./config/passport
var LocalStrategy = require('passport-local').Strategy;
var User = require('../app/models/user');
module.exports = function(passport) {
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('local-signup', new LocalStrategy({
passReqToCallback : true
},
function(req, username, password, done) {
console.log(req.body.username);
console.log(req.body.password); //successfully logs all of these 3
console.log(req.body.email);
process.nextTick(function() {
User.findOne({ 'username' : username }, function(err, user) {
if (err) {
return done(err);
}
if (user) {
return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
}
else {
var newUser = new User;
//filling new user data here
newUser.save(function(err) {
if (err)
throw err;
return done(null, newUser);
});
}
});
});
}));
I end up with strange behavior. Sometimes POST has no problem, sometimes I get cannot POST /signup, but the result is still saved into the database.
I've tried switching some lines in server.js file, but without result. As I've read, when I require passport in controller/signup, it should be the same 'passport' object which I 'initialized' in server.js, so I dont end up working with a fresh passport object. Am I right?
In case someone faces the same problem.
The reason I got the error, but the save into the database was successful was that I have commented that line: successRedirect

Why this simple passport-local authentication doesn't work?

This minimalistic implementation of local passport strategy, always redirect me to /failure:
const express = require('express');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const session = require('express-session');
var user = {username:"joe", password:"parmesano", id:34};
console.log(user);
passport.use(new LocalStrategy( (username, password, done) => {
done(null, user);
}));
passport.serializeUser( (user, done) => {
done(null, user.id)
});
passport.deserializeUser( (id, done) => {
done(null, user)
});
const app = express();
app.use(session({ secret: 'jamalaja', resave: false, saveUninitialized: false }));
app.use(passport.initialize());
app.use(passport.session());
app.post('/', passport.authenticate('local', { failureRedirect: '/failure', successRedirect: '/success' }));
app.listen(3000);
Should not I be sent to / success?
I get the /success redirect if I add body-parser middleware:
app.use(require('body-parser').urlencoded({ extended: true }));
And test it with the command:
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'username=meda&password=ajana' localhost:3000/

Unable to redirect users to Google for authentication

I have the following code to authenticate users using Google in node.js. I use the passport-google-oauth module. While I'm fairly sure the code is correct, the app simply won't redirect me to the Google login page. Please help me out.
Here is the code (using express.js 4.9.0):
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var passport = require('passport');
var session = require('express-session');
var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
passport.serializeUser(function (user, done) {
done(null, user);
});
passport.deserializeUser(function (obj, done) {
done(null, obj);
});
passport.use(new GoogleStrategy({
clientID: MY CLIENT ID,
clientSecret: MY CLIENT SECRET,
callbackURL: "http://127.0.0.1:1337/auth/google/callback"
},
function (accessToken, refreshToken, profile, done) {
process.nextTick(function () {
return done(null, profile);
});
}
));
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(require('stylus').middleware(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));
// required for passport
app.use(session({ secret: 'victoriassecret' })); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
// catch 404 and forward to error handler
app.use(function (req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
app.get('/', function (req, res) {
//res.render('index', { title: 'Collaborative' });
res.sendFile(path.join(__dirname, '../public', 'login.html'));
});
app.get('/auth/google',passport.authenticate('google', {
scope: ['https://www.googleapis.com/auth/userinfo.profile','https://www.googleapis.com/auth/userinfo.email']
}),
function (req, res) {
// The request will be redirected to Google for authentication, so this
// function will not be called.
});
app.get('/auth/google/callback', passport.authenticate('google', { failureRedirect: '/login' }),
function (req, res) {
res.redirect('/profile');
});
app.get('/logout', function (req, res) {
req.logout();
res.redirect('/');
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function (err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function (err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
app.listen(1337);
module.exports = app;

LocalStrategy function never called

I have tried to setup a simple local strategy authentification with express4 / passportjs, but the authenticate function is never called :
here's my code
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
app.use(compress());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
/* AUTHENTIFICATION */
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
passport.use(new LocalStrategy(
function(username, password, done) { //THIS FUNCTION IS NEVER CALLED
console.log("Local strategy");
}
));
app.post('/login', function(req, res) {
console.log("user : ", req.body.username);
console.log("password : ", req.body.password);
passport.authenticate('local', { successRedirect: '/',
failureRedirect: '/login' })
});
/* !AUTHENTIFICATION */
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'bower_components')));
app.use(express.static(path.join(__dirname, 'controllers')));
app.use(express.static(path.join(__dirname, 'modules')));
app.use('/', routes);
app.use('/users', users);
When i send a post request in /login, i see in the logs the username and password but the password.authentificate method doesnt do anything.
It should call the LocalStrategy function and console.log('strategy') but it doesn't.
Does someone know how to fix it ?
Thanks
authenticate()'s function signature is standard Connect middleware from here.
So reference of req, res, next should be passed
So you can use it either as route middleware
app.post('/login', passport.authenticate('local', { successRedirect: '/',
failureRedirect: '/login' }));
Or
app.post('/login', function(req, res, next) {
passport.authenticate('local', { successRedirect: '/',
failureRedirect: '/login' })(req, res, next);
});

Node PassportJS authentication: req.isAuthenticated() doesn't stay set

Short summary of the problem: I'm using a new version of express (4.9.0) on a Node.js website which has a few public pages and a few private pages, which I'm putting behind a Google OAuth2 login, using PassportJS. When I request a page behind the sign-in, the user keeps being asked to sign-in; req.isAuthenticated() isn't "sticky". I've seen some comments online that there are can be problems with cookie parser versions being incompatible, so that could be the issue here.
Here is my (rather long) app.js:
var express = require('express');
var http = require('http');
var path = require('path');
var passport = require('passport');
var googleStrategy = require('passport-google-oauth').OAuth2Strategy;
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var app = express();
app.use(cookieParser());
app.use(bodyParser());
app.use(session({ secret: 'mysecret' }));
app.set('view engine', 'html');
app.set('views', path.join(__dirname, 'views'));
app.engine('html', require('ejs').renderFile);
app.set('port', process.env.PORT || 3000);
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
passport.use(new googleStrategy({
clientID: clientId,
clientSecret: secret,
callbackURL: "http://127.0.0.1:3000/auth/google/callback"
},
function (accessToken, refreshToken, profile, done) {
process.nextTick(function () {
return done(null, profile);
});
}
));
app.get('/auth/google',
passport.authenticate('google', { scope: ['https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/userinfo.email'] }),
function(req, res){
});
app.get('/auth/google/callback',
passport.authenticate('google', { failureRedirect: '/login' }),
function(req, res) {
console.log("successfully authenticated with google");
res.redirect('/');
});
app.get('/login', function(req, res){
res.redirect('/auth/google');
});
app.get('/privatepage', ensureAuthenticated, function(req, res) {
var dostuff = module.listThings(function(rows) {
res.render('somepage.html', {
title : "some page",
data : rows
});
});
});
function ensureAuthenticated(req, res, next) {
console.log("in ensureAuth", req.isAuthenticated());
console.log("session data", req.session);
console.log("user data", req.user);
if (req.isAuthenticated()) { return next(); }
res.redirect('/login');
}
var server = app.listen(3000, function() {
var host = server.address().address
var port = server.address().port
console.log('App listening at http://%s:%s', host, port)
})
After the first login, if I visit the /privatepage URL, I get re-directed through Google and land on the homepage again. This is what's in the log from those console.log lines:
in ensureAuth false
session data { cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true },
passport: {} }
user data undefined
I assume this is some session issue where it doesn't store the user's logged in state, but I'm a node newbie & am a little stuck on how to fix this. I'm running on a single computer, so it's not a multiple machines issue. Any debugging suggestions, or ideas on the conflict causing the logged-in state not to be stored?

Resources