passport icon indicating copy to clipboard operation
passport copied to clipboard

passport is empty in session but has user in sessionStore

Open bogas04 opened this issue 9 years ago • 34 comments
trafficstars

I've spent 4 hours scrolling through all SO posts about req.isAuthenticated() giving false always and then realizing that my session.passport lacks user itself and then figuring out that it appears in sessionStore once (I am using MemoryStore for now) and on second request it disappears, god knows why.

Please help me out.

import express from 'express';
import passport from 'passport';
import bodyParser from 'body-parser';
import constants from '../constants';
const app = express();

app.use('/', express.static(__dirname + '/../client'));

// Config
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json({ limit: '25mb' }));
app.use(require('express-session')({ 
  secret: 'yolo 123',
  resave: true,
  saveUninitialized: false,
  cookie: { maxAge : 24*60*60*1000 }, 
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(require('./passport-local'));

app.get('/test', (req, res) => { 
  console.log(req.sessionStore, req.sessionID, req.session);
  res.status(200).end(req.isAuthenticated() ? 'logged in': 'logged out');
});

app.post('/login', passport.authenticate('local'), (req, res) => {
  let user = req.user.toJSON();
  delete user.password;
  res.status(200).json({ user })
});
...

./passport-local.js

import { Strategy } from 'passport-local';
import constants from '../constants';
import passport from 'passport';
import { User } from './db';

passport.serializeUser((user, done) => done(null, user.id));

passport.deserializeUser((user, done) => (
  User.where({ id: user.id })
  .fetch()
  .then(u => done(null, u))
));

module.exports = new Strategy({ usernameField: 'username', passwordField: 'password' }, (username, password, done) => (
  User.where({ username }).fetch()
  .then(user => {
    if(user) {
      if (!password.compare(password, user.toJSON().password)) {
        return done(null, false, { message: 'Incorrect password.' });
      } else {
        return done(null, user);
      }
    } else {
      return done(null, false, { message: 'Incorrect username.' });
    }
  })
  .catch(console.log)

Flow: Login -> I receive user object with correct details from DB -> I visit /test

GET /test
MemoryStore {
  sessions: { N6YkV5_LIZRBTDcXDPMhgNSRRxtbZDIX: '{"cookie":{"originalMaxAge":86400000,"expires":"2016-01-09T12:09:21.366Z","httpOnly":true,"path":"/"},"passport":{"user":"2"}}' },
  generate: [Function],
  _events: { disconnect: [Function], connect: [Function] },
  _eventsCount: 2 } 'N6YkV5_LIZRBTDcXDPMhgNSRRxtbZDIX' Session {
  cookie: 
   { path: '/',
     _expires: Sat Jan 09 2016 17:39:21 GMT+0530 (IST),
     originalMaxAge: 86400000,
     httpOnly: true },
  passport: {} }

I revisit /test

GET /test
MemoryStore {
  sessions: { N6YkV5_LIZRBTDcXDPMhgNSRRxtbZDIX: '{"cookie":{"originalMaxAge":86400000,"expires":"2016-01-09T12:09:24.179Z","httpOnly":true,"path":"/"},"passport":{}}' },
  generate: [Function],
  _events: { disconnect: [Function], connect: [Function] },
  _eventsCount: 2 } 'N6YkV5_LIZRBTDcXDPMhgNSRRxtbZDIX' Session {
  cookie: 
   { path: '/',
     _expires: Sat Jan 09 2016 17:39:24 GMT+0530 (IST),
     originalMaxAge: 86400000,
     httpOnly: true },
  passport: {} }
  • Why is MemoryStore having {user:2} (that is the id) but not req.session on first request to /test
  • Why does it disappear in second request?

EDIT: Just used database (postgres) for session store, exact same behaviour. What piece of code is making an update entry on the passport: {} in session store and thus emptying it?

EDIT2: I'm adding/removing user to/from session myself in my login and logout routes for now, and they are persistent. I guess this has to do with passport getting confused or something like that.

bogas04 avatar Jan 08 '16 12:01 bogas04

I am having the exact same problem. Instead of using a /test endpoint, I just create a all-route endpoint that logs out the session info no matter what:

  app.use((req, res, next) => {
    var status = req.isAuthenticated() ? 'logged in' : 'logged out';
    console.log(
      'status:', status, '\n',
      req.sessionStore,
      req.sessionID,
      req.session
    );
    next();
  });

So when I am not logged in:

status: logged out 
 MemoryStore {
  sessions: {},
  generate: [Function],
  _events: { disconnect: [Function], connect: [Function] },
  _eventsCount: 2 } i41u4l-rapAOtbT-loUfTFR4K8Tpxw5m Session {
  cookie: 
   { path: '/',
     _expires: null,
     originalMaxAge: null,
     httpOnly: true } }

Then after I login:

status: logged out 
 MemoryStore {
  sessions: {},
  generate: [Function],
  _events: { disconnect: [Function], connect: [Function] },
  _eventsCount: 2 } B_P8564UmyyTJnQgCyJ9z_IaOWVcgHZ7 Session {
  cookie: 
   { path: '/',
     _expires: null,
     originalMaxAge: null,
     httpOnly: true } }

I setup like this:

/*  Server I/O  ---------------------------------------------------------- */
{

  // i/o middlewares
  app.use(cookieParser());
  app.use(bodyParser.json());
  app.use(bodyParser.urlencoded({extended: false}));
  app.use(session({
    secret: 'K7@*{GwHdq1@+ChhB%|M|r$1JkW|15ip^Kwguq#^ETD',
    name: '_codepix',
    resave: false,
    saveUninitialized: false
  }));

  app.use(passport.initialize());
  app.use(passport.session());
}

/* Router setup */
{
  app.use((req, res, next) => {
    var status = req.isAuthenticated() ? 'logged in' : 'logged out';
    console.log(
      'status:', status, '\n',
      req.sessionStore,
      req.sessionID,
      req.session
    );
    next();
  });

  // Static paths
  app.use(express.static(staticpath));
  app.use('/c0dez/data', express.static('data'));

  // api endpoint
  app.use('/api', (req, res, next) => {
    if (app.get('rasterizer')) {
      req.rasterizer = app.get('rasterizer');
    }
    next();
  });
  app.use('/api', api);

  // root endpoint
  app.use('/', root);

}

What gives ??

MattMcFarland avatar Jan 08 '16 17:01 MattMcFarland

~~Is it because of ES6 syntax?~~ @MattMcFarland I think I've found the issue, I wasn't using CORS.

Server Side:

app.use((req, res, next) => {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

Client Side:

  • If you are using fetch API then use following:
fetch('endpoint.json', {
  credentials: 'include',
...
  • If you are using jQuery/xhr then use withCredentials: true in the ajax object

bogas04 avatar Jan 09 '16 08:01 bogas04

NOTE : Passport is still not filling req.user, I am manually adding user to session at login and removing on logout, so I guess the issue is still valid.

bogas04 avatar Jan 09 '16 10:01 bogas04

Same problem here :(

AdamZikmund avatar Feb 17 '16 18:02 AdamZikmund

Same problem here as well

brianmmorton avatar Apr 29 '16 15:04 brianmmorton

Same problem here as well

sethisidd avatar Jun 22 '16 13:06 sethisidd

Me too. I feel like this is due to a race condition in the express session store, but I'm not sure. Very frustrating. Does anyone have even a dirty workaround?

jdposthuma avatar Jun 22 '16 21:06 jdposthuma

I used JWT instead of sessions :) and it's better solution.

AdamZikmund avatar Jul 13 '16 10:07 AdamZikmund

+1 one on this. Same issue. When I make the same requests with postman everything works fine. I've tried adding CORS support and made sure the cookie is in fact coming across.

rhinodavid avatar Oct 28 '16 07:10 rhinodavid

I've fixed this, but it hasn't been accepted as the Travis CI is failing for some reason:

https://github.com/jaredhanson/passport/pull/504

jdposthuma avatar Oct 28 '16 13:10 jdposthuma

Any progress on this issue? It's frustrating.

abelosorio avatar Jan 24 '18 19:01 abelosorio

Any workaround, i have accessed that from sessionStore manually, but that appears to be redundant approach though.

MuhammadHasham23 avatar Jan 26 '18 20:01 MuhammadHasham23

Old issue, 2016, but it hit me now... in Auth-controller I have:

const express         = require("express");
const authController  = express.Router();
const passport        = require("passport");

// Our user model
const User            = require("../api/user/user.model");
const upload          = require('../config/multer');

const isAuthenticated = require('../config/isAuthenticated'); //prueba

// Bcrypt let us encrypt passwords
const bcrypt         = require('bcrypt');
const bcryptSalt     = 10;

The login is:

authController.post("/login", function(req, res, next) {
  passport.authenticate('local', function(err, user, info) {
    console.log("intentamos hacer login");
    console.log(err);
    if (err) {
      res.status(500).json({ message: 'Something went wrong in passport.authenticate' });
      return;
     }

    if (!user) { return res.status(401).json(info); }

    req.login(user, function(err) {
      if (err) {
        console.log ("dentro del reglogin");
        return res.status(500).json({
          message: 'something went wrong :('
        });
      } else{
        console.log("dentro del authController.post --> req.login: correcto");
        console.log("req.session.passport.user y despues req.user");
        console.log(req.session.passport.user);
        console.log(req.session);
        console.log(req.user);
        res.status(200).json(req.user);}

    });
  })(req, res, next);
});


When I do Login, in console are:

Session {
  cookie:
   { path: '/',
     _expires: 2018-10-26T08:57:02.193Z,
     originalMaxAge: 2419200000,
     httpOnly: true },
  passport: { user: 5a0492a6b004db02c32afbf0 } }

OK...

But when I do inmediatly /test (like @bogas04 the passport session is missing:


/* ---- TEST ---- */
authController.get('/test', (req, res) => {
  console.log("REQ:SESSIONSTORE: ",req.sessionStore);
  console.log("REQ.SESSIONID: ",req.sessionID);
  console.log("REQ.SESSION: ",req.session);
  res.status(200).end(req.isAuthenticated() ? 'logged in': 'logged out');
});
/* ---- TEST ----*/

The req.session is:

Session {
  cookie:
   { path: '/',
     _expires: 2018-10-26T08:51:00.438Z,
     originalMaxAge: 2419200000,
     httpOnly: true } }

And the response (with postman) to get localhost:3000/test is logged out

JorgeJoseAbad avatar Sep 28 '18 09:09 JorgeJoseAbad

Yeah! but you can't access req.user, can you?

MuhammadHasham23 avatar Sep 28 '18 11:09 MuhammadHasham23

@MohammadHasham
undefined, In the above authcontroller.test If I'added line console.log(req.user)
its undefined Thank you

JorgeJoseAbad avatar Sep 28 '18 17:09 JorgeJoseAbad

Did you figure out what the problem is? I am having this issue. Sometimes it was fixed and then it happened again.

jim423 avatar Dec 07 '18 08:12 jim423

@JorgeJoseAbad Did you find a solution to this issue? I am confronting the same issue. Looked through so many links, nothing is working out.

kamalpreetgrewal avatar Feb 15 '19 21:02 kamalpreetgrewal

@kamalpreetgrewal I fixed it by enabling credential in headers when sending login request. It’s an issue about not using CORS.

jim423 avatar Feb 16 '19 01:02 jim423

I am having the same issue, I am user Cons but still ! The thing is it is not consistent, I am using Axios for testing and I need to be logged in, once the user is attached to the session Session { cookie: { path: '/', _expires: 2018-10-26T08:57:02.193Z, originalMaxAge: 2419200000, httpOnly: true }, passport: { user: 5a0492a6b004db02c32afbf0 } }

some times it's with out the user so the cookie is not valid

anyone have any idea what to do !

MahmoudAbdo90 avatar Oct 02 '19 07:10 MahmoudAbdo90

I figured out what is the cause of this, using server.use( session({ cookie:blabla, resave: false, saveUninitialized: true, secret: process.env.RDS_COOKIE_SECRET, store: testEnvironment ? null : new require('connect-pg-simple')(session)() }) )

disable the store when you are sending so many login requests when testing some how causes a problem with using connect-pg-simple but now it is works just fine.

MahmoudAbdo90 avatar Oct 02 '19 10:10 MahmoudAbdo90

I made a sample repository here in case it might help some people :) I use Nest.js, nestjs/passport with a local strategy and url redirection. Detailed article here.

Roms1383 avatar Mar 21 '20 08:03 Roms1383

I also have this issue!

reteps avatar May 16 '20 03:05 reteps

same issue

ErezShahaf avatar May 17 '20 22:05 ErezShahaf

Having the same issue, its been a week am I going insane?

colorpulse6 avatar Sep 25 '20 22:09 colorpulse6

same issue please help :/

0xOnyx avatar Sep 28 '20 21:09 0xOnyx

Did anyone get a work around? I am facing this issue when I deploy it. I have deployed client in netlify and backend in heroku. Everything works fine when running on local as well as works with postman(the deployed version), but am still facing error on browsers. I have implemented cors, and am not getting why serialize user is not saving the session in the request.

malay5-1 avatar May 31 '22 14:05 malay5-1

Not sure if this is relevant, but I had an issue with Passport in version 0.6.0.

passport.authenticate removed id_token from request session object - with 0.5.3 the id_token was not removed.

Scandianis avatar Aug 11 '22 22:08 Scandianis

hello everyone i'm coming from 2022 near 2023 and i have the same fucking issues.

Osama-D avatar Nov 30 '22 21:11 Osama-D