passport deserialize being called too many times - serialization

I don't understand why my deserialize method is being called so many times. Here's my server.js file
var express = require('express');
var app = express();
var passport = require('passport');
var bodyParser = require('body-parser');
var session = require('express-session');
var MongoSessionStore = require('connect-mongo/es5')(session);
// Local ENV ======================================================================
var env = require('./config/config.json')[app.get('env')];
// Mongo Database ======================================================================
var mongoInstance = require('./config/db.config.js');
mongoInstance.connection.on('open', function(){
console.log('connection works');
});
// Configuration ======================================================================
app.use(session({
secret: 'secretsarenofun', // Change this to anything else
resave: false,
saveUninitialized: true,
store: new MongoSessionStore({
mongooseConnection: mongoInstance.connection,
autoRemoveInterval: 60
})
}));
require('./config/passport.config.js')(passport, env, mongoInstance);
app.use(passport.initialize());
app.use(passport.session());
// Routes ======================================================================
var auth = require('./routes/auth.route')(app, passport);
var users = require('./routes/users.route')(passport);
// Middleware ======================================================================
app.use(express.static(__dirname + '/public'));
app.use('/users', users);
app.use('/auth', auth);
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// Launch ======================================================================
var server = app.listen(8000, function(){
console.log('The dagger flies at 8000');
});
var io = require('socket.io').listen(server);
require('./sockets')(io);
And in my passport module I set this
module.exports = function(passport, env, db){
var request = require('request');
var OpenIDStrategy = require('passport-openid').Strategy;
var steamKey = 'test';
var User = require('../models/user.model');
var SteamStrategy = new OpenIDStrategy({
providerURL: 'http://steamcommunity.com/openid',
stateless: true,
returnURL: env.path+'/auth/openid/return',
realm: env.path,
},
function(identifier, done) {
var steamId = identifier.match(/\d+$/)[0];
return done(null, {
identifier: identifier,
steamId: identifier.match(/\d+$/)[0]
});
});
passport.use(SteamStrategy);
passport.serializeUser(function(user, done) {
done(null, user.identifier.match(/\d+$/)[0]);
});
// used to deserialize the user
passport.deserializeUser(function(identifier, done) {
console.log('this calls too many times');
//fetch
done(null, identifier);
});
};
When I just visit the home page after I have auth'd the deserialize function calls like it's supposed to but it's calling up to 8 times.
Why is this? I tried moving the app.use(passport.initialize());
app.use(passport.session()); around with some luck but not completely. Why does this occur?

Move app.use(express.static(__dirname + '/public')) above app.use(passport.initialize());

Related

Can't set a cookie w/ Nuxt.js, Express-Session

I'm new to NUXT and SSR and I've been researching this for a few hours now and I can't seem to figure it out. I'm using JWT to authenticate users in my Nuxt app with a Bearer Token, which is working great until I hit refresh and lose my session.
Now I'm looking to persist sessions using express-session and connect-mongo. I can't get the cookie to set on the client to be included on future requests.
When a user is authenticated:
router.post('/login', function(req, res) {
User.findOne({
username: req.body.username
}, function(err, user) {
if (err) throw err;
if (!user) {
res.status(401).send({success: false, msg: 'Authentication failed. User not found.'});
} else {
// check if password matches
user.comparePassword(req.body.password, function (err, isMatch) {
if (isMatch && !err) {
// if user is found and password is right create a token
var token = jwt.sign(user.toJSON(), config.secret, { expiresIn: 604800 });
req.session.authUser = { 'user': 'Test User' }
return res.json({success: true, token: token, user: user});
} else {
res.status(401).send({success: false, msg: 'Authentication failed. Wrong password.'});
}
});
}
The console.log above shows the authUser in the session.
Session {
cookie:
{ path: '/',
_expires: 2018-04-03T18:13:53.209Z,
originalMaxAge: 60000,
httpOnly: true },
authUser: { user: 'Test User' } }
When I look at my chrome devtools application cookies a connect.ssid hasn't been set and when I console.log(req.session) on future requests the authUser is missing.
My server code is:
// Passport
var passport = require('passport');
var passportJWT = require("passport-jwt");
var ExtractJwt = passportJWT.ExtractJwt;
var JwtStrategy = passportJWT.Strategy;
// Config File
let config = require('./config/settings.js')
// Initialize Express
var app = express();
// CORS-ENABLE
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "http://127.0.0.1:1337");
res.header("Access-Control-Allow-Credentials", 'true');
next();
});
app.use(cors())
const dbPath = 'mongodb://blogUser:blogUserPassword#localhost:27017/blog'
// Express Session
app.use(session({
secret: 'super-secret-key',
resave: false,
saveUninitialized: false,
store: new MongoStore({ url: dbPath }),
cookie: { maxAge: 60000 }
}))
// File Upload
app.use(fileUpload());
// view engine setup
// app.set('views', path.join(__dirname, 'views'));
// app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// Routes
var index = require('./routes/index');
var users = require('./routes/users');
app.use('/api', index);
app.use('/users', users);
// Passport Config
app.use(passport.initialize());
app.use(passport.session())
// mongoose
const options = {
autoIndex: true, // Don't build indexes
reconnectTries: Number.MAX_VALUE, // Never stop trying to reconnect
reconnectInterval: 500, // Reconnect every 500ms
poolSize: 10, // Maintain up to 10 socket connections
// If not connected, return errors immediately rather than waiting for reconnect
bufferMaxEntries: 0
};
console.log(options);
// Localhost Connect
mongoose.connect(dbPath, options).then(
() => { console.log("connected !!!"); },
err => { console.log(err); }
);
Any and all help is appreciated.
If you want to use the server you create the problem with the session is the express router, because change res and req vars so like recommend in nuxt use this.
const express = require('express');
// Create express router
const router = express.Router()
// Transform req & res to have the same API as express
const app = express()
router.use((req, res, next) => {
Object.setPrototypeOf(req, app.request)
Object.setPrototypeOf(res, app.response)
req.res = res
res.req = req
next()
})
You are missing this step
// Create express router
const router = express.Router()
// Transform req & res to have the same API as express
// So we can use res.status() & res.json()
router.use((req, res, next) => {
Object.setPrototypeOf(req, app.request)
Object.setPrototypeOf(res, app.response)
req.res = res
res.req = req
next()
})
The req, res parameters need to be interchanged on the client side
Once you do router.post('/login') and logout
app.use('/api', router)
And that will work perfectly

passportjs TypeError: User.authenticate is not a function

I'm trying to build a small nodejs, express, mongodb app with authentication using passport-local and passport-local-mongoose, however for some reason when entering the middleware for passport in the main app.js file I get this error "TypeError: User.authenticate is not a function"
I tried the authentication by itself in a test project and it worked just fine, so maybe it's something to do with the order of my code but I can't get to what's causing this issue. I've tried several refactors but to no avail.
Below is the code for the app.js and the User Schema , but Here's a link to the project files if needed.
app.js
const express = require('express'),
app = express(),
path = require('path'),
exphbs = require('express-handlebars'),
methodOverride = require('method-override'),
flash = require('connect-flash'),
session = require('express-session'),
bodyParser = require('body-parser'),
mongoose = require('mongoose'),
LocalStrategy = require("passport-local"),
passport = require("passport"),
mongodb = require("mongodb"),
User = require("./models/User");
// Load routes
const ideas = require('./routes/ideas');
const users = require('./routes/users');
// Connect to mongoose
mongoose.connect('mongodb://localhost/diaries');
mongoose.Promise = Promise;
// Handlebars Middleware
app.engine('handlebars', exphbs({
defaultLayout: 'main'
}));
app.set('view engine', 'handlebars');
// Body parser middleware
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Static folder
app.use(express.static(path.join(__dirname, 'public')));
// Method override middleware
app.use(methodOverride('_method'));
// Express session midleware
//PASSPORT CONFIGURATION
app.use(require("express-session")({
secret: "secret",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.use(flash());
// Global variables
app.use(function(req, res, next) {
res.locals.success_msg = req.flash('success_msg');
res.locals.error_msg = req.flash('error_msg');
res.locals.error = req.flash('error');
next();
});
// Index Route
app.get('/', (req, res) => {
const title = 'Welcome';
res.render('index', {
title: title
});
});
// About Route
app.get('/about', (req, res) => {
res.render('about');
});
// Use routes
app.use('/ideas', ideas);
app.use('/users', users);
const port = process.env.PORT;
app.listen(port, () => {
console.log(`Server started on port ${port}`);
});
User Schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const passportLocalMongoose = require("passport-local-mongoose");
// Create Schema
const UserSchema = new Schema({
name:{
type: String,
required: true
},
email:{
type: String,
required: true
},
password:{
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
});
UserSchema.plugin(passportLocalMongoose, {usernameField: "email"});
mongoose.model('users', UserSchema);
try importing LocalStrategy from require('passport-local').Strategy
like
const LocalStrategy = require('passport-local').Strategy

Parse-SDK-JS Express Webapplication and Passportjs Mixed Up Logged in Users Page

issue is:
page content of logged in users mixed up with another logged in user
project attributes:
I run project on
aws ec2 instance with
nginx as proxy to
pm2 started index.js of
expressjs website with
below library for my project
"aws-ses-mail": "^2.1.1",
"body-parser": "^1.15.2",
"cookie-parser": "^1.4.3",
"ejs": "^1.0.0",
"express": "~4.11.x",
"express-ejs-layouts": "^2.2.0",
"express-session": "^1.14.1",
"kerberos": "~0.0.x",
"mandrill": "^0.1.0",
"moment": "^2.14.1",
"parse": "~1.8.0",
"passport": "^0.3.2",
"passport-parse": "0.0.5",
"underscore": "^1.8.3"
also this code did not solve my problem:
app.disable('view cache');
app.use(function (req, res, next) {
res.removeHeader("X-Powered-By");
res.setHeader('Cache-Control', 'no-cache');
next();
});
with the following index.js code:
var express = require('express');
var cookieParser = require('cookie-parser');
var _ = require('underscore');
var moment = require('moment');
var path = require('path');
var ejs = require('ejs');
var bodyParser = require('body-parser');
var session = require('express-session');
var ParseStrategy = require('passport-parse');
var expressLayouts = require('express-ejs-layouts');
var postActions = require('./post-actions');
var Utility = require('./libs/utilities');
var requireUser = require('./require-user');
var userAgentDetector = require('./user-agent-detector');
var passport = require('passport');
Parse = require('parse/node').Parse;
Parse.initialize("hashcode", "hashcode","hashcode");
Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse');
Parse.CoreManager.set('USE_MASTER_KEY', true);
var app = express();
app.use(bodyParser.json()); // for parsing application/json
app.set('views', __dirname+'/views');
app.set('view engine', 'ejs');
app.use(expressLayouts);
// Serve static assets from the /public folder
app.use('/public', express.static(path.join(__dirname, '/public')));
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: true }));
var parseStrategy = new ParseStrategy({parseClient: Parse});
passport.use(parseStrategy);
code continue :
app.use(session({
name: 'session-cookie-id',
secret: 'secret',
saveUninitialized: false,
resave: false
}));
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function(user, done) {
// done(null, user);
done(null, user.getSessionToken());
});
passport.deserializeUser(function(user, done) {
// user.className = "_User";
// user = Parse.Object.fromJSON(user);
// done(null, user);
var sessionToken = user;
var query = new Parse.Query('_Session');
query.equalTo('sessionToken', sessionToken);
query.include('user');
return query.first({useMasterKey: true}).then(function(session) {
user = session.get('user');
if (user) {
done(null, user);
} else {
done();
}
}, function(err) {
done();
});
});
app.use(userAgentDetector);
app.use(postActions);
code continue :
app.locals._ = _;
app.locals.moment = moment;
ejs.filters.videoMessageStr = function(str){
//return some code;
};
ejs.filters.secureImageUrl = function (url) {
return url.replace("http://", "https://s3.amazonaws.com/");
};
ejs.filters.getObjectThumb = function (userObject, params) {
//return some code;
};
ejs.filters.getImageThumb = function (imageObject, params) {
//return some code;
};
app.disable('view cache');
app.use(function (req, res, next) {
res.removeHeader("X-Powered-By");
res.setHeader('Cache-Control', 'no-cache');
next();
});
// Controller code in separate files.
var homeController = require('./controllers/home');
var usersController = require('./controllers/users');
app.get('/', homeController.index);
app.get('/home', homeController.getHomePage);
app.get('/home/page/:page', homeController.getHomePage);
app.get('/messages', requireUser, messagesController.index);
app.get('/login-and-save', usersController.loginAndSave);
code continue :
app.get('/login', usersController.getLogin);
app.post('/login', function(req, res, next){
passport.authenticate('parse',function(err, user, info) {
if (err || !user) {
return res.status(400).json(info);
}
req.logIn(user, function(err) {
if (err) {
return res.status(400).json(err);
}
res.end("ok");
});
})(req, res);
});
app.get('/logout', function(req, res, next){
req.logOut();
res.redirect('/');
});
app.get('*', function(req, res) {
res.render('home/404.ejs', { layout: false, url: req.url });
});
var port = process.env.PORT || 9000;
var httpServer = require('http').createServer(app);
httpServer.listen(port, function() {
console.log('parse-server running on port ' + port + '.');
});
There are several things you need to take into consideration when porting your Cloud Code to parse-server, especially around authentication. The passport-parse library you're using to handle authentication appears to be written with parse.com apps in mind, and has not been updated in two years as of this writing. I highly suspect that module is depending on the old currentUser behavior of hosted Parse.com apps.
Take a look at the Parse Server Guide to learn more about what needs to be updated when moving over to parse-server.

app.use() requires middleware functions

I am facing this error in my Expressjs file . Here is my code. I tried to set it according to this link
https://github.com/expressjs/multer/issues/169 But I am unable to correct this. Kindly help me out.
/**
* Express configuration
*/
'use strict';
var express = require('express');
var favicon = require('serve-favicon');
var morgan = require('morgan');
var compression = require('compression');
var bodyParser = require('body-parser');
var multer = require('multer');
var methodOverride = require('method-override');
var cookieParser = require('cookie-parser');
var errorHandler = require('errorhandler');
var path = require('path');
var config = require('./environment');
var passport = require('passport');
var session = require('express-session');
var mongoStore = require('connect-mongo')(session);
var mongoose = require('mongoose');
module.exports = function(app) {
// var env = app.get('env');
var env = 'development';
app.set('views', config.root + '/server/views');
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
app.use(compression());
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
app.use(methodOverride());
app.use(multer({
dest: '../client/assets/images/uploads/',
rename: function(fieldname, filename) {
return filename + Date.now();
},
onFileUploadStart: function(file) {
console.log(file.originalname + ' is starting...');
},
onFileUploadComplete: function(file, req, res) {
console.log(file.fieldname + ' uploaded to ' + file.path);
var fileimage = file.name;
req.middlewareStorage = {
fileimage: fileimage
}
}
}));
app.use(cookieParser());
app.use(passport.initialize());
// Persist sessions with mongoStore
// We need to enable sessions for passport twitter because its an oauth 1.0 strategy
app.use(session({
secret: config.secrets.session,
resave: true,
saveUninitialized: true,
store: new mongoStore({
mongooseConnection: mongoose.connection
})
}));
if ('production' === env) {
app.use(favicon(path.join(config.root, 'public', 'favicon.ico')));
app.use(express.static(path.join(config.root, 'public')));
app.set('appPath', config.root + '/public');
app.use(morgan('dev'));
}
if ('development' === env || 'test' === env) {
// app.use(require('connect-livereload')());
app.use(express.static(path.join(config.root, '.tmp')));
app.use(express.static(path.join(config.root, 'client')));
app.set('appPath', 'client');
app.use(morgan('dev'));
app.use(errorHandler()); // Error handler - has to be last
}
};
check your multer version as there was a syntax change in how to use multer.
now you have to define something as follows
var upload = multer({.....})
then use upload as your middleware in the express route.

passport.js deserialization ok, but authentication not working

I have a working development version and even my testing version worked until recently. The authentication works sometimes, but mostly the authentication just fails with req.isAuthenticated().
server.js:
var express = require('express');
var app = express();
var port = PORTS[ENVIRONMENT];
var passport = require('passport');
var morgan = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var passportConfigs = require('./config/passport');
var routes = require('./routes.js');
// App setup
app.use("/", express.static(__dirname + '/public/'));
// configuration ===============================================================
/* open mongo connection */
require('./database/' + ENVIRONMENT + '.js');
/* === passport configs === */
passportConfigs(passport, ENVIRONMENT);
// set up our express application
app.use(morgan(morganEnv)); // log every request to the console
app.use(cookieParser()); // read cookies (needed for auth)
//app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
})); // get information from html forms
app.set('view engine', 'ejs'); // set up ejs for templating
// required for passport
app.use(session({
secret: '********' ,
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
passport serialize:
passport.deserializeUser(function(id, done) {
userQueries.findID(id)
.then(function(user) {
var firebaseRef = firebaseRefMod(user, environment).ref;
if(!firebaseRef) {
throw new Error('problem with generating firebase reference, dunno why!');
}
console.log("UserFirst:", { userData: filterUserData( user ), FBRef: firebaseRef })
done(null, { userData: filterUserData( user ), FBRef: firebaseRef } );
}).then(null, function(err) {
console.log(err);
done(err, null);
});
});
routes:
app.post('/auth', isLoggedIn, function(req, res) {
console.log("req", req.user)
res.status(200).send({ "authKey": authGenerator.createToken(authGenerator.types.NORMAL, req.user.userData) , "user": req.user.userData } );
});
function isLoggedIn(req, res, next) {
console.log("userIn", req.isAuthenticated())
// if user is authenticated in the session, carry on
if (req.isAuthenticated())
return next();
// if they aren't redirect them to the home page
errorInRestRequest(res, errorCodes.userNotAuthenticated, req.user);
return false;
}
So basically if the authentication succeeds as it should, the isLoggedIn-function has access to user data from req.user. Even if the authentication does not success, the user is deserialized without problem every time verified by the "console.log("UserFirst:"... entry), but the req.user does not hold the data when it reaches in isLoggedIn-function.
Unfortunately my knowledge of passport and express middlewares are limited, so I'm puzzled as to where the data vanishes in between.
Seems like the problem was caused by wrong node module versions. Do not have the specifics yet, but reverting several modules to older versions fixed the issue.