I am Using expression-session and express-mysql-session for storing in database but on every ajax returns new session id.For more info calling from http only.This issue is not coming when i disable security of browser.``
My Code is
var express = require('express');
var mysql = require('mysql');
var jwt = require('jsonwebtoken');
var session=require('express-session');
var MySQLStore = require('express-mysql-session')(session);
var options = {
host: 'localhost',// Host name for database connection.
port: 3306,// Port number for database connection.
user: 'root',// Database user.
password: '',// Password for the above database user.
database: 'node',// Database name.
checkExpirationInterval: 900000,// How frequently expired sessions will be cleared; milliseconds.
expiration: 1512671400000,// The maximum age of a valid session; milliseconds.
createDatabaseTable: true,// Whether or not to create the sessions database table, if one does not already exist.
connectionLimit: 10,// Number of connections when creating a connection pool
schema: {
tableName: 'sessions',
columnNames: {
session_id: 'session_id',
expires: 'expires',
data: 'data'
}
}
};
var connection = mysql.createConnection(options); // or mysql.createPool(options);
var sessionStore = new MySQLStore({}/* session store options */, connection);
var router = express.Router();
router.use(session({
name: 'session_cookie_name',
secret: 'session_cookie_secret',
store: sessionStore,
resave: false,
saveUninitialized: true,
cookie: { path: '/', httpOnly: false, secure: false, maxAge: 365 * 24 * 60 * 60 * 1000 }
}));
router.get('/session', function(req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.send(req.sessionID);
});
Hi @brijeshIOGit sorry your issue hasn't gotten to yet. Thanks for the server code! Is it possible you can provide the client side code that demonstrates the issue? Nothing seems wrong in your server example, so not sure what is happening. Ideally can you provide the following:
Thanks!
Any ajax call from from front end to session api will create new session id. You can check by hitting session api using ajax call.You will the exact problem if you print the session ID returned by api.
Hi @brijeshIOGit I use this module on my own servers and of course use AJAX calls to the server (because, single page apps) and never have an issue. I'm not really sure what is going on with your setup, through. I'd be happy to take a look 馃憤 Ideally can you provide the following:
Thanks!
@dougwilson I have the same issue from my AngularJS client. I am running my server with Node v6.11.3, express-session 1.15.6
Hi @naz-mul very sorry you're experiencing this issue :( No one has provided me the information I need to start looking into it yet. Would you be able to? I would love to get to the bottom of this 馃憤
Hi,
I have been facing this issue for quite a long time now and it has had me stumped,following are more details:
NodeJS 4.5
express-session: 1.12.1
Session store for express-session : Memory
Authentication into application is via SSO (Ping)
To check if the user is logged in we have the following common check executed on each route of the application:
Server code:
if(req.session.somekey1 || req.session.somekey2){
//user is considered to be logged in
}
else{
//user session hasn't been set, hence force to logout page
if (req.headers["x-requested-with"] == 'XMLHttpRequest')
{
res.send({error:"session expired", code:1111});
}
}
Here is the flow of the issue
Steps 4 to 8 continue in a loop when the user tries to login again.
The only way to stop this is to close the browser completely, clear cookies and start it up again
Note that on the forced logout at step 7 below is the code:
router.get('/applogout', function(req,res,next){
res.header('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0');
req.session.destroy();
req.logout();
res.redirect('/loggedout');
});
Following is the client side code of how we are forcing the logout on AJAX call
$.ajaxSetup({
complete: function (x, status, error) {
if(x.status==403){
alertify.error("You are not authorized to perform this action.");
}
else if(x.status==500){
alertify.error("An exception occurred during processing.");
}
else if (x && x.responseJSON) {
if (x.responseJSON.code === 1111 && !ajaxTriggeredLogout) {
ajaxTriggeredLogout = true;
alertify.error("Sorry, your session has expired. You will be logged out shortly");
setTimeout(function(){window.location.href = "/applogout"}, 2000);
}
}
else if (x && x.responseText && x.responseText.indexOf('"code":1111') >= 0 && !ajaxTriggeredLogout) {
ajaxTriggeredLogout = true;
alertify.error("Sorry, your session has expired. You will be logged out shortly");
setTimeout(function(){window.location.href = "/applogout"}, 2000);
}
else if (status === 'timeout') {
alertify.error("Connection Timed Out");
}
},
timeout: 60000
});
From analysis it seems to be related to a possible race condition because Memory store is being used for the session but haven't been able to confirm this nor find a resolution for it
Any help here is appreciated
Hi @ricfernandes thanks for the additional information. I'm trying to setup a server and client what that code but not sure how to get it pieced together to be functional in order to be able to run it with a debugger to help see what is going on. Can you provide instructions for how to set it all up and the step by step instructions to reproduce the issue?
Hi @dougwilson ,
Apologies for the long wait, following is a sample skeleton of the code for the usecase:
https://www.dropbox.com/s/4qo44l7du902fwh/ExpressSessionIssue.zip?dl=0
You can access http://localhos:5600/login and will get loggedin and redirected to http://localhos:5600/nk
There is a link on the page to execute an AJAX call for the test
The steps for the issue are mentioned in my previous post, the only difference is the login with SSO is replaced by a simulation of it with user just getting logged in on hitting /login
Hopefully this will help
Thanks
Richard
Hi @dougwilson ,
Just wanted to check if you have had a chance to test out the sample code provided.
Thanks
Richard
I haven't yet, very sorry. I have it on my todo unless someone else is able to figure it out before hand.
Ok, so I just downloaded, installed, and setup the app. I loaded the /login and clicked on the AJAX link. Everything seems good. Didn't realize that I actually needed to do this were I would have at least an hour to reproduce the issue (and then an hour each time to try again...?) so I didn't choose a good time, so if I really need to keep it open for an hour, I may not be able to have it left open that long during this session.
I can say, though, that looking at the cookie that your server set in the web browser, it is set to expire after 1 hour. So... is this your issue? Once the cookie expires, the web browser won't sent in in the request, so if you just leave the app past the cookie expiration time, you'll get a new session.
@dougwilson , yes the cookie is set to expire after an hour. Adding back the steps sed to reproduce this for reference:
Steps 4 to 8 continue in a loop when the user tries to login again.
The only way to stop this is to close the browser completely, clear cookies and start it up again
As noted in step 6, after the re-login the first landing page does not have any issue with verifying that the session is active and loads successfully. however the AJAX request that is triggered from the landing page is not able to detect the same session, in fact it ends up with a different session id
Thanks for the information! I'll try to start this again sometime this week or next if I know I have at least an hour to spend on it, though I have no guarantees. Absolutely would accept a PR with a fix; though :+1:
@ricfernandes / @dougwilson did either of you get any further with this? I'm hitting the same issue:
Node version: v8.11.3
express-session: ^1.15.6
client side code
fetch('/api/test')
.then(resp => resp.json())
.then(res => {
console.log(res);
});
fetch('/api/test2')
.then(resp => resp.json())
.then(res => {
console.log(res);
});
server side
app.use(session({
secret: 'keyboard cat',
resave: true,
saveUninitialized: false,
cookie: {
maxAge: 3600000
}
}));
app.get('/api/test', (req, res) => {
console.log('TEST: ', req.sessionID);
});
app.get('/api/test2', (req, res) => {
console.log('TEST2: ', req.sessionID);
});
output
TEST: UV2UwbDwcobDEhv0E4SNUyR2ldYyzu8C
TEST2: Ab6ReF4PUZFazCMDQwhWAweuMwPY1tSa
I'm sorry I have not and honestly completely forgot about this. I'll try to find some time, but ultimately the best way to get moving is if you're able to make a pull request with a fix, of course 鉂わ笍
Actually (for my situation at least) I've come across a solution for this right after I posted lol updated below:
fetch('/api/test', {
credentials: "same-origin"
})
.then(resp => resp.json())
.then(res => {
console.log(res);
});
So (with fetch at least) it doesn't send cookies by default, you need to set credentials to "same-origin". This kicks the express-session into gear to use the correct session for the request. @brijeshIOGit / @ricfernandes not sure if this helps? Maybe double check the request is actually sending the HTTP cookie header.
Thanks @ottis ! I'm going to close this since we have a solution 馃帀
Most helpful comment
Actually (for my situation at least) I've come across a solution for this right after I posted lol updated below:
So (with fetch at least) it doesn't send cookies by default, you need to set credentials to "same-origin". This kicks the express-session into gear to use the correct session for the request. @brijeshIOGit / @ricfernandes not sure if this helps? Maybe double check the request is actually sending the HTTP cookie header.