Http-proxy-middleware: Cookie not saved in browser

Created on 6 Jun 2017  ·  10Comments  ·  Source: chimurai/http-proxy-middleware

Expected behavior

I expected to use the proxy middleware so that when I query http://localhost:8080/api/myurl with ajax it will actually send the request to https://dev.mydomain.com/api/myurl, and return a header with set-cookie that will be saved in my browser and used the next time I run another ajax query to that endpoint.

Actual behavior

The proxy seems to be working and reaching the proper endpoint correctly and set-cookie returns a correct looking domain=dev.mydomain.com without secure but it is not saved in my browser and therefore not included with the following request. I've tried changing the target and cookieDomainRewrite options but have not successfully had a cookie saved from my response. I tried the method outlined in issue #137 and repeated below. This seems to manually read and write the cookie relative headers? However, when I do this I receive a response from the correct domain but the wrong (missing) subdomain. How can I preserve the subdomain? Or am I doing something else wrong with this setup?

Setup

proxy middleware configuration

var proxyOptions = {
    target: 'https://dev.mydomain.com/',
    changeOrigin: true,
    ws: true,
    secure: false,
    cookieDomainRewrite: "dev.mydomain.com",
    debug: true,
    onProxyReq: relayRequestHeaders,
    onProxyRes: relayResponseHeaders
}
function relayRequestHeaders(proxyReq, req) {
   Object.keys(req.headers).forEach(function (key) {
     proxyReq.setHeader(key, req.headers[key]);
   });
 }
function relayResponseHeaders(proxyRes, req, res) {
   Object.keys(proxyRes.headers).forEach(function (key) {
     res.append(key, proxyRes.headers[key]);
   });
 }
var apiProxy = proxy('/api', proxyOptions);

Most helpful comment

Since you are trying to proxy between http <-> https;
You might want to check your cookie flags. (Especially the secure flag);

The cookie will not be set if this flag is present in the response, because you're running http on localhost.

More info:
https://blog.dareboost.com/en/2016/12/secure-cookies-secure-httponly-flags/

All 10 comments

Thanks for your question.

I don't have the answer unfortunately.

The option cookieDomainRewrite is provided by http-proxy library.

Best to do is read the cookieDomainRewrite documentation carefully: https://github.com/nodejitsu/node-http-proxy#options.

If you think it's a bug, please file an issue at the issue tracker of http-proxy.

Thanks for your reply. I'd looked at that documentation again and again but wasn't until I read the original PR for cookieDomainRewrite that I understand now i was using it totally wrong. I changed it to:
var proxyOptions = { target: 'https://dev.mydomain.com/', changeOrigin: true, ws: true, secure: false, cookieDomainRewrite: "localhost", debug: true }
and it works perfectly : )

Since you are trying to proxy between http <-> https;
You might want to check your cookie flags. (Especially the secure flag);

The cookie will not be set if this flag is present in the response, because you're running http on localhost.

More info:
https://blog.dareboost.com/en/2016/12/secure-cookies-secure-httponly-flags/

Glad to hear you've found the answer.
Thanks for sharing the solution!

@okwme
hi, I'm having a same question with you. First, I send a http request to my server by using http-proxy, and then, I want to send a websocket request to the same server, and the first http request's response cookie must be taken along with the second websocket request, it's a basic auth. but the cookie is not saved in my browser , so my send websocket request response 401.
sorry,my English is poor, but can you help me resolve this question ?

@16slowly can you paste in your proxy settings? how is your dev server set up? the domains need to match, and if the secure flag is set to true then so does the ssl (like @chimurai mentioned).

@okwme hello,i'm also having the same question... I query http://localhost:9999/api/xxx with ajax it will actually send the request to https://100.2.52.95:8080/api/xxxx, basicly it's a proxy between http <->https
here is my options:
options = { target: options, secure: false, // https代理需要加这一句 cookieDomainRewrite: { '*' : 'localhost' }, onProxyReq: function (proxyReq, req) { Object.keys(req.headers).forEach(function (key) { proxyReq.setHeader(key, req.headers[key]); }) }, onProxyRes: function (proxyRes, req, res) { Object.keys(proxyRes.headers).forEach(function (key) { res.append(key, proxyRes.headers[key]); }) }, pathRewrite: function (path, req) { return path.replace('/api', '/api') } }
but can't get any cookie saved in browser, so I can't make following request.....
I'm not sure what's wrong with my proxy options., hope you could give me a hand~~^_^

Hi I ended up using this config with cookies saving successfully:
proxyTable: { '/api': { target: 'https://api-endpoint.com', ws: true, secure: false, cookieDomainRewrite: "localhost", debug: true, preserveHeaderKeyCase: true } }
while running my dev environment on http://localhost:8080

Just in case this helps anyone that lands here:

In my case I was convinced I was missing something in the proxy config, but it turned out to be something completely different. I'm proxying to a graphql server like this:

    proxyTable: {
      '/graphql': 'http://localhost:3003'
    }

And that works fine, but I was missing something on the client-side:

const httpLink = new HttpLink({
  uri: '/graphql',
  credentials: 'same-origin', // <--- need this
})

I believe fetch would also require a similar option. So, check whatever library you are using that is making XHR requests and make sure you pass credentials if it doesn't do it for you.

It works for me.

onProxyRes: (proxyRes, req, res) => {
  const sc = proxyRes.headers['set-cookie'];
  if (Array.isArray(sc)) {
    proxyRes.headers['set-cookie'] = sc.map(sc => {
      return sc.split(';')
        .filter(v => v.trim().toLowerCase() !== 'secure')
        .join('; ')
    });
  }
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

gajus picture gajus  ·  8Comments

joshiste picture joshiste  ·  4Comments

udayms picture udayms  ·  8Comments

kimmobrunfeldt picture kimmobrunfeldt  ·  5Comments

minhduchcm picture minhduchcm  ·  7Comments