12

I have a simple Express based Node.js web server that I'm using for development of a JavaScript application. I set up the server to use node-http-proxy to proxy API requests the application makes to a Jetty server that is running on a different domain and port. This setup has been working flawlessly until I started to run into problems with session management.

Upon authentication the application server returns a cookie with an auth token representing the server session. When I run the JS application off of my filesystem (file://) I can see that once client receives the cookie, it is sent in all the subsequent API requests. When I run the JS app on the node server and API calls are proxied through node-http-proxy (RoutingProxy) the request headers never include the cookie.

Is there something I need to handle manually to support this type of session persistence through the proxy? I've been digging through the node-http-proxy code but it is a little over my head because I am new to Node.

https://gist.github.com/2475547 or:

var express = require('express'),
    routingProxy = require('http-proxy').RoutingProxy(),
    app = express.createServer();

var apiVersion = 1.0,
    apiHost = my.host.com,
    apiPort = 8080;

function apiProxy(pattern, host, port) {
    return function(req, res, next) {
        if (req.url.match(pattern)) {
            routingProxy.proxyRequest(req, res, {host: host, port: port});
        } else {
            next();
        }
    }
}

app.configure(function () {
    // API proxy middleware
    app.use(apiProxy(new RegExp('\/' + apiVersion + '\/.*'), apiHost, apiPort));

    // Static content middleware
    app.use(express.methodOverride());
    app.use(express.bodyParser());
    app.use(express.static(__dirname));
    app.use(express.errorHandler({
        dumpExceptions: true, 
        showStack: true
    }));
    app.use(app.router);
});

app.listen(3000);
tomswift
  • 349
  • 1
  • 2
  • 9

5 Answers5

5

I did what you are asking by manually looking at the response, seeing if it is a set-cookie, snipping off the JSESSSIONID, storing it in a variable, and passing it on all subsequent requests as a header. This way the reverse proxy acts as a cookie.

on('proxyReq', function(proxyReq){ proxyReq.setHeader('cookie', 'sessionid=' + cookieSnippedValue) 
mweber
  • 670
  • 7
  • 18
httpete
  • 2,765
  • 26
  • 34
2

Hi @tomswift does your local server run on http protocol, but the session cookie receive from the remote server carry with Secure; like:

'set-cookie':
[ 'JSESSIONID=COOKIEWITHSECURE98123; Path=/;HttpOnly;Secure;']

If so, before your local server response to the client, extract set-cookie from the original response(response from remote server to local server) header, remove the Secure; and put the rest of it into the proxy response (response from local server to client ) header like:

'set-cookie':
[ 'JSESSIONID=COOKIEWITHSECURE98123; Path=/;HttpOnly;']

then the client will take the session cookie automatically.

Hope it may help.

Halt
  • 1,055
  • 9
  • 18
  • Thank you for mentioning this @Halt removing the `secure` flag also solved my issue specifically related to JSESSIONID – Phil Lucks Sep 11 '19 at 03:13
  • 1
    Be careful when removing the "secure" flag. That means that cookies will be sent over insecure connections, and could be exposed to packet sniffers, potentially giving away the user's login creds, or sensitive session information! – Murphy Randle Jan 08 '20 at 17:39
0

Ideally the job of a proxy is to just forward a request to the destination, and should not strip off critical headers like cookies, But if it is, i think you should file a issue against them here https://github.com/nodejitsu/node-http-proxy/issues.

Also you said the request headers never include the cookie, Is it possible the client never received it?

FUD
  • 5,114
  • 7
  • 39
  • 61
  • I have confirmed in Web Inspector that the client recieves the 'set-cookie' header. You can see the transaction [here](http://i.imgur.com/VQV0a.png). The request cookie in this case is being generated by Express's cookieParser which I was trying to use to support the session but it seems to always do its own thing. – tomswift Apr 24 '12 at 20:29
  • Opened an issue in GitHub as I struggle to try and get the cookie from the proxied server's response and manually support the session: https://github.com/nodejitsu/node-http-proxy/issues/236 – tomswift Apr 24 '12 at 20:46
0

I found a way to implement this by forking and modifying node-http-proxy. It serves my current purpose which is a development environment. For any sort of serious consideration it needs to be fleshed out into a more legitimate solution.

The details can be found in the issue I filed in GitHub: https://github.com/nodejitsu/node-http-proxy/issues/236#issuecomment-5334457

I would love some input on this solution, especially if I'm going completely in the wrong direction.

tomswift
  • 349
  • 1
  • 2
  • 9
0

I had similar problems that cookies were not passed forward to the client. Solution:

  1. get cookie from proxy response
  2. set it in proxy request, with slightly modified value
let cookie;
const webpackConfig = {
  proxy: {
    '/api': {
        ...
        onProxyReq: (proxyReq) => {
          if(cookie) {
            proxyReq.setHeader('Cookie', cookie);
          }
        },
        onProxyRes: (proxyRes) => {
          const sc = proxyRes.headers['set-cookie'];

          const raw = sc.filter(s => s.startsWith('JSESSIONID'));

          if(raw.length) {
            cookie = raw[0].split(';')[0];
          }
        }

    }
  }
}
kurumkan
  • 2,635
  • 3
  • 31
  • 55