mongodb-js / connect-mongodb-session

Lightweight MongoDB-backed session store for Connect and Express
Apache License 2.0
176 stars 35 forks source link

Session saved in the DB but req.session result is {"cookie":{"originalMaxAge":172800000,"expires":172800000,"secure":false,"httpOnly":true,"path":"/"}} #75

Open reyontech opened 4 years ago

reyontech commented 4 years ago

var store = new MongoStore( { uri: process.env.ATLAS_URI, collection: 'sessions' }, function(error) { // Should have gotten an error }); store.on('error', function(error) { assert.ifError(error); assert.ok(false); });

app.use(session({ secret: 'abcdefghijklm', saveUninitialized: true, resave: true, cookie: { secure: false, expires: 1000 60 60 24 2
}, store: store }));

app.post('/cart', function(req, res){ var cart = req.body; req.session.cart = cart; req.session.cart = cart; req.session.save(function(err){ if(err){ throw err; } res.json(req.session.cart); }); })

app.get('/', function(req, res) { res.send(req.session); });

image

vkarpov15 commented 4 years ago

I don't understand the issue, can you please clarify what the expected behavior is and what the behavior you're seeing is?

reyontech commented 4 years ago

Session stored in the DB working fine.

This part not working. req.session app.get('/', function(req, res) { res.send(req.session); });

Reult is {"cookie":{"originalMaxAge":172800000,"expires":172800000,"secure":false,"httpOnly":true,"path":"/"}}

My session data not visible here.

mkhoussid commented 4 years ago

Same issue here.

// api/auth:login
router.post(apiRoutesBack.AUTH.LOGIN, async (req, res) => {
        req.session.user = {
            id: 'someId'
            email: 'someEmail',
            username: 'someUsername',
        };

        res.json({ user: req.session.user });
});

And on app load, in my initmethod,

// api/auth:load
router.get(apiRoutesBack.AUTH.LOAD, async (req, res) => {
        console.log('req.session', req.session);
        res.json(req.session);
});

console.log('req.session', req.session); always prints:

req.session Session {
        cookie: {
            path: '/',
            _expires: 2020-09-18T07:13:43.733Z,
            originalMaxAge: 604800000,
            httpOnly: true,
            secure: null,
            domain: null,
            sameSite: null
      }
}

My setup in server.ts:

import express from 'express';
import next from 'next';
import { authRouter } from './routes';
import { connectDb } from './utils/connectDb';
import session from 'express-session';
import { v4 } from 'uuid';
import MongoDBStore from 'connect-mongodb-session';
import config from 'config';

const sessionStore = MongoDBStore(session);
const sessionInit = {
    secret: 'This is a secret',
    cookie: {
        maxAge: 1000 * 60 * 60 * 24 * 7,
    },
    resave: true,
    saveUninitialized: true,
    genid: () => v4(),
};

const PORT = process.env.PORT || 3000;

const dev = process.env.NODE_ENV !== 'production';
const nextApp = next({ dev });
const handle = nextApp.getRequestHandler();

const applyRoutes = (app: Application) => {
    app.use('/api/auth', authRouter);
};

const startServer = async () => {
    await nextApp.prepare();
    await connectDb();

    const app = express();

    if (!dev) {
        app.set('trust proxy', 1); // trust first proxy
        sessionInit.cookie.secure = true; // serve secure cookies
    }

    sessionInit.store = new sessionStore({
        uri: config.get('mongoURI'),
        collection: 'sessions',
    });

    app.use(session(sessionInit));

    app.get('*', (req, res) => handle(req, res));
    app.listen(PORT, () => console.log(`App listening on port ${PORT}`));
};

startServer();

The sessions collecting gets created on MongoDB Atlas, but the cookie seems to not persist through page reloads and page navigations.

Fauphi commented 4 years ago

Same for me. The session gets stored in the database, but not in req.session.

Is there a special way to update the session for req.session?

mkhoussid commented 4 years ago

Ended up using pure cookies (storeless). next-iron-session. Just iron-session would work fine as well.

effieguenther commented 11 months ago

I was having this same issue and spent so long trying to figure this out! But here's what fixed it:

add this before session configuration: app.set(("trust proxy", 1);

Add proxy option to session: app.use(session({ secret: 'secret', resave: false, saveUninitialized: false, cookie: { secure: true, httpOnly: true, sameSite: 'none' }, store: store, proxy: true }))

DavidForDev commented 11 months ago

I was having this same issue and spent so long trying to figure this out! But here's what fixed it:

add this before session configuration: app.set(("trust proxy", 1);

Add proxy option to session: app.use(session({ secret: 'secret', resave: false, saveUninitialized: false, cookie: { secure: true, httpOnly: true, sameSite: 'none' }, store: store, proxy: true }))

hey, it still not working, I use the Redis store for sessions like that:

app.set("trust proxy", 1);

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(
  cors({
    origin: "http://localhost:3000",
    credentials: true,
  })
);

app.use(
  session({
    store: new RedisStore({
      client: redisClient,
      ttl(sess) {
        return 1000 * 60 * 60 * 24 * 7;
      },
    }),
    proxy: true,
    secret: "secretmeforever",
    saveUninitialized: false,
    resave: false,
    cookie: {
      maxAge: 1000 * 60 * 60 * 24 * 7,
      httpOnly: false,
      secure: false,
      sameSite: "none",
    },
  })
);

but result still:

Session {
  cookie: {
    path: '/',
    _expires: 2023-12-17T06:57:16.209Z,
    originalMaxAge: 604800000,
    httpOnly: false,
    secure: false,
    sameSite: 'none'
  }
}

I lost a few days... I'm already tired

effieguenther commented 11 months ago

@DavidForDev I feel you. I tried for 3 days before getting it to work. There were a few other things that I did along the way that probably made a difference.

  1. If you are using passport like me, confirm that your deserialize function is being called and working properly. Add console.log() statements. If you don't see the deserialize function being called, it probably means the cookie wasn't sent with the request.
  2. Confirm if the session cookie is actually being sent with your request. On Chrome you can use the dev tools > application >storage > cookies > localhost:3000 to confirm it even exists. Then check the network request and see if the cookie was sent with in the headers. Things can get a bit wonky here because your dev environment might not register the cookie as the same origin as your server. To combat this you can:
    • unblock 3rd party cookies in your browser settings
    • in your cors setup: corsOptions = { origin: true, credentials: true }
    • in your frontend where you're making the request, set credentials to 'include'. export const post = async (path, body) => { try { const response = await fetch( baseUrl + path, { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(body) }); const data = await response.json(); return data; } catch (err) { return err }

If you want you can check out my auth code here and my session code here

DavidForDev commented 11 months ago

@DavidForDev I feel you. I tried for 3 days before getting it to work. There were a few other things that I did along the way that probably made a difference.

  1. If you are using passport like me, confirm that your deserialize function is being called and working properly. Add console.log() statements. If you don't see the deserialize function being called, it probably means the cookie wasn't sent with the request.
  2. Confirm if the session cookie is actually being sent with your request. On Chrome you can use the dev tools > application >storage > cookies > localhost:3000 to confirm it even exists. Then check the network request and see if the cookie was sent with in the headers. Things can get a bit wonky here because your dev environment might not register the cookie as the same origin as your server. To combat this you can:
  • unblock 3rd party cookies in your browser settings
  • in your cors setup: corsOptions = { origin: true, credentials: true }
  • in your frontend where you're making the request, set credentials to 'include'. export const post = async (path, body) => { try { const response = await fetch( baseUrl + path, { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(body) }); const data = await response.json(); return data; } catch (err) { return err }
  • I haven't yet figured out how to get the cookie to send with GET requests. I suspect it's something to do with my CORS setup, but you might have better luck testing this with post/put requests first.

If you want you can check out my auth code here and my session code here

thank you for your answer. I use different tools, so for more detail, you can see my post on Stackoverflow: https://stackoverflow.com/questions/77634864/trouble-accessing-session-data-in-express-redis-after-setting-from-apollo-client

thanks