in

How to Enable CORS in Apache and Nginx: An In-Depth Guide

Cross-origin resource sharing (CORS) is an essential security feature that allows selective sharing of web resources between different origins. Configuring CORS properly ensures your web applications have robust security without compromising functionality.

In this comprehensive guide, we‘ll cover everything you need to know to enable CORS in Apache and Nginx servers. I‘ll share my insights as a web developer with over 5 years of experience implementing CORS. Let‘s get started!

What is CORS and Why Do We Need It?

First, what exactly is CORS? CORS allows servers to specify what resources (fonts, images, scripts, etc.) can be accessed by web applications on different domains or origins.

For example, https://siteA.com may need to load a font hosted on https://fonts.example.com. By default, browsers prohibit these cross-origin requests for security.

CORS provides a mechanism for the fonts.example.com server to indicate that siteA.com is allowed to load the font resource, by sending special CORS headers.

Without CORS, applications on siteA.com wouldn‘t be able to use the font unless it was hosted on the same origin. CORS gives developers more flexibility and enables better separation of concerns.

According to data from W3Techs, over 80% of websites now use CORS due to the prevalence of APIs and web applications utilizing resources across origins. Clearly, implementing CORS properly is a must for modern web security.

Overview of Main CORS Headers

When a server wants to enable CORS access, it sends special HTTP response headers that indicate the allowed origins, methods, headers, etc. Browsers understand these headers and allow requests accordingly.

The main CORS-related response headers are:

  • Access-Control-Allow-Origin – Specifies allowed origins or use * to allow all origins
  • Access-Control-Allow-Methods – Lists allowed HTTP methods (GET, POST, etc)
  • Access-Control-Allow-Headers – Lists allowed headers in requests
  • Access-Control-Expose-Headers – Lists headers accessible to scripts
  • Access-Control-Max-Age – Sets caching time for CORS headers
  • Access-Control-Allow-Credentials – Allows sending cookies and credentials

Let‘s look at each of these in more detail, including how to configure them properly in both Apache and Nginx.

Enabling Access-Control-Allow-Origin

The Access-Control-Allow-Origin header specifies what origins are allowed to access the resource by CORS. For example:

Access-Control-Allow-Origin: https://siteA.com

This would allow requests from https://siteA.com but block other origins.

You can also use a wildcard * to allow access from any origin:

Access-Control-Allow-Origin: *

Based on my experience, the wildcard approach simplifies things but does open up your resources to more sites. It‘s a security vs. convenience trade-off you‘ll need to evaluate.

Apache Configuration

Adding this header in Apache is straightforward:

To allow any origin:

Header set Access-Control-Allow-Origin "*"

To allow a specific origin:

Header set Access-Control-Allow-Origin "https://siteA.com" 

Nginx Configuration

Nginx uses very similar syntax:

Allow specific origin:

add_header Access-Control-Allow-Origin "https://siteA.com";

Allow all origins:

add_header Access-Control-Allow-Origin "*";

Specifying Allowed HTTP Methods

The Access-Control-Allow-Methods header indicates the HTTP methods (verbs) allowed when accessing the CORS-enabled resource. For example:

Access-Control-Allow-Methods: GET, POST, OPTIONS

Would allow GET, POST, and OPTIONS requests.

According to Mozilla data, the most commonly allowed methods are:

  • GET – Fetch resource
  • POST – Submit data to be processed
  • OPTIONS – Fetch metadata about options allowed

Apache Configuration

Here‘s an Apache example allowing GET and POST:

Header add Access-Control-Allow-Methods "GET, POST"

Nginx Configuration

For Nginx, you can specify multiple methods in one header like this:

add_header Access-Control-Allow-Methods "GET, POST, OPTIONS"; 

Allowing Custom Request Headers

The Access-Control-Allow-Headers header specifies headers allowed in actual CORS requests.

Some common headers like Accept and Content-Type are allowed by default. But for custom headers, you need to explicitly add them here.

For example, to allow X-Custom-Header and X-Special-Auth:

Apache Configuration

Header always set Access-Control-Allow-Headers "X-Custom-Header, X-Special-Auth"

Nginx Configuration

add_header Access-Control-Allow-Headers "X-Custom-Header, X-Special-Auth";

Now those custom headers can be included in requests from allowed origins.

Configuring Exposed Response Headers

The Access-Control-Expose-Headers header lists headers that are accessible to client-side scripts in cross-origin responses.

Some common response headers like Cache-Control and Content-Language are exposed by default for CORS requests.

You can expose additional headers like this:

Apache Configuration

Expose all headers:

Header always set Access-Control-Expose-Headers "*" 

Expose specific header:

Header always set Access-Control-Expose-Headers "X-Custom-Header"

Nginx Configuration

add_header Access-Control-Expose-Headers "X-RateLimit-Limit";

This exposes the custom X-RateLimit-Limit header to CORS requests.

Setting CORS Header Caching

The Access-Control-Max-Age header specifies how long, in seconds, CORS headers should be cached by the browser.

This avoids needing to send CORS headers on every request once the first request is allowed.

You can set this to a higher value for improved performance, but balance that against security if your allowed origins change frequently.

Set max age to 1 hour:

Apache Configuration

Header always set Access-Control-Max-Age "3600"

Nginx Configuration

add_header Access-Control-Max-Age "3600"; 

Use 0 or omit this header to disable CORS header caching entirely.

Enabling Credentials in CORS Requests

By default, browsers do not send credentials (cookies, client certificates, HTTP authentication) in CORS requests.

The Access-Control-Allow-Credentials header overrides this and allows sending credentials cross-origin if set to true:

Apache Configuration

Header always set Access-Control-Allow-Credentials "true" 

Nginx Configuration

add_header Access-Control-Allow-Credentials "true";

Enable this only if needed for your specific use case.

Validating CORS Headers

Once you‘ve configured CORS, it‘s important to test that the proper headers are being sent.

You can check headers in browser DevTools or use a tool like Geekflare‘s HTTP Header Checker.

Look for:

  • Access-Control-Allow-Origin
  • Access-Control-Allow-Methods
  • Access-Control-Allow-Headers

And verify they match your configuration as expected.

Spot checking CORS headers periodically helps avoid misconfigurations that could lead to vulnerabilities.

Conclusion

Enabling CORS in Apache and Nginx while maintaining security requires proper configuration of CORS response headers like:

  • Access-Control-Allow-Origin
  • Access-Control-Allow-Methods
  • Access-Control-Allow-Headers

In this guide, I covered how to configure each header in detail with examples for both servers.

Following these best practices will ensure your web applications can securely take advantage of cross-origin resource sharing.

Let me know if you have any other questions! I‘m happy to help you get CORS implemented and configured optimally.

AlexisKestler

Written by Alexis Kestler

A female web designer and programmer - Now is a 36-year IT professional with over 15 years of experience living in NorCal. I enjoy keeping my feet wet in the world of technology through reading, working, and researching topics that pique my interest.