13

I am using a simple nginx instance to proxy REST calls to another server. The purpose of my proxy is to allow the use of cookies for authentication. I have it working, except for one problem. The server providing the REST service is sending the header Access-Control-Allow-Origin *. That header is too permissive for cookie based authentication. I need to replace that header with one that is more restrictive.

Here is a subset of my nginx config:

map $http_origin $cors_header {
    default "";
    "~^https?://[^/]+\.mydomain\.com(:[0-9]+)?$" $http_origin;
}

server {    
    location / {
        proxy_pass https://myrestserver.com/api;
        add_header Access-Control-Allow-Origin $cors_header;
        add_header Access-Control-Allow-Credentials true;
    }
}

My problem is that I end up with two Access-Control-Allow-Origin headers present in my response. How can I replace the header that comes back from the REST server so that only my version of the header is present in the final response?

Michael Taylor
  • 233
  • 1
  • 2
  • 5

2 Answers2

29

this works without extra nginx modules

proxy_hide_header 'access-control-allow-origin';
add_header 'access-control-allow-origin' '*';
exe-dealer
  • 299
  • 3
  • 2
  • 2
    I do not get it – Pierre.Vriens Aug 23 '18 at 15:33
  • 2
    @Pierre.Vriens You hide the `Access-Control-Allow-Origin` that you get back from the server you proxy to with `proxy_hide_header` and then you add your own custom header with `add_header`. This answer is the only way to "replace" a header in Nginx as far as I know. Upvote from me! – Wilt Apr 15 '19 at 14:54
  • I got `proxy_hide_header directive is not allowed here` so it is not working for me without further explanations... – m13r Feb 22 '22 at 16:18
  • @m13r you cannot put proxy_hide_header inside an if block. – Zhang Buzz Feb 25 '22 at 04:05
8

The best thing to do would be to change the response on the REST server side, but, assuming you don't have control of the REST server, there is a module for Nginx that can modify headers called ngx_headers_more: https://github.com/openresty/headers-more-nginx-module

You'll have to install the module (this will likely involve building nginx from source and adding the module in ./configure, as described in the github readme). For your specific problem, once you install it you can add this directive in any block

more_set_headers "Access-Control-Allow-Origin: $cors_header"
suitablyawesome
  • 331
  • 1
  • 8
  • You may or may not need to use "more_clear_headers" before "more_set_headers". I do, but not sure if it was me being cautious or actually needing to. Building nginx is pretty easy, I have a guide coming out that includes that soon. – Tim Jan 25 '16 at 22:00
  • 2
    You don't actually! As the docs say, more_set_headers "Replaces (if any) or adds (if not any) the specified output headers..." but I doubt the cautious approach adds significant overhead. – suitablyawesome Jan 25 '16 at 22:05
  • Good to know :) You're right, I clear some headers like "Server" (for security) and "Pragma" (because it's old) and just set the headers I care about. – Tim Jan 25 '16 at 22:08
  • This did work without needing to use more_clear_headers. Thanks! – Michael Taylor Jan 26 '16 at 04:48