How to Enable CORS in NGINX

NGINX is a popular web server capable of handling high traffic and server loads. In most cases, it serves requests sent to a specific domain and sub-domains. These requests are mostly sent from a client browser, or another server serving the same domain/sub domain. Sometimes, you may need to configure NGINX to server requests from another domain. By default, this is disabled in NGINX for security purposes. But there are real-life situations such as APIs where one domain needs to serve requests sent from one or more other domains. This is known as Cross Origin Resource Sharing (CORS). In this article, we will learn how to enable CORS in NGINX web server.

What is Same Origin Policy (SOP)

By default, most web server such as Apache and NGINX accept requests only from client web browsers or from other upstream/downstream servers that are serving the same domain. When a web browser sends a request, it sets the Origin HTTP header to the domain name. When a server receives the request, it reads the Origin header value to determine whether to allow or deny the request. The setting of origin header is automatically done by web browsers and cannot be modified using scripts like JavaScript.

Why you need CORS

The Same Origin Policy has been devised to protect the server and its data from unauthorized requests from unknown origins. But there are real-world use cases where you need to circumvent this mechanism. For example, if you want to host an API for your product/service, then your server needs to accept requests from other websites. You may commonly seen this in social media snippets displayed on other websites. Here, when users visit a website on their web browser and the web page is loaded, the website sends request to social media sites, which are other domains. Many products also provide an API for reporting and analytics. This is where you need to configure Cross Origin Resource Sharing (CORS), which allows servers to accept requests from other websites/domains.

What is Preflight

Preflight is an HTTP OPTIONS type of request sent by web browser to website to server before it makes a cross origin request. For example, when an AJAX request is made, the web browser first sends a preflight request to the target domain to check if it accepts the cross origin request. For this purpose, the server will verify the origin, http method and headers in the preflight request. Only if it receives a favorable response, then it will go ahead and send the actual CORS request. Otherwise, the browser will simply cancel the request and display a warning in the browser console.

How to Enable CORS in NGINX

Now that we have understood preflight and CORS, let us look at how to set it up.

1. Open NGINX Configuration File

Generally, NGINX configuration file is located at /etc/nginx/nginx.conf or /etc/nginx/conf.d/. Open it in text editor.

$ vi /etc/nginx/nginx.conf

2. Modify NGINX Configuration File

Add the required response headers in that file. For this purpose, you need to use add_header NGINX directive. It will automatically add the specific response headers to the requests sent to the location/server block where this directive is added.

Here is an example to allow access from all origins to ‘/’ location block.

location / {
add_header 'Access-Control-Allow-Origin' '*';
}

The add_header directive can be added to one or more location, or server blocks. If you add it to a server block, it will be applicable to all location blocks in that server.

The Access-Control-Allow-Origin header specifies the origin(s) that are allowed to send requests to this specific resource, that is, location. We use wildcard ‘*’ to specify all domains.

If you want to allows access from only one domain, then you can mention it in above command, instead of using ‘*’.

location / {
add_header 'Access-Control-Allow-Origin' 'example.com';
}

Please note, in this case, you can also use subdomains in place of domains. If you do not specify a sub domain, then requests from all subdomains will be accepted.

location / {
add_header 'Access-Control-Allow-Origin' 'blog.example.com';
}

Sometimes, you may need to allow requests from multiple origins. In this case, we define system variables $http_origin, $origin_allowed and $origin_header using map directive. Here is an example to demonstrate its use.

map $http_origin $origin_allowed {
default 0;
"domain1.com" 1;
"domain2.com" 1;
}

map $origin_allowed $origin_header {
default "";
1 $http_origin;
}

Then we use the the origin_header variable in location block.

location / {
add_header 'Access-Control-Allow-Origin' $origin_header;
}

The above CORS directives are applicable to all kinds of requests such as GET, POST, OPTIONS, etc. If you only want to handle preflight requests, then you can use an if condition to apply the above directive only to OPTIONS requests.

location / {
# Handle preflight requests
if ($request_method = OPTIONS) {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, HEAD';
add_header 'Access-Control-Allow-Headers' 'Authorization, Origin, X-Requested-With, Content-Type, Accept';
add_header 'Access-Control-Max-Age' 1728000;
return 204;
}
}

In the above code, we use use $request_method server variable to check the request method. If it is OPTIONS, that is, preflight, only then we proceed further.

Let us look at the above headers in details.

  • Access-Control-Allow-Origin – Specifies the origin(s) that are allowed to request the resource
  • Access-Control-Allow-Methods – Mentions the HTTP request methods that are allowed to make CORS requests. Other methods will be denied access.
  • Access-Control-Allow-Headers – Specifies which header types are allowed in actual CORS request.
  • Access-Control-Max-Age – Defines how long the result of preflight requests should be cached.

Similarly, you can use if condition along with $request_method to allow CORS only for specific request methods.

location / {
if ($request_method ~* '(GET|POST|PUT|DELETE|PATCH)') {
add_header 'Access-Control-Allow-Origin' '*';
...
}
}

Once you have modified the NGINX Configuration, save and close the file.

3. Restart NGINX Server

Restart NGINX server to apply changes.

$ sudo service nginx restart

Conclusion

In this article, we have learnt how to set up CORS in NGINX server. The key is to set the appropriate response headers for the required location or server blocks. We have learnt how to configure preflight requests for CORS. We have also learnt how to allow cross domain requests from one, multiple as well as all domains. You can use any of these configurations as per your requirement. Please note, enabling CORS can reduce security of your website, since you are basically accepting requests from other domains. So enable CORS in NGINX only if you really need it, and that too for only those URLs where it is absolutely necessary.

Also read:
How to Increase Request Timeout in NGINX
How to Uninstall NGINX
How to Password Protect Directory in NGINX

Leave a Reply

Your email address will not be published. Required fields are marked *