jdesboeufs / connect-mongo

MongoDB session store for Express
MIT License
1.96k stars 342 forks source link

Error: Failed to serialize user into session #356

Closed locohost closed 4 years ago

locohost commented 4 years ago

I had PassportJS with LocalStrategy work with straight express-session, storing session info in memory. However, after some reading I learned this is not suitable for production environments. Since I'm already using MongoDb for my app data, I figured this would be best place to persist session data.

So for last 2 days I've been struggling with the error in subject.

What looks good to me...

  1. In the LocalStrategy callback, I can clearly see the User data pulled from MongoDb.
  2. In passport.serializeUser (at start of method) I can clearly see the exact same User data.
  3. In my MonoDb, in "sessions" collection, I can clearly see the session data getting stored.

So all appears to be working, however immediately after passport.serializeUser fires, in passport "authenticator.js" now hard fails to serialize the User data.

Here is the exact error...

Error: Failed to serialize user into session at pass (C:\Users\markd\Google Drive\Documents\Projects\web\nodejs\yardsale-monster\node_modules\passport\lib\authenticator.js:281:19) at serialized (C:\Users\markd\Google Drive\Documents\Projects\web\nodejs\yardsale-monster\node_modules\passport\lib\authenticator.js:286:7) at passport.serializeUser (C:\Users\markd\Google Drive\Documents\Projects\web\nodejs\yardsale-monster\config\passport.js:18:3) at pass (C:\Users\markd\Google Drive\Documents\Projects\web\nodejs\yardsale-monster\node_modules\passport\lib\authenticator.js:294:9) at Authenticator.serializeUser (C:\Users\markd\Google Drive\Documents\Projects\web\nodejs\yardsale-monster\node_modules\passport\lib\authenticator.js:299:5) at SessionManager.logIn (C:\Users\markd\Google Drive\Documents\Projects\web\nodejs\yardsale-monster\node_modules\passport\lib\sessionmanager.js:14:8) at IncomingMessage.req.login.req.logIn (C:\Users\markd\Google Drive\Documents\Projects\web\nodejs\yardsale-monster\node_modules\passport\lib\http\request.js:50:33) at C:\Users\markd\Google Drive\Documents\Projects\web\nodejs\yardsale-monster\routes\users-routes.js:109:8 at Strategy.strategy.success (C:\Users\markd\Google Drive\Documents\Projects\web\nodejs\yardsale-monster\node_modules\passport\lib\middleware\authenticate.js:219:18) at verified (C:\Users\markd\Google Drive\Documents\Projects\web\nodejs\yardsale-monster\node_modules\passport-local\lib\strategy.js:83:10) at Strategy.passport.use.LocalStrategy [as _verify] (C:\Users\markd\Google Drive\Documents\Projects\web\nodejs\yardsale-monster\config\passport.js:9:12) at process._tickCallback (internal/process/next_tick.js:68:7)

Here are my passport config methods...

    passport.use(
        new LocalStrategy({ usernameField: 'handle' }, async (handle, pass, done) => {
            try {
                const user = await User.login(handle, pass);
                console.log('LocalStrategy: ', user);
                return done(null, user);
            } catch (error) {
                return done(null, false, { message: error.message || error });
            }
        })
    );

    passport.serializeUser((user, done) => {
        console.log('serializeUser: ', user);
        done(null, user.id);
    });

    passport.deserializeUser(async (id, done) => {
        try {
            const fields = '_id handle name email role';
            const user = await User.findById(id, fields).exec();
            console.log('deserializeUser: ', user);
            const userInfo = { 
                id: user._id.toString(),
                handle: user.handle,
                name: user.name,
                email: user.email,
                roleIsSiteAdmin: user.role.siteAdmin || false
            }
            return done(null, userInfo);
        } catch (error) {
            console.error('deserializeUser failed: ', error);
            return done(error);
        }
    });

The console.log lines above show this in console...

LocalStrategy: { user: { id: '5e87d43ce385a75338efa1eb', handle: 'rayray', name: 'Ray Lewis', email: 'rayray@mail.com', roleIsSiteAdmin: false } } serializeUser: { user: { id: '5e87d43ce385a75338efa1eb', handle: 'rayray', name: 'Ray Lewis', email: 'rayray@mail.com', roleIsSiteAdmin: false } }

I would greatly appreciate any suggestions :-)

Mark

locohost commented 4 years ago

Ugh... please close this :-(

In User.login I was returning { user }, which results in a "user" object below the User data. So the id string was actually in user.user.id. I fixed the return in User.login and all works. I think posting out error details and a good explanation for help is therapeutic and mind-clearing. This very often leads one to the solution :-)

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.