Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passport login and persisting session

Background

I have a MEAN application with CRUD capabilities fully tested with postman. I have been trying to persist login for quite some time now with no luck. I have read and tried the following

  • passport docs
  • toon io's blog about login
  • Express session
  • Scotch io, node auth made easy
  • Plus a buch of other light reading materials (Lots of SO questions)

But I have only been able to register and log a user in, not persist login with a session.

My App

Here is a link to the full github repo (if you are looking for the latest changes check develop branch)

My Understanding of Auth/Login

Here is my understanding of user login with code examples from my project and screenshot of postman results as well as console logs.

Passport setup

I have the following auth.js file, it configs passport

var passport = require('passport'); var LocalStrategy = require('passport-local').Strategy;  module.exports = function(app, user){    app.use(passport.initialize());   app.use(passport.session());    // passport config   passport.use(new LocalStrategy(user.authenticate()));    passport.serializeUser(function(user, done) {     console.log('serializing user: ');     console.log(user);     done(null, user._id);   });    passport.deserializeUser(function(id, done) {     user.findById(id, function(err, user) {       console.log('no im not serial');       done(err, user);     });   }); }; 

This gets called in the server file like

//code before var user    = require('./models/user.js'); var auth    = require('./modules/auth.js')(app, user); // code after 

Routing for login

In my routes I have the login route as follows

router.post('/login', function(req, res, next) {    passport.authenticate('local', function(err, user, info) {      if (err) {         return next(err);     }      if (!user) {         return res.status(401).json({             err: info         });     }      req.logIn(user, function(err) {          if (err) {             return res.status(500).json({                 err: 'Could not log in user'             });         }          res.status(200).json({             status: 'Login successful!'         });      });   })(req, res, next); }); 

This route works as tested with postman. I enter the details 'joe' and 'pass' and get the following response.

enter image description here

When this route is hit we can also see in the console that the user is serialized.

enter image description here

So what next?

This is where I get lost. I have a few questions.

  1. Is the user now in a session on my server?
  2. Should I send the req.session.passport.user back to the client?
  3. Do I need the session ID on all future requests?

Testing the Session

I have a second route setup for testing the session it is as follows

router.get('/checkauth', passport.authenticate('local'), function(req, res){      res.status(200).json({         status: 'Login successful!'     });  }); 

The part passport.authenticate('local') (I thought) is there to test if the user session exists before giving access to the route but I never get a 200 response when I run this, even after a login.

Does this route expect a req.session.passport.user passed in the head or as a data argument on a http request that requires auth?

If I missed anything or am understanding something wrong please tell me, any input is appreciated. Thanks all.

like image 416
Joe Lloyd Avatar asked Apr 07 '16 20:04

Joe Lloyd


People also ask

Does passport use session?

Passport uses serializeUser function to persist user data (after successful authentication) into session. The function deserializeUser is used to retrieve user data from session and perform some condition-based operations. Now all the endpoints hitting the backend server will go through passport. deserializeUser() .

What is Passport login system?

Passport is a popular, modular authentication middleware for Node. js applications. With it, authentication can be easily integrated into any Node- and Express-based app. The Passport library provides more than 500 authentication mechanisms, including OAuth, JWT, and simple username and password based authentication.

What are Passportjs strategies?

Strategies are responsible for authenticating requests, which they accomplish by implementing an authentication mechanism. Authentication mechanisms define how to encode a credential, such as a password or an assertion from an identity provider (IdP), in a request.

Can passport use multiple strategies?

Passport's middleware is built in a way that allows you to use multiple strategies in one passport.


1 Answers

Is the user now in a session on my server?

No, You need to use the express-session middleware before app.use(passport.session()); to actually store the session in memory/database. This middleware is responsible for setting cookies to browsers and converts the cookies sent by browsers into req.session object. PassportJS only uses that object to further deserialize the user.

Should I send the req.session.passport.user back to the client?

If your client expects a user resource upon login, then you should. Otherwise, I don't see any reason to send the user object to the client.

Do I need the session ID on all future requests?

Yes, for all future requests, the session id is required. But if your client is a browser, you don't need to send anything. Browser will store the session id as cookie and will send it for all subsequent requests until the cookie expires. express-session will read that cookie and attach the corresponding session object as req.session.

Testing the Session

passport.authenticate('local') is for authenticating user credentials from POST body. You should use this only for login route.

But to check if the user is authenticated in all other routes, you can check if req.user is defined.

function isAuthenticated = function(req,res,next){    if(req.user)       return next();    else       return res.status(401).json({         error: 'User not authenticated'       })  } router.get('/checkauth', isAuthenticated, function(req, res){      res.status(200).json({         status: 'Login successful!'     }); }); 
like image 195
hassansin Avatar answered Oct 02 '22 12:10

hassansin