0

I know there's a few questions similar to this already, but they all have crucial differences which do not give me the solution. I'm using client-session module. I've set everything up exactly like it's specified in the docs, but for some reason I can't set session values from async callback. Here is my code

router.get('/auth', function(req, res, next) {

    var params      = req.query;
    var act         = params.act;


    switch (act) {
        case Constants.ACT_LOGIN_CHECK:
            console.log('SESSION CHECK >>> ', JSON.stringify(req.session), req.session.isNew);
            res.send(`SESSION CHECK >>> ${JSON.stringify(req.session)} ${req.session.isNew}`);
            break;
        case Constants.ACT_LOGIN_REQUEST:
            var code        = params.code;
            var state       = params.state;
            login(code, state, function(result) {
                if (result) {
                    if (result.accessToken) {
                        // console.log("WRITING SESSION BEFORE: ", JSON.stringify(req.session), req.session.isNew);
                        req.session.accessToken = result.accessToken;
                        req.session.userId      = result.userId;
                        req.session.firstName   = result.firstName;
                        req.session.lastName    = result.lastName;
                        // req.session.photoURL    = result.photoURL;
                        req.session.save();
                        console.log(`SESSION SET >>> ${JSON.stringify(req.session)} ${req.session.isNew}`);
                        res.send(`SESSION SET >>> ${JSON.stringify(req.session)} ${req.session.isNew}`);
                    }
                } else {
                    res.end();
                }
            });
            break;
        case Constants.ACT_LOGOUT_REQUEST:
            req.session = null;
            res.send(`LOGGED OUT, SESSION >>> ${JSON.stringify(req.session)}`);
            console.log('LOGGED OUT, SESSION >>> ', JSON.stringify(req.session));
            break;
    }
});

As you can see, I'm trying to set the session from callback function passed as third argument to my login() function. I can't say it doesn't work at all but it works, like, one time in a million. I'm not finilazing the response before the session is set, but anyway, when I check the session, this is what i get in the vast majority of cases:

SESSION CHECK >>> {} true

Even though this output

Is also shown all the time I set the session.

But if I simplify the code to this:

router.get('/auth', function(req, res, next) {

    var params = req.query;
    var act = params.act;
    if (act == Constants.ACT_LOGIN_CHECK) {
        console.log('SESSION CHECK >>> ', JSON.stringify(req.session), req.session.isNew);
        res.send(`SESSION CHECK >>> ${JSON.stringify(req.session)} ${req.session.isNew}`);
    } else if (act == Constants.ACT_LOGIN_REQUEST) {
        req.session.accessToken = "595a751fa174ecbda109b14339b827941b58f7d0b10b495d0f85819e749e0b42c320dcda71520342cd020";
        req.session.userId = 2195783;
        req.session.firstName = "John";
        req.session.lastName = "Doe";
        req.session.save();
        console.log('SETTING SESSION >>> ', JSON.stringify(req.session), req.session.isNew);
        res.send(`SESSION SET >>> ${JSON.stringify(req.session)} ${req.session.isNew}`);
    } else {
        req.session = null;
        console.log(`SESSION KILLED >>> ${JSON.stringify(req.session)}`);
        res.send(`SESSION KILLED >>> ${JSON.stringify(req.session)}`);
    }
} 

It all works like a charm. The session is set / cleared / checked every time I want, with no errors or bugs.

I've been struggling with this issue for 3 days now :(. I've also tried different modules like client-sessions and several others. The same result. Seems like the problem is deeper.

So is it possible at all to save session from async callback? I can't set it until I get the necessary data from social network

p.s. Here is the actual initialization code from app.js

var Constants     = require('./constants');
var express       = require('express');
var path          = require('path');
var app           = express();
var favicon       = require('serve-favicon');
var logger        = require('morgan');
var cookieSession = require('./cookiesession');
var bodyParser    = require('body-parser');

const user          = require('./routes/user');
const auth          = require('./routes/auth');
const posting       = require('./routes/posting');
const messages      = require('./messages');
const mongo         = require('./mongo');


app.use(express.static(path.join(__dirname, 'public')));
app.set('trust proxy', true);
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieSession({
    secret: Constants.COOKIE_SESSION_KEY_1
}));
app.use(function (req, res, next) {
    req.sessionOptions.maxAge = Constants.COOKIE_SESSION_MAX_AGE;
    next();
})


app.use('/api/', user);
app.use('/api/', posting);
app.use('/api/', auth);

module.exports = app;

MORE DETAILS NOW:

If the callback is executed in 1 second, the session will be set. But if it takes up more time, like 3+ seconds, it won't. I've simplified my login() function like this:

function login(code, state, onComplete) {
    setTimeout(function() {
        onComplete({
            accessToken: "sfsd646481351gsFFHgDrgrrg",
            userId: "user",
            firstName: "John",
            lastName: "Doe"
        })}, 1000
    );
}

So in case I set 1000 ms to setTimeout() it works fine, but if I set it to 3000, it won't. Looks like express finalizes response before the callback is called


ANOTHER DETAIL:

I've just found out, that this only happens if I proxy the request from reactjs app. If I call API (express) server directly with postman, it won't matter how much time the response will wait, the cookie will be set with no problems

Konstantin
  • 1,150
  • 13
  • 31

1 Answers1

0

I found a reason why cookies were not set. It was because I made request to social network and it returned its headers before I could set mine

Konstantin
  • 1,150
  • 13
  • 31