Passport login and persisting session

前端 未结 5 1055
悲哀的现实
悲哀的现实 2020-12-22 22:11

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

相关标签:
5条回答
  • 2020-12-22 22:18

    As per the passport documentation, req.user will be set to the authenticated user. In order for this to work though, you will need the express-session module. You shouldn't need anything else beyond what you already have for passport to work.

    As far as testing the session, you can have a middleware function that checks if req.user is set, if it is, we know the user is authenticated, and if it isn't, you can redirect the user.

    You could for example have a middleware function that you can use on any routes you want authenticated.

    authenticated.js

    module.exports = function (req, res, next) {
        // if user is authenticated in the session, carry on
        if (req.user) {
            next();
        }
        // if they aren't redirect them to the login page
        else {
            res.redirect('/login');
        }
    };
    

    controller

    var authenticated = require('./authenticated');
    
    router.get('/protectedpage', authenticated, function(req, res, next) {
        //Do something here
    });
    
    0 讨论(0)
  • 2020-12-22 22:21

    I don't know of a way to check all existing sessions, but Passport is handling the issuing of session ids. Try checking that you have req.user on your test endpoint after logging in

    0 讨论(0)
  • 2020-12-22 22:23

    As @hassansin says you need to use a middleware that implement session management. The passport.session() middleware is to connect the passport framework to the session management and do not implement session by itself. You can use the express-session middleware to implement session management. You need to modify your auth.js in the following way

    var passport = require('passport');
    var session = require('express-session');
    var LocalStrategy = require('passport-local').Strategy;
    
    module.exports = function(app, user){
      app.use(session({secret: 'some secret value, changeme'}));    
    
      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);
        });
      });
    };
    

    Notice that in this case the session engine is using the in memory store and it didn't work if you scale your application and apply load balancing. When you reach this development state something like the connect-redis session store will be needed.

    Also notice that you need to change the secret value used on the session midleware call and use the same value on all application instances.

    0 讨论(0)
  • 2020-12-22 22:30

    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!'
        });
    });
    
    0 讨论(0)
  • 2020-12-22 22:35

    Passport.js does not work well as it stores the session in the server (bad and not scalable). You don't want to store any session data in the server (keeping it stateless) as then you may scale up your clusters and handle more requests.

    If you look at the code in the Passport.js library, there isn't much.. Building it yourself can actually be faster and more efficient.

    Here is a tutorial I wrote on connecting to Google in a much better way.

    0 讨论(0)
提交回复
热议问题