getting authenticated user info from passportjs and express - node.js

I have an express application that uses passport for OAuth. I have it working successfully with Google and Facebook. My problem is that I can get req.user on controller functions where the routes are configured like this:
router.post('/', auth.isAuthenticated(), controller.create);
but when I try to access the user info from a controller function that doesn't require authentication, req.user is undefined even though the user is logged in. What am I doing wrong here?
and here is how express and passport are configured:
module.exports = function(app) {
var env = app.get('env');
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(cookieParser());
// 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({ mongoose_connection: mongoose.connection })
}));
app.use(passport.initialize());
app.use(passport.session());
.
.
.

Related

My express req.sessions get saved as undefined in Express v4

My express V4 app doesn't give me the correct value of the sessions instead just returns undefined. My app was structured and built using express-generator and this is my app.js file.
var express = require('express'),
path = require('path'),
bodyParser = require('body-parser'),
routes = require('./routes/index'),
app = express(),
compression = require('compression'),
session = require('express-session');
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.set('view cache', true);
app.enable('trust proxy');
app.use(session({
secret: "Share3na Network!195",
resave: true,
saveUninitialized: true,
cookie: { secure: true, httpOnly: true }
}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(compression());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
And these are the routes the take the session value and send it back.
router.get('/getmask', function(req,res){
res.send(req.session.mask);
});
//GET the mask during event body load
router.get('/sendmask', function(req,res){
req.session.mask = striptags(emojiStrip(req.query.m));
});
In another route when I append the requests' IP address with the session value: req.ip() + req.session.mask, what gets saved in the database is "123.456.789undefined"
You need to save the session values after modification. The documentation for the same can be seen in the README of the package.
//GET the mask during event body load
router.get('/sendmask', function(req,res){
req.session.mask = striptags(emojiStrip(req.query.m));
req.session.save();
});

Express creating new session for each request

Express-session is creating a new session (new sessionID) for new request. And it happens intermittently, for example sometimes for first 3-4 hits it will work fine and keep using same existing session and on 4th hit it will create a new one, Sometimes it will create new session on first request itself.
Also this Issue comes on my hosted website. It works fine on localhost.
Things that i have already tried and are not working..
Express session is created after static file routes.
Express session secret and cookieParser secret are set to same.
Using app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); for favicon.
Setting very high value for max-age field while creating cookie.
Below is my app.js snippet -
var passport = require('passport');
var expressSession = require('express-session');
var app = express();
app.engine('hbs', hbs.express4({
partialsDir: __dirname + '/views/partials'
}));
app.set('view engine', 'hbs');
app.set('views', path.join(__dirname, 'views'));
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(express.static(path.join(__dirname, 'public')));
var flash = require('connect-flash');
app.use(flash());
var initPassport = require('./passport/init');
initPassport(passport);
//app.use(bodyParser.urlencoded());
app.use(cookieParser('mysecret'));
app.use(expressSession({ secret: 'mysecret', name:'user', cookie: {maxAge: 60000000}}));
app.use(passport.initialize());
app.use(passport.session());
Any kind of help would be greatly appreciated. Thanks.
why don't you use MongoStore to store session data? may be that will solve your problem.
app.use(session({
secret: 'mysecret',
resave: false,
saveUninitialized: false,
expires: new Date(Date.now() + (60 * 60 * 24 * 7 * 1000)),
cookie: { } ,
store: new MongoStore({mongooseConnection: mongoose.connection})
}));
For those landing here for a similar multi session creation, I solved my issue by setting this flag in the session middleware to false. It saves your cookie in DB only when it has been updated with some additional data like an email for example. `
saveUninitialized: false

req.user undefined in Express 4

I built an app that uses Oauth to authenticate with a third party Jawbone app. I'm attempting to pull req.user.jawbone.token from req.user in one of my routes; however, I'm getting an error stating that req.user is undefined. I had this working in express 3, but after upgrading to express 4 it's no longer working - which leads me to believe that my sessions aren't being stored properly.
Here are the relevant parts of my app.js configuration:
var passport = require('passport');
var session = require('express-session')
var MongoStore = require('connect-mongo')({session: session});
require('./config/passport')(passport);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
// passport
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(session({
store: new MongoStore({
url: mongoUrl
}),
secret: 'password',
resave: false,
saveUninitialized: true
}));
For anyone else that runs into this problem, the issue was due to my middleware being in the wrong order. I rearranged to the below and it's working properly
app.use(session({
store: new MongoStore({
url: mongoUrl
}),
secret: 'password',
resave: false,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());

Express js 4 and multer

I'm writing a Node js application which handles multipart form data and so I'm using multer for the purpose.
The problem is that req.body is always undefined.
Here is my code:
var app = express();
var http = require('http').createServer(app);
//All environments
app.set('port', process.env.PORT || config.ports.HTTP_PORT);
app.set('views', config.folders.views);
app.set('view engine', 'ejs');
//Express 4 dependencies
app.use(morgan('dev'));
app.use(multer({ dest: config.folders.uploads}))
app.use(cookieParser()); //Parser for cookie session
app.use(session({ secret: 'secret' }));
app.use(passport.initialize()); //Init passport
app.use(passport.session()); //Persistent login sessions
app.use(flash()); //Flash messages
//Public folder
app.use(express.static(config.folders.public));
require('./auth')(passport); //Add auth methods to passport
require('./routes')(app, passport); //Add routes
app.post('/test', function(req, res) {
console.log(req.body.test); //req.body always undefined
});
What could be the problem?
EDIT:
Now req.body is filled with data, but the req.files property is still undefined
add bodyParser with this code :
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
HTML forms need to have the enctype attribute set appropriately in order for files to be sent. Example:
<form method="POST" action="/foo" enctype="multipart/form-data">
Editing your original code:
You have to install Multer Multer Docs
npm i multer -S
const app = express();
const http = require('http').createServer(app);
const multer = require('multer'); // added, wasn't in your original code.
//All environments
app.set('port', process.env.PORT || config.ports.HTTP_PORT);
app.set('views', config.folders.views);
app.set('view engine', 'ejs');
//Express 4 dependencies
app.use(morgan('dev'));
// newly added
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(multer({ dest: config.folders.uploads}).single('file')) // added the single() method
app.use(cookieParser()); //Parser for cookie session
app.use(session({ secret: 'secret' }));
app.use(passport.initialize()); //Init passport
app.use(passport.session()); //Persistent login sessions
app.use(flash()); //Flash messages
//Public folder
app.use(express.static(config.folders.public));
require('./auth')(passport); //Add auth methods to passport
require('./routes')(app, passport); //Add routes
Testing the code:
app.post('/test', (req, res) => {
console.log(req.body.test); //req.body always undefined
console.log(req.file); // added this, it should work fine now.
});

Upgrading to Express 4 and my sessions and passport no longer work

I was reading in upgrading to express 4 that the order of app.use has to come after my app.get and app.post routes.
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'public'));
app.set('view engine', 'hjs');
// Initialize Passport! Also use passport.session() middleware, to support
// persistent login sessions (recommended).
app.use(passport.initialize());
app.use(passport.session());
//app.use(favicon(path.join(__dirname,'public','images','favicon.ico')));
app.use(cookieParser());
//app.use(express.json());
//app.use(express.urlencoded());
app.use(session({
secret: 'keyboard cat',
saveUninitialized: true,
resave: true
}));
//authentication
app.get('/app', ensureAuthenticated,appRoutes.app);
app.get('/app/:name', ensureAuthenticated,appRoutes.main);
app.get('/views/app/:name', ensureAuthenticated, appRoutes.index);
app.get('/views/app/:name/*', ensureAuthenticated, appRoutes.partials);
app.get('/',routes.home);
app.use(express.static(path.join(__dirname, 'public')));
app.use(morgan('dev'));
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
app.use(methodOverride());
http.createServer(app).listen(app.get('port'), function() {
console.log('Express server listening on port ' + app.get('port'));
});
I upgraded and now my passport authentication is not working. I moved it above the routes and below and either way I get no error just does not authenticate and set a session.
I was reading in upgrading to express 4 that the order of app.use has to come after my app.get and app.post routes.
Nonsense ! Where did you read that ?
The only thing that comes close to what you're saying is this line from Expres 3.x to 4.x Migrating Guide :
app.router has been removed. Middleware and routes are now executed in the order they're added. Your code should move any calls to app.use that came after app.use(app.router) after any routes (HTTP verbs).
But it does not mean that every app.use call should go after the routes (HTTP Verbs). Only the ones that you used to put after app.use(app.router) in your old Express 3.x code. Is that more clear ?
Regarding your issue, from Passport's docs :
Note that enabling session support is entirely optional, though it is
recommended for most applications. If enabled, be sure to use
express.session() before passport.session() to ensure that the login
session is restored in the correct order.
So you should change :
app.use(passport.initialize());
app.use(passport.session());
//app.use(favicon(path.join(__dirname,'public','images','favicon.ico')));
app.use(cookieParser());
//app.use(express.json());
//app.use(express.urlencoded());
app.use(session({
secret: 'keyboard cat',
saveUninitialized: true,
resave: true
}));
to :
//app.use(favicon(path.join(__dirname,'public','images','favicon.ico')));
app.use(cookieParser());
//app.use(express.json());
//app.use(express.urlencoded());
app.use(session({
secret: 'keyboard cat',
saveUninitialized: true,
resave: true
}));
app.use(passport.initialize());
app.use(passport.session());
Hope that helps.

Resources