15 September 2023

Understanding and Implementing CORS in NGINX: A Detailed Guide

Learn what HTTP header-level CORS is and how to implement it in an NGINX environment to improve the security and functionality of your website.

In the modern world of the web, security is a major concern for developers and system administrators. One of the security features that is often underestimated but is fundamental is that of CORS, or Cross-Origin Resource Sharing. This functionality is particularly relevant for companies that deal with hosting and systems engineering, especially those that use web servers like NGINX. In this article, we will explore in detail what HTTP header-level CORS are and what they are used for, with a particular focus on how to implement them in an NGINX environment.

What is CORS?

CORS, an acronym for "Cross-Origin Resource Sharing", is a web security protocol implemented in modern browsers to control and manage resource requests between different web domains. In simpler terms, CORS is a set of HTTP rules and headers that allow a website to access resources on another website without violating the Same-Origin Policy.

Same-Origin Policy

To fully understand the importance of CORS, it is crucial to understand the politics of the same origin. This is a security measure implemented in browsers to limit interactions between different domains. According to this policy, scripts running on a web page can only access resources from the same domain, protocol and port from which the page was loaded. For example, if a website on http://dominioA.com try to make an AJAX request to http://dominioB.com, the request will be blocked unless dominioB.com does not provide adequate CORS authorizations.

Types of Resources

CORS is applicable to a variety of web resources, including:

  • JavaScript file
  • CSS style sheets
  • Images and videos
  • Font
  • RESTful API and JSON data

Operation of CORS

When a resource from domain A tries to access a resource on domain B, the browser sends an HTTP request to domain B. This request includes several CORS headers, such as Origin, which indicates which domain the request comes from. The server on domain B can then respond with its own CORS headers, such as Access-Control-Allow-Origin, to indicate whether the request is authorized or not.

 

If the request is authorized, the browser proceeds with the operation. Otherwise, the browser blocks the request and usually reports an error in the development console, telling you that the request was blocked due to the same-origin policy.

CORS Preflight

In some cases, before sending the "real" request, the browser sends a preliminary request called "preflight" using the HTTP method OPTIONS. This is to check whether the next request is safe to make. The server responds to this preliminary request with the appropriate CORS headers, indicating whether the original request is allowed.

CORS is, in short, an essential mechanism that allows greater interactivity and integration between websites, while maintaining high security standards. Through a set of HTTP headers and well-defined rules, CORS offers a way to securely bypass same-origin policy restrictions, making the web a more flexible and secure environment.

Because it is important ?

In the modern web era, applications are often distributed across multiple domains or services. For example, you might have a front-end application hosted on dominioA.com which interacts with an API backend on dominioB.com. In an ideal world, you would like these two parts of the application to be able to freely communicate with each other to provide a smooth and functional user experience. However, the reality is a little more complicated due to a security measure implemented in browsers called the Same-Origin Policy.

The Same Origin Policy was introduced to protect users from potential Cross-Site Request Forgery (CSRF), Cross-Site Scripting (XSS) attacks, and other types of security vulnerabilities that may arise when websites from different origins interact between them. In practice, this policy prevents a web page from making requests to another domain without explicit authorization. So, without a mechanism like CORS, the browser would block any attempts from the front end to dominioA.com to make requests to the backend on dominioB.com.

This becomes a significant problem when dealing with modern web applications that require a high degree of interactivity and dynamic functionality. For example, if you have an online store with a shopping cart that needs to check the availability of a product in real time, or a social media application that needs to load posts from an API server, the limitation imposed by the same origin policy could represent an insurmountable obstacle.

That's where CORS comes in. With CORS, you can set specific rules on the backend server that allow the frontend to interact with it despite them being hosted on different domains. This not only improves the functionality and usability of web applications, but does so in a way that maintains high security measures. In other words, CORS offers the best balance between security and functionality, allowing developers to build rich, interactive web applications without compromising end-user security.

CORS at HTTP Header Level

CORS works by adding new HTTP headers that allow servers to describe which sources are allowed to access resources on a web server. Some of the most common CORS headers include:

  • Access-Control-Allow-Origin: Specifies which sources can access the resource.
  • Access-Control-Allow-Methods: Specifies the HTTP methods that can be used when accessing the resource.
  • Access-Control-Allow-Headers: Specifies headers that can be used when making an HTTP request.

CORS implementation in NGINX

NGINX is one of the most popular web servers and offers high flexibility to configure CORS settings. Here is an example of how you can configure CORS in NGINX:

location /api/ { if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; 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' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; } if ($request_method = 'GET') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; } }

In this example, we used the directive location to specify that CORS rules apply only to requests that point to the resource /api/. We then used the variable $request_method to apply different sets of CORS headers depending on the HTTP method used.

Security Considerations

While the use of wildcard * in the header Access-Control-Allow-Origin While it is convenient to allow any source to access your resources, it is also a potentially dangerous practice from a security perspective. We recommend that you explicitly specify which sources are allowed.

Conclusion

CORS are a critical building block for security and functionality in modern web development. They allow secure communication between different domains, overcoming the limitations imposed by the same origin policy. Implementing CORS in NGINX is relatively simple but requires a detailed understanding of HTTP headers and potential security implications. We hope this article has provided you with the information you need to effectively and safely implement CORS in your NGINX environment.

Do you have doubts? Don't know where to start? Contact us!

We have all the answers to your questions to help you make the right choice.

Chat with us

Chat directly with our presales support.

0256569681

Contact us by phone during office hours 9:30 - 19:30

Contact us online

Open a request directly in the contact area.

INFORMATION

Managed Server Srl is a leading Italian player in providing advanced GNU/Linux system solutions oriented towards high performance. With a low-cost and predictable subscription model, we ensure that our customers have access to advanced technologies in hosting, dedicated servers and cloud services. In addition to this, we offer systems consultancy on Linux systems and specialized maintenance in DBMS, IT Security, Cloud and much more. We stand out for our expertise in hosting leading Open Source CMS such as WordPress, WooCommerce, Drupal, Prestashop, Joomla, OpenCart and Magento, supported by a high-level support and consultancy service suitable for Public Administration, SMEs and any size.

Red Hat, Inc. owns the rights to Red Hat®, RHEL®, RedHat Linux®, and CentOS®; AlmaLinux™ is a trademark of AlmaLinux OS Foundation; Rocky Linux® is a registered trademark of the Rocky Linux Foundation; SUSE® is a registered trademark of SUSE LLC; Canonical Ltd. owns the rights to Ubuntu®; Software in the Public Interest, Inc. holds the rights to Debian®; Linus Torvalds holds the rights to Linux®; FreeBSD® is a registered trademark of The FreeBSD Foundation; NetBSD® is a registered trademark of The NetBSD Foundation; OpenBSD® is a registered trademark of Theo de Raadt. Oracle Corporation owns the rights to Oracle®, MySQL®, and MyRocks®; Percona® is a registered trademark of Percona LLC; MariaDB® is a registered trademark of MariaDB Corporation Ab; REDIS® is a registered trademark of Redis Labs Ltd. F5 Networks, Inc. owns the rights to NGINX® and NGINX Plus®; Varnish® is a registered trademark of Varnish Software AB. Adobe Inc. holds the rights to Magento®; PrestaShop® is a registered trademark of PrestaShop SA; OpenCart® is a registered trademark of OpenCart Limited. Automattic Inc. owns the rights to WordPress®, WooCommerce®, and JetPack®; Open Source Matters, Inc. owns the rights to Joomla®; Dries Buytaert holds the rights to Drupal®. Amazon Web Services, Inc. holds the rights to AWS®; Google LLC holds the rights to Google Cloud™ and Chrome™; Microsoft Corporation holds the rights to Microsoft®, Azure®, and Internet Explorer®; Mozilla Foundation owns the rights to Firefox®. Apache® is a registered trademark of The Apache Software Foundation; PHP® is a registered trademark of the PHP Group. CloudFlare® is a registered trademark of Cloudflare, Inc.; NETSCOUT® is a registered trademark of NETSCOUT Systems Inc.; ElasticSearch®, LogStash®, and Kibana® are registered trademarks of Elastic NV Hetzner Online GmbH owns the rights to Hetzner®; OVHcloud is a registered trademark of OVH Groupe SAS; cPanel®, LLC owns the rights to cPanel®; Plesk® is a registered trademark of Plesk International GmbH; Facebook, Inc. owns the rights to Facebook®. This site is not affiliated, sponsored or otherwise associated with any of the entities mentioned above and does not represent any of these entities in any way. All rights to the brands and product names mentioned are the property of their respective copyright holders. Any other trademarks mentioned belong to their registrants. MANAGED SERVER® is a trademark registered at European level by MANAGED SERVER SRL, Via Enzo Ferrari, 9, 62012 Civitanova Marche (MC), Italy.

Back to top