1

I have several NodeJS (Express 4) servers behind a Nginx proxy. Everything works fine, except for the cookies: upon each ajax CORS request, I seem to get a new regenerated session ID value in the returned Set-Cookie header.

I have worked on this for hours, looked into dozens of websites. Even this did not seem to help: Node.js + Nginx - What now?

My Nginx listens to port 80, and defines multiple servers, one for each subdomain: myapp.local, api.myapp.local, static.myapp.local.

My NodeJS Express 4 servers listen to a different port each one (8081, 8082, ...)

When calling api.myapp.local/login in ajax from myapp.local, I receive the proper data and session ID, but in the response I seem to have a newly generated session ID, which messes up everything and prevents me from having a healthy session.

Here is the conf for my api.myapp.local server:

server {
    listen      80;
    server_name api.myapp.local;

    error_log   logs/api.error.log notice;
    access_log  logs/api.access.log;

    location / {
        if ($request_method !~ ^(GET|HEAD|POST|OPTIONS)$ ) {
            return 405;
        }

        if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Allow-Origin' "$http_origin";
            add_header 'Access-Control-Allow-Credentials' 'true';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, HEAD, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'Referer,Accept,Origin,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,X-HTTP-Method-Override,If-Modified-Since,Cache-Control,Content-Type,Cookie';
            add_header 'Access-Control-Max-Age' 1728000;
            add_header 'Content-Type' 'text/plain charset=UTF-8';
            add_header 'Content-Length' 0;
            return 204;
        }

        if ($request_method = 'POST') {
            add_header 'Access-Control-Allow-Origin' "$http_origin";
            add_header 'Access-Control-Allow-Credentials' 'true';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, HEAD, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'Referer,Accept,Origin,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,X-HTTP-Method-Override,If-Modified-Since,Cache-Control,Content-Type,Cookie';
            add_header 'Access-Control-Max-Age' 1728000;
        }

        if ($request_method = 'GET') {
            add_header 'Access-Control-Allow-Origin' "$http_origin";
            add_header 'Access-Control-Allow-Credentials' 'true';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, HEAD, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'Referer,Accept,Origin,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,X-HTTP-Method-Override,If-Modified-Since,Cache-Control,Content-Type,Cookie';
            add_header 'Access-Control-Max-Age' 1728000;
        }

        proxy_pass http://localhost:8081;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header X-NginX-Proxy true;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto  $scheme;
    }
}

Here is my NodeJS server (straightforward):

var app = express();

app.enable('trust proxy');

/**
 * Session
 */
require('../common/webapp_session.js')(app, conf);


var iPort = process.env.PORT || conf.port;
app.listen(iPort);

console.log('API on port ' + iPort);

Now my session stuff (in webapp_session.js):

app.use(cookieParser());
console.log('** COOKIE SESSION');
console.log(conf.cookie);
app.use(session({
    secret: conf.cookie.secret,
    name: conf.cookie.name,
    cookie: {secure: conf.cookie.secure, domain: conf.cookie.domain, maxAge: 1000*60*60*24}
}));

And last my ajax call:

$.ajax('http://api.myapp.local/login',
{
    type: 'POST',
    data: oForm.serialize(),
    crossDomain: true,
    xhrFields: {
        withCredentials: true
    },
    success: function(res)
    {
            // ...
    }
});

EDIT: forgot the Express configuration for session:

{ cookie:
   { path: '/',
     _expires: Mon Jun 16 2014 23:24:06 GMT+0200 (Paris, Madrid (heure d’été)),
     originalMaxAge: 86400000,
     httpOnly: true,
     secure: false,
     domain: '.myapp.local' } }

Thank you a lot in advance for any help, I'm getting mad with this issue :-/

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Lideln Kyoku
  • 952
  • 9
  • 20
  • After other tries, I discovered this: 1) It does not seem to be related to CORS, only to cookies, because I tried a normal GET request on my http://api.myapp.local subdomain, and the same bug arose. 2) I debugged the req.sessionID in the login() call, and I could confirm it was a newly generated ID 3) However, I also debugged the headers received, and the "cookie" header was present, and my session ID was the good (old) one 4) Express sent a Set-Cookie header with the newly generated cookie. Why is that... ? – Lideln Kyoku Jun 18 '14 at 06:48
  • Ok nevermind... I think I will go back to the system I was using with PHP: https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/ – Lideln Kyoku Jun 18 '14 at 07:12

0 Answers0