req.session.passport and req.user empty, serializeUser and deserializeUser are never called - node.js

I'm using Express (v4.11.2) with Passport in order to support multiple providers (local, facebook, twitter and google) for access to the web app I'm building. As a backend I'm using mysql. For now I have two local strategies: local-signup and local-signin. The issue I'm experiencing is that the req.session.passport and req.user are always empty and that, in fact, serializeUser and deserializeUser are never being called.
Here is the setup of express and passport:
var bodyParser = require('body-parser');
var session = require('express-session');
var MemoryStore = session.MemoryStore;
var _ = require('underscore');
var passport = require('passport');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(session({
key: 'KEY',
secret: 'SECRET331156%^!fafsdaasd',
store: new MemoryStore({reapInterval: 60000 * 10}),
saveUninitialized: true,
resave: false
}));
app.use(passport.initialize());
app.use(passport.session());
require('./config/passport')(passport); // pass passport for configuration
and here is the passport file with authentication strategies:
module.exports = function (passport) {
passport.serializeUser(function (user, done) {
logger.info('SERIALIZE USER');
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
logger.info('DESEIRALIZE USER!');
mysqllib.getConnection(function (err, connection) {
if (err) {
done(err);
}
var sql = "SELECT * FROM users WHERE idusers = ?";
logger.info('sql: ' + sql);
connection.query(sql, [id], function (err, rows) {
connection.release();
var user = {};
user.id = rows[0].idusers;
done(err, user.id);
});
});
});
passport.use('local-signup', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true // allows us to pass back the entire request to the callback
},
function (req, email, password, done) {
logger.info('CALLING local-signup');
var firstname = req.body.firstname;
var lastname = req.body.lastname;
var role = req.body.role;
mysqllib.getConnection(function (err, connection) {
var sql = "INSERT INTO users VALUES(0, ?, ?, ?, ?, null, ?, 0, null, null, null, null, null, null, 0, 0)";
logger.info('sql: ' + sql);
connection.query(sql, [email, password, firstname, lastname, role], function (err, rows) {
connection.release();
if (err) {
if (err.code == 'ER_DUP_ENTRY') {
logger.info('er_dup_entry');
return done(err);
} else {
logger.info('general err');
return done(err);
}
} else {
logger.info('everything is OK!');
var user = {};
user.id = rows.insertId;
req.session.user_auth = user.id;
return done(null, user);
}
});
});
}));
passport.use(
'local-login',
new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true // allows us to pass back the entire request to the callback
},
function (req, email, password, done) {
mysqllib.getConnection(function (err, connection) {
if (err) {
logger.info('getConnection: ' + err);
return done(err);
}
var sql = "SELECT idusers, first_name, last_name, email, phone, dob, address, role, photo1, photo2, photo3, photo4, phonevalidated, uservalidated FROM users WHERE email = " + connection.escape(email) + " AND password = " + connection.escape(password);
connection.query(sql, function (err, rows) {
connection.release();
if (err) {
logger.error("select user", err);
return done(err);
} else if (rows.length) {
var user = rows[0];
user.id = rows[0].idusers;
return done(null, user);
} else {
logger.warn('Incorrect Login credentials, username: ' + email + ' password: ' + password);
return done(null, false, {message: 'unauthorized'});
}
});
});
})
);
};
and, for last, here is how I'm using the strategies in express routes:
app.post('/login', function (req, res, next) {
passport.authenticate('local-login', function (err, user, info) {
if (err) {
mysend(res, 500, 'Ups. Something broke!');
} else if (info) {
mysend(res, 401, 'unauthorized');
} else {
mysend(res, 200, JSON.stringify(user));
logger.info(req.user);
logger.info(req.session);
}
})(req, res, next);
});
Everything works fine, even in a strategy I can set the value of user's id in the session like this:
req.session.user_id = user.id
and continue to use it manually but I really don't get why serializeUser and deserializeUser aren't being called.

You need to call req.login() in custom callback which will then call serializeUser and set the user object to the session:
app.post('/login', function (req, res, next) {
passport.authenticate('local-login', function (err, user, info) {
if (err) {
mysend(res, 500, 'Ups. Something broke!');
} else if (info) {
mysend(res, 401, 'unauthorized');
} else {
req.login(user, function(err) {
if (err) {
mysend(res, 500, 'Ups.');
} else {
mysend(res, 200, JSON.stringify(user));
}
}
}
})(req, res, next);
});

Related

Policy evaluation not working in sails.js with passport

I've created a small API module, to have authenticated access for certain controllers using JWT.
Using local authentication to get the token, and JWT for subsequent end points
However the policies are not getting evaluated, it looks like middleware is not getting executed and sails is not evaluating the policy isSubscriber.js in the api/policies folder.
Here are the relevant code snippets:
/*
* Passport login strategy.
*/
const { JsonWebTokenError } = require('jsonwebtoken');
var passport = require('passport'),
LocalStrategy = require('passport-local').Strategy,
JwtStrategy = require ('passport-jwt').Strategy,
ExtractJwt = require ('passport-jwt').ExtractJwt,
md5 = require('md5');
passport.serializeUser (function(user, done){
done (null, user.id);
});
passport.deserializeUser(function (id, done){
Subscriber.findOne ({id: id}, function (err, user){
done(err, user);
})
});
var opts = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secrtOrKey : 'xxxxx',
issuer: 'xxxxxx',
audience: 'xxxxx'
};
passport.use (new JwtStrategy(opts, function (jwt_payload, done){
sails.log ("Authenticating with JWT strategy");
Subscriber.findOne ({id: jwt_payload.id}, function (err, subscriber){
if (err){
return done (err, false);
}
if (user) {
return done(null, user);
} else {
return done(null, false);
}
});
}));
passport.use (new LocalStrategy({
usernameField: 'phone',
passwordField: 'password'
},
function (phone, password, done) {
sails.log ("Locating subscriber: " + phone + " Password: " + password);
Subscriber.findOne ({phone: phone}, function (err, subscriber){
if (err) { return done (err);}
sails.log ("Subscriber : " , subscriber);
if (!subscriber) {
sails.log ('User with phone ' + phone + ' not found!');
return done (null, false, {message : 'Subscriber not found.'});
}
sails.log ("Checking password: ");
if (md5(password) != subscriber.password_hash) {
sails.log ('Password mismatch for user ' + phone);
return done (null, false, {message: 'Invalid password'});
}
sails.log ("Successfully logged in");
return done(null, subscriber, {
message: 'Logged in succesfully.'
});
})
}
));
Middleware section in http.js
middleware: {
passportInit: require('passport').initialize(),
passportSession: require('passport').session(),
order: [
'cookieParser',
'session',
'passportInit',
'passportSession',
'bodyParser',
'compress',
'poweredBy',
'router',
'www',
'favicon',
]
policies:
module.exports.policies = {
'*': ['isSubscriber'],
'AuthController': {
'login': true // Always allow access to the user login action
}
};
isSubscriber.js:
module.exports = function (req, res, next){
sails.log ("Authenticating using jwt");
passport.authenticate ('jwt', function (error, user, info){
if (error) return res.serverError (error);
if (!user) {
return res.status(403).send ("Failed to authenticate");
}
req.user = user;
sails.log ("User authenticated, user record: " , req.user);
next();
})(req, res);
};

PassportJS Local Strategy not working Withh MongoDB

I'm trying to get a handle on user authentication with PassportJS, and I cannot get it to work my database setup.
I'm using MongoDB without Mongoose, and I can't get the LocalStrategy module to work.
Hopefully my database queries aren't too cumbersome to read.
Local Strategy:
passport.use(new LocalStrategy(
function(username, password, done) {
//Fire up database
mongo.connect("mongodb://localhost:27017/formulas", function(e, db) {
if (e) {return next(e);}
var col = db.collection("users");
//Do a database query to find a record by username
col.findOne({"username": username}, function(err, user){
if (err) { return done(err);}
if(!user) {
return done(null, false, { message: "Please check your log in credentials." });
}
//if it exists call done() object with user information
bcrypt.compare(password, user.password, function(err, res){
if (err) throw err;
if (res == true) {
return done(null, {username: username, password: password});
} else {
return done(null, false, { message: "Invalid password."});
}
});
});
});
}));
I call passport.authenticate() like this:
router.post('/login',
passport.authenticate('local', {successRedirect:'/', failureRedirect:'/about',failureFlash: false}),
function(req, res){
console.log(req.body);
console.log(req.user);
console.log("The user was logged");
});
SerializeUser and deserializeUser look like this:
passport.serializeUser(function(user, done) {
done(null, user.username);
});
passport.deserializeUser(function(id, done) {
mongo.connect("mongodb://localhost:27017/formulas", function(e, db){
if (e) {return next(e);}
var col = db.collection("users");
col.findOne({"username": id}, function(err, user){
done(err, {"username": id});
});
});
});
When I call app.post(/login) I'm taken directly to /about and nothing is logged to the console so I'm not quite sure what's going wrong.
Advice on what to fix or how to troubleshoot is greatly appreciated.
Firstly when u serialize user object , then in deserialize also whole user object must be passed.
Consider the example below.
For routes :
router.post('/login', function(req, res, next) {
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); }
req.session.user = req.user;
return res.redirect('/home');
});
})(req, res, next);
});
For passport.js , place the localstrategy and passport in same folder
var passport = require('passport'),
session = require('express-session');
var local = require('./localstrategy.js');
module.exports = function (app) {
app.use(session({
secret: 'Site visit',
resave: true,
saveUninitialized: true,
cookie: { secure: false }
}));
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function(user, done){
done(null, user);
});
passport.deserializeUser(function(user, done){
done(null, user);
});
local();
};
For local strategy :
'use strict';
var passport = require('passport'),
local = require('passport-local').Strategy;
var user;
// path where the db.js is placed
var db = require('./../db.js');
var ObjectId = db.getObjectID();
var bcrypt = require('bcrypt');
module.exports = function(){
passport.use(new local({
usernameField : 'username',
passwordField : 'password'
}, function(username, password, done){
var collection = db.getDb().collection('users');
collection.findOne({
username: username,
}, function (err, result) {
if(result == null){
cb(null, false);
}else {
bcrypt.compare(password, result.password, function (err, passRes) {
if (passRes == true) {
user = user;
done(err, user);
}else{
done(null, false, { message : 'Invalid Password'});
}
});
}
});
}));
};

passport local-strategy executing the successcase always

I am trying an example of local-strategy passport. When I do a POST request with incorrect password (I only have a single db record at this moment) it still does ends up executing my success function :
function (err, user) {
console.log("Login successful");
res.redirect('/loggedIn');
}
defined in passport.authenticate.Where am I going wrong ? When is the failureRedirect invoked.
var express = require('express');
var app = express();
var http = require('http');
var server = http.Server(app);
var querystring = require('querystring');
var bodyParser = require('body-parser');
var passport = require('passport');
var Strategy = require('passport-local').Strategy;
var users = {
user : {username : "abc", password : "123"},
findByUsername (username, cb) {
return cb(null, this.user);
}
};
app.use(bodyParser.json());
app.use(passport.initialize());
app.use(passport.session());
passport.use(new Strategy(
function verify (username, password, done) {
users.findByUsername(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);
});
} // close verify function
));
app.get('/signupError', function (req, res) {
var result = {error : 'You entered incorrect username/password'};
res.status(200).json(result);
});
app.get('/loggedIn', function (req, res) {
var result = {error : 'You entered correct username/password'};
res.status(200).json(result);
});
app.post('/login', function (req, res) {
passport.authenticate('local', { failureRedirect: '/signupError' },
function (err, user) {
console.log("Login successful");
res.redirect('/loggedIn');
})(req,res);
});
server.listen(80, function() {
console.log("listening") ;
});
try using this argument in passport.use
passport.use( new Strategy({usernameField: 'username',
passwordField: 'password',
session: false
},
function verify (username, password, done) {
users.findByUsername(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);
});

Passport doesn't save the session

I have read a lot about this issue but any answer doesn't work for me. I am working with React, Express and Passport to manage my authenticate routine. The authentication routine is fine, and it makes the redirect that I want. But, when I refresh any route, it says me that I am not authenticate. It seems that Passport doesn't save the session. Here my code:
Server.js
const lisaApp = express();
lisaApp.use(bodyParser.json())
lisaApp.use(bodyParser.urlencoded({ extended: false }))
lisaApp.use(cookieParser())
lisaApp.use(session({
secret: config.secret,
resave: false,
saveUnitialized: false
}))
lisaApp.use(passport.initialize())
lisaApp.use(passport.session())
passport.use(auth.localStrategy);
passport.serializeUser(auth.serializeUser);
passport.deserializeUser(auth.deserializeUser);
lisaApp.post('/login', (req, res, next) => {
const validationResult = validateLoginForm(req.body);
if (!validationResult.success) {
return res.status(400).json({
success: false,
message: validationResult.message,
errors: validationResult.errors
});
}
return passport.authenticate('local', (err, userData) => {
if (err) {
if (err.response.statusText === 'Unauthorized') {
return res.status(400).json({
success: false,
message: 'The password is not right'
});
}
return res.status(500).json({
success: false,
message: 'Wrong data'
});
}
console.log('is authenticated?: ' + req.isAuthenticated()) // Here always is false
return res.json({
success: true,
token,
message: 'Successful Login',
user: userData.data
});
})(req, res, next);
});
// I am using this function as a middleware to check if the user is authenticated, always is false. No matter if I put right data in the login form
function ensureAuth (req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.status(401).send({ error: 'not authenticated' })
}
auth/index.js(passport routine)
var LocalStrategy = require('passport-local').Strategy;
var LisaClient = require('pos_lisa-client');
var config = require('../config');
var ClientApi = LisaClient.createClient(config.lisaClient);
exports.localStrategy = new LocalStrategy({
usernameField: 'username',
passwordField: 'password',
session: false,
passReqToCallback: true
}, (req, username, password, done) => {
var authData = {
username,
password
}
// Here is a custom API, I pass the data that I need. This works fine
ClientApi.authenticate(authData, (err, token) => {
if (err) {
return done(err)
}
var token = token.data
ClientApi.getClient(username, (err, user) => {
if (err) {
return done(err)
}
user.token = token
return done(null, user)
})
})
})
exports.serializeUser = function (user, done) {
// The app never enters here
done(null, {
username: user.username,
token: user.token
})
}
exports.deserializeUser = function (user, done) {
// The app never enters here
ClientApi.getClient(user.username, (err, usr) => {
if (err) {
return done(null, err)
} else {
usr.token = user.token
done(null, usr)
}
})
}
Where I am wrong?
If you're using a custom authentication callback, you have to call req.logIn() to establish a session (or you can create one manually):
// Add this where you are console.log'ing `req.isAuthenticated()`
req.logIn(userData, function(err) {
if (err) return next(err);
console.log('is authenticated?: ' + req.isAuthenticated());
return res.json({
success: true,
token,
message: 'Successful Login',
user: userData.data
});
});
This is documented here (scroll down to "Custom Callback"):
Note that when using a custom callback, it becomes the application's responsibility to establish a session (by calling req.login()) and send a response.

MongoStore, Passport-local - Sessions are not being stored in db

I have a Node.js Express App and I am trying to use MongoStore to save the sessions and Passport-local for authentication. The app is not storing sessions in db.sessions
app.js
var session = require("express-session");
var MongoStore = require("connect-mongo/es5")(session);
var passport = require('passport');
app.use(session({
secret: 'secret',
resave: false,
saveUninitialized: false,
duration: 30 * 60 * 1000,
activeDuration: 5 * 60 * 1000,
store: new MongoStore({
url: MongoDB.MONGODB_URL
})
}));
app.use(passport.initialize());
passport.serializeUser(function(user, done) {
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
db.users.findById(id, function(err, user){
if(!err) done(null, user);
else done(err, null);
});
});
localstrategy is implemented as follows. MongoDB is my own module which interacts with MongoDB.
passport.use('local', new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
},
function (email, password, done) {
process.nextTick(function () {
MongoDB.collection("users").findOne({
email: email
}, function (error, doc) {
if (error) {
return done(error);
}
if (doc) {
if (doc.password === PasswordManager.encryptPassword(password)) {
return done(null, doc);
} else {
return done("Invalid Password", false);
}
}
});
});
}
));
Authentication Request.
As I am trying to use MongoStore sessions, I have passed the option - {session: false} to the req.LogIn function.
router.post('/login', function (req, res, next) {
passport.authenticate('local', function (err, user) {
if (err) {
return next(err);
}
if (!user) {
return res.status(401).send({
success: false,
error: "User not found!",
data: null
});
}
req.logIn(user, {session: false}, function (err) {
if (err) {
return next(err);
}
req.session.user = user;
return res.send({
success: true,
error: null,
data: user
});
})
})(req, res, next);
});

Resources