I am having problems using sessions in Passport/ExpressJS.
When I log req.session
, I can see that passport is {}
:
{ cookie:
{ path: '/',
_expires: Mon Sep 29 2014 19:37:16 GMT-0300 (BRT),
originalMaxAge: 3594522,
httpOnly: true,
secure: true },
passport: {} }
Also, I am authenticating with Facebook, and passport.deserializeUser
is not being called.
This is my code:
passport.use(new FacebookStrategy({
// pull in our app id and secret from our auth.js file
clientID : configAuth.facebookAuth.clientID,
clientSecret : configAuth.facebookAuth.clientSecret,
callbackURL : configAuth.facebookAuth.callbackURL
},
// facebook will send back the token and profile
function(token, refreshToken, profile, done) {
// asynchronous
process.nextTick(function() {
console.log("profile " + profile.id);
console.log("profile.name "+profile.name.givenName)
// find the user in the database based on their facebook id
User.findOne({ 'facebook.id' : profile.id }, function(err, user) {
// if there is an error, stop everything and return that
// ie an error connecting to the database
if (err)
return done(err);
// if the user is found, then log them in
if (user) {
//returning undefined
//console.log(user.name + " " + user.email);
return done(null, user); // user found, return that user
} else {
// if there is no user found with that facebook id, create them
var newUser = new User();
// set all of the facebook information in our user model
newUser.facebook.id = profile.id; // set the users facebook id
newUser.facebook.token = token; // we will save the token that facebook provides to the user
newUser.facebook.name = profile.name.givenName + ' ' + profile.name.familyName; // look at the passport user profile to see how names are returned
newUser.facebook.email = profile.emails[0].value; // facebook can return multiple emails so we'll take the first
// save our user to the database
newUser.save(function(err) {
if (err)
throw err;
// if successful, return the new user
return done(null, newUser);
});
}
});
});
}));
// used to serialize the user for the session
passport.serializeUser(function(user, done) {
console.log("serialize");
done(null, user.id);
});
// used to deserialize the user
passport.deserializeUser(function(id, done) {
console.log("deserialize");
User.findById(id, function(err, user) {
console.log(user);
done(err, user);
});
});
I've tried moving both methods to the beginning but it didn't make any difference. passport.serializeUser
is called just fine.
This is where I initiliaze passport
:
app.use (cookieParser());
app.use(session({ secret: 'appsecret', saveUninitialized: true, cookie: { secure: true, maxAge: new Date(Date.now() + 3600000) }, key:'connect.sid' }));
app.use(passport.initialize());
app.use(passport.session());
And this is my route
:
// =====================================
// FACEBOOK ROUTES =====================
// =====================================
// route for facebook authentication and login
app.get('/auth/facebook', passport.authenticate('facebook', { scope : 'email' }));
// handle the callback after facebook has authenticated the user
app.get('/auth/facebook/callback',
passport.authenticate('facebook', {
successRedirect : '/home',
failureRedirect : '/login'
}));
Can someone help me with this?
Thanks!
Passport uses serializeUser function to persist user data (after successful authentication) into session. Function deserializeUser is used to retrieve user data from session.
Passport is Express-compatible authentication middleware for Node. js. Passport's sole purpose is to authenticate requests, which it does through an extensible set of plugins known as strategies.
Passport. js is a popular Express middleware specifically created to facilitate the login process. It is flexible, trusted by many organizations worldwide, and easy to integrate into your ExpressJS code. In this tutorial we'll: Create a login form for a Node application using Passport.
The Passport library provides more than 500 authentication mechanisms, including OAuth, JWT, and simple username and password based authentication. Using Passport makes it easy to integrate more than one type of authentication into the application, too.
For me the issue with deserializeUser not being called and empty passport object was cross-domain issue. When I was sending ajax request from localhost:4200 to localhost:1000 cookies and sessions didn't work for my Ember.js client. However, Postman extension received correct response. Also passport object was filled with data correctly. User.deserializeUser was getting called correctly.
To solve this I had to set correct server-side and client HTTP headers. Server-side(node.js + express + passport):
# The important part. Must go AFTER the express session is initialized
app.use passport.initialize()
app.use passport.session()
# Enable CORS
# X-Requested-With, X-AUTHENTICATION, X-IP
# https://stackoverflow.com/a/18290875/2166409
app.use (req, res, next) ->
res.header 'Access-Control-Allow-Origin', 'http://localhost:4200'
res.header 'Access-Control-Allow-Headers', 'Origin, X-Requested-With, X-AUTHENTICATION, X-IP, Content-Type, Accept'
res.header 'Access-Control-Allow-Credentials', true
res.header 'Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'
next()
app.use '/api/v1', router
Client-side:
If using jQuery add this to $.ajax options:
xhrFields: { withCredentials:true }
Then everything works as expected:
DESERIALIZE USER
{ id: '547fabf22a098ade53e6e48e',
name: 'test',
firstName: 'test',
email: '[email protected]' }
LOGIN SUCCESS SESSION
{ cookie:
{ path: '/',
_expires: Thu Dec 04 2014 20:26:52 GMT+0100 (CET),
originalMaxAge: 3597205,
httpOnly: false },
passport:
{ user:
{ id: '547fabf22a098ade53e6e48e',
name: 'test',
firstName: 'test',
email: '[email protected]' } } }
These answers helped me: about Ember.js, jQuery.ajax.
For me, the root cause was the cookie security value in the express-session.
app.use(require('express-session')({
secret: 'crackalackin',
resave: true,
saveUninitialized: true,
cookie : { secure : false, maxAge : (4 * 60 * 60 * 1000) }, // 4 hours
}));
On my local machine, I wasn't running over HTTPs so when cookie.secure is true, the session and user object were empty. When in dev mode and secure was false, it worked correctly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With