Express-session not saving set variables after server side ajax request (to spotify api) using request module

Viewed 115

I'm trying to create a website to organize music based on genres and as such I need to use the spotify API. I authorize and set the session.loggedIn and other variables to desired variables. But, these variables are not saved after setting them. Below is the most important code (also included full code a bit further down). After signin is where the user is sent after visiting the spotify login page and being redirected.

request.post(clientServerOptions, (err, postres, body) => onReplyToAuth(req,res,err,postres,body)) then calls the auth POST from the server, to get a key for data access. The communication is all successful, the data received in the body is correct data (confirmed this).

{
  if(req.session.loggedIn) res.redirect(res.locals.pathPrefix+"/listofplaylists");
  else if(true)
  {
    var code = req.query.code
    if(!code) res.redirect(res.locals.pathPrefix);
    else
    {
      req.session.authCode = code;
      var clientServerOptions = 
      {
        url: "https://accounts.spotify.com/api/token",
        form: 
        {
          grant_type : "authorization_code",
          code: code,
          redirect_uri:"http://www.localhost:8080"+res.locals.pathPrefix+"/afterSignIn"
        },
        headers:
        {
          'Authorization' : 'Basic ' + (new Buffer(myClientId+":"+myClientSecret).toString("base64"))
        },
        json: true
      };
      request.post(clientServerOptions, (err, postres, body) => onReplyToAuth(req,res,err,postres,body));
    }

  }
  else
  {
    res.redirect(res.locals.pathPrefix);
  }
});

function onReplyToAuth(req,res,err,postres,body)
{
  console.log(body);
  if(!err)
  {
    req.session.loggedIn = true;
    req.session.loggingIn = false;
    req.session.accessToken = body.access_token;
    req.session.refreshToken = body.refresh_token;  
    console.log("Before saving:");
    console.log(req.session);
    req.session.save(function(err) 
    {
      if(!err)
      {
        console.log("After saving:")
        console.log(req.session);
        res.redirect(res.locals.pathPrefix+"/listofplaylists");
      }
    });

  }
  else
  {
    res.redirect(res.locals.pathPrefix);
  }
}

Using router.use((req,res,next)=>{console.log(req.session);next()}); I've noticed that the req.session.x is undefined for all set variables when in a new request. Furthermore, I've checked the execution of the code (using a console log after the assignments, and session and the variables were available (req.session was set correctly there).

FULL SOURCE:

var request = require('request');
var createError = require('http-errors');
var path = require('path');
var cookieParser = require('cookie-parser');
var router = express.Router();
var session = require("express-session")({secret: 'cookie secret',
resave: false,
saveUninitialized: true,
cookie: { secure: true }});
var myClientId = "my id";
var myClientSecret = "my secret"

router.use(session)
router.use((req,res,next)=>{console.log(req.session);next()});

router.get("/requestsignin", function(req,res,next)
{
  var scopes="playlist-read-collaborative playlist-modify-public playlist-read-private playlist-modify-private";
  res.redirect('https://accounts.spotify.com/authorize' +
  '?response_type=code' +
  '&client_id=' + myClientId +
  (scopes ? '&scope=' + encodeURIComponent(scopes) : '') +  
  '&redirect_uri=' + encodeURIComponent("http://www.localhost:8080"+res.locals.pathPrefix+"/afterSignIn"));
});

router.get("/afterSignIn", function(req, res)
{
  if(req.session.loggedIn) res.redirect(res.locals.pathPrefix+"/listofplaylists");
  else if(true)
  {
    var code = req.query.code
    if(!code) res.redirect(res.locals.pathPrefix);
    else
    {
      req.session.authCode = code;
      var clientServerOptions = 
      {
        url: "https://accounts.spotify.com/api/token",
        form: 
        {
          grant_type : "authorization_code",
          code: code,
          redirect_uri:"http://www.localhost:8080"+res.locals.pathPrefix+"/afterSignIn"
        },
        headers:
        {
          'Authorization' : 'Basic ' + (new Buffer(myClientId+":"+myClientSecret).toString("base64"))
        },
        json: true
      };
      request.post(clientServerOptions, (err, postres, body) => onReplyToAuth(req,res,err,postres,body));
    }

  }
  else
  {
    res.redirect(res.locals.pathPrefix);
  }
});


function onReplyToAuth(req,res,err,postres,body)
{
  if(!err)
  {
    req.session.loggedIn = true;
    req.session.loggingIn = false;
    req.session.accessToken = body.access_token;
    req.session.refreshToken = body.refresh_token;  
    res.redirect(res.locals.pathPrefix+"/listofplaylists");
  }
  else
  {
    res.redirect(res.locals.pathPrefix);
  }
}

function requestSpotifyData(url,req, callback)
{
  var authOptions = 
  {
    url:url,
    headers:
    {
      'Authorization':"Bearer " + req.session.accessToken
    },
    json : true
  }
  request.get(authOptions,callback);
}

router.get("/listofplaylists", function(req,res,next)
{
  if(!req.session.loggedIn)
  {
    res.redirect(res.locals.pathPrefix)
  }
  else
  {
    requestSpotifyData("https://api.spotify.com/v1/me/playlists?limit=50",req,(err,postres,body) =>
    {
      res.render("listOfplaylists",
      {
        playlists : body.items
      });
    });
  }

});



/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});




module.exports = router;

Nodemon app.js debug (note that the code is ran before the get log (code above corresponds to request):

Session {
  cookie: {
    path: '/',
    _expires: null,
    originalMaxAge: null,
    httpOnly: true,
    secure: true
  }
}
GET /spotify/requestsignin 302 18.590 ms - 628
Session {
  cookie: {
    path: '/',
    _expires: null,
    originalMaxAge: null,
    httpOnly: true,
    secure: true
  }
}
(node:1596) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
{
  access_token: 'access token',
  token_type: 'Bearer',
  expires_in: 3600,
  refresh_token: 'refresh token',
  scope: 'playlist-read-private playlist-read-collaborative playlist-modify-private playlist-modify-public'
}
Before saving:
Session {
  cookie: {
    path: '/',
    _expires: null,
    originalMaxAge: null,
    httpOnly: true,
    secure: true
  },
  authCode: 'auth code',
  loggedIn: true,
  loggingIn: false,
  accessToken: 'access token',
  refreshToken: 'refresh token'
}
After saving:
Session {
  cookie: {
    path: '/',
    _expires: null,
    originalMaxAge: null,
    httpOnly: true,
    secure: true
  },
  authCode: 'auth code',
  loggedIn: true,
  loggingIn: false,
  accessToken: 'access token',
  refreshToken: 'refresh token'
}
GET /spotify/afterSignIn?code=auth code 302 141.181 ms - 92
Session {
  cookie: {
    path: '/',
    _expires: null,
    originalMaxAge: null,
    httpOnly: true,
    secure: true
  }
}
GET /spotify/listofplaylists 302 6.726 ms - 60
Session {
  cookie: {
    path: '/',
    _expires: null,
    originalMaxAge: null,
    httpOnly: true,
    secure: true
  }
}
GET /spotify/ 304 238.770 ms - -
GET /spotify/stylesheets/style.css 304 1.629 ms - -
Session {
  cookie: {
    path: '/',
    _expires: null,
    originalMaxAge: null,
    httpOnly: true,
    secure: true
  }
}
GET /spotify/ 304 15.980 ms - -

Thanks for helping!

2 Answers

I'm not sure if this could be the problem, but there's a possibility that res.redirect was called before the session was fully saved in the onReplyToAuth function, you might want to try calling req.session.save then pass in a callback function to redirect once the session has been saved.

req.session.loggedIn = true;
req.session.loggingIn = false;
req.session.accessToken = body.access_token;
req.session.refreshToken = body.refresh_token;  
req.session.save(function(err) {
  // session saved
  res.redirect(res.locals.pathPrefix+"/listofplaylists");
})

I hope it helps.

As I was goofing around with the session settings I changed

var session = require("express-session")({secret: 'secret`376712',
resave: false,
saveUninitialized: true,
cookie: { secure: true}});

to

var session = require("express-session")({secret: 'secret`376712',
resave: false,
saveUninitialized: true,
cookie: { secure: false }});

and I got the playlist list with desired outputs (session wasn't reset anymore). I think this is a fix because the connection to the server is HTTP and not HTTPS and therefore the cookie is not sent. I am however not sure about this.

Thanks a lot to others thinking with me!

PS: I will try update the post to achieve the best reachability for other people.

Related