What is CORS?
Cross-Origin Resource Sharing (CORS) is a header-based mechanism that specifies how web browsers and servers interact and determines the safety of cross-origin HTTP requests and data transfers. Origin, in this case, includes both the port, hostname, and scheme associated with a request. Depending on the setup, CORS allows or disallows access to resources that are located outside of a domain from which resources were initially provided.
CORS is a way of relaxing the same-origin policy (SOP) to enable controlled access to one website domain from another via the use of HTTP requests. This controlled access is achieved via HTTP headers and the instructions contained therein. As part of the CORS response, a server can also inform a client if cookies or authentication data can be sent with a request.
The CORS policy does not protect against cross-origin attacks and may even enable them under certain conditions. A poor cross-origin resource sharing setup may, in fact, make cross-site request forgery (CSRF) and cross-site scripting (XSS) attacks easier, which is why it must be understood and implemented well.
One of the protocol headers used in CORS is the Access-Control-Allow-Origin header. This header is returned by servers when a cross-origin request is allowed, along with the conditions under which it is permitted.
CORS preflight request scenario
The CORS specification includes the possibility for browsers to perform a “preflight request” to a server via the OPTIONS method.
This is used to determine whether they will be allowed to perform a specific cross-domain request, especially one that contains non-standard HTTP methods or headers that can modify data. The preflight request is a security measure to protect servers from the greater flexibility afforded under CORS.
In this scenario, the browser sends headers to the server using the OPTIONS method that specifies the methods and headers it intends to use in the actual request. The client request will be made if the server allows the methods and headers in the response.
HTTP request and response headers
Under CORS, many additional headers are used both in the cross-origin request and response to navigate the exchange. These include:
HTTP client request headers:
- Origin
- Access-Control-Request-Method
- Access-Control-Request-Headers
HTTP server response headers:
- Access-Control-Allow-Origin
- Access-Control-Allow-Credentials
- Access-Control-Expose-Headers
- Access-Control-Max-Age
- Access-Control-Allow-Methods
- Access-Control-Allow-Headers
You can learn more about the different types of headers utilized as a part of CORS from Mozilla’s detailed Cross-Origin Resource Sharing (CORS) article.

What is Access-Control-Allow-Origin?
When the Access-Control-Allow-Origin response header is implemented, it will be included in the response of one server (domain) to another that is making the cross-origin request. In addition, it will specify which request origin is allowed.
The client (browser) then compares the origin of the website requesting access to the one specified in the header response by the domain serving the resource to determine if they match. If they do, it proceeds with the request and allows code running on the requesting website to access the response. The browser will not share the server response if the origin is not included in the header.
Roughly speaking, this would look like this:
- Origin A (http://siteA.com) requests access to resources from Origin B (http://siteB.com) through, for example, a request header and GET method.
- The Origin B server responds and includes Access-Control-Allow-Origin: http://siteA.com in the header.
- The browser compares the allowed origin in the header to the requesting Origin A and shares the response if these match.
Passing credentials with cross-origin resource requests
Typically, Access-Control-Allow-Origin responses are passed on to the requesting origin without credentials such as cookies or authorization headers, even if these are sent with the request.
However, using the “Access-Control-Allow-Credentials: true” along with Access-Control-Allow-Origin will allow the actual request to be made and the response to be read.
Access-Control-Allow-Origin response header values
Access-Control-Allow-Origin can have several values. These are the wildcard value (*), the null value, and specific origin values you wish to allow (i.e., origins that have been whitelisted).
Allowed origins must be included in a list against which the server will check origin requests. The request will be granted if the domain is included in the list.
The wildcard value means that requests from any domain are allowed. This value is typically used and considered safe when the content on a domain is considered public and intended to be freely accessible. In other words, it is the appropriate value for requests without credentials.
This value does not allow requests to supply credentials – i.e., HTTP authentication, cookies, and client-side certificates – and cannot be used with another value. Allowing for “Access-Control-Allow-Credentials: true” along with the wildcard via a workaround can be very dangerous as it can expose authentication information to untrusted parties.
The null value for an origin (Access-Control-Allow-Origin: “null”) should not be used by servers as it may create a vulnerability. Setting the origin to null leaves the door open for attackers to generate requests that contain a null value in the origin header.
If the null value is whitelisted, then an attacker’s inclusion in the header will be allowed. On the attacker’s side, “null” may be associated with a hostile file which will provide it with access to the server’s resources.
Does Access-Control-Allow-Origin support multiple origins?
While the header does support multiple origins, browsers usually do not.
A whitelist of permitted domains must be created to offer support to multiple origins. However, this must be done carefully, as blanket access permission to a domain and all of its subdomains may easily open the door to unwanted visitors and requests.
How to enable Access-Control-Allow-Origin headers
To enable the use of these headers, you must first add CORS support to your server. See the Enable CORS website for a full breakdown to learn how to implement CORS for a specific platform.
This resource will provide you with all of the information required to implement CORS and Access-Control-Allow-Origin headers for:
- Apache
- App Engine
- ASP.NET
- AWS API Gateway
- BFE
- Caddy
- CGI Scripts
- ColdFusion
- ExpressJS
- Flask
- IIS6
- IIS7
- Spring Boot Applications in Kotlin
- Meteor
- nginx
- Perl
- PHP
- Tomcat
- Virtuoso
- WCF
For additional information about CORS and implementing it at the HTTP server or web application level, see the official W3C CORS Enabled resource.
Secure Third-Party Access to a REST API
These days, enforcing security policies on web applications is ‘relatively easy’ using the correct headers in HTTP responses. Take the following example of an application:
- https://example.org delivers the frontend of the great example applications to its users. This is the domain a user knows.
- https://api.example.org is handling all information. If the user logs in, the frontend sends a request to this domain and changes according to the response.
In this case, it should not be possible for anybody else but the frontend to access the rest API. By now, browsers try to protect the user and block malicious requests. For example, such a request would be to visit https://malicious.example.org, and the web application there would try to access https://api.example.org. To prevent that, the webserver delivering the API can send the Access-Control-Allow-Origin header as follows:
Access-Control-Allow-Origin: https://example.org
This way, the malicious website has no more access to our API if the user uses a recent browser.

This way, the malicious website has no more access to our API if the user uses a recent browser.
No security headers set? Better use them when developing a web application.
If the application setup becomes more complex, things get much more complicated to configure. Assume that there are more systems:
- https://staging.example.org, which holds the staging environment of the frontend.
- https://payment.example.org, the external payment provider that needs to access the API to confirm payments
- https://localhost:8080 is the local server that the developer uses to try out changes locally.
The Access-Control-Allow-Origin header cannot contain multiple domains, like separating different domains via spaces or commas. Besides specifying a single domain, only ”*’ is another valid option, which would allow access from everywhere. And this is no secure option in this case.
Therefore the API needs to check the request’s origin and adjust the header field accordingly. For example, it can use the ”Origin’ header on the request to check who is accessing the resource. If one of the allowed domains, it sets the Access-Control-Allow-Origin accordingly. Otherwise, it just sets it to https://example.org so that the browser blocks the request. The following example explains how a Laravel project can make use of middleware to set this header correctly:
<?php
class CORSMiddleware
{
[...]
/**
* Add Access Control headers.
*
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Http\Response $response
*
* @return \Illuminate\Http\Response
*/
protected function addAccessControlHeaders($request, $response)
{
$possibleOrigins = [
'https://example.com',
'https://api.example.com',
'https://staging.example.com',
'https://payment.example.org',
];
if (env('APP_ENV') == 'development') {
$possibleOrigins[] = 'https://localhost:8080';
}
if (in_array($request->header('origin'), $possibleOrigins)) {
$origin = $request->header('origin');
} else {
$origin = 'https://example.com';
}
$headers = [
'Access-Control-Allow-Origin' => $origin,
'Vary' => 'Origin',
];
foreach ($headers as $header => $value) {
$response->header($header, $value);
}
return $response;
}
}
In this case, it should not be possible for anybody else but the frontend to access the API. By now, browsers try to protect the user and block malicious requests. For example, such a request would be to visit https://malicious.example.org, and the web application there would try to access https://api.example.org. To prevent that, the webserver delivering the API can send the Access-Control-Allow-Origin header as follows:
In addition to the Access-Control-Allow-Origin header, the Vary header is set so that the browser knows that this API’s response may vary depending on the origin. Therefore it will not use any cached response when the API is called from a different frontend site in the same browser.
FAQs
What is Access-Control-Allow-Origin?
Access-Control-Allow-Origin is one of the HTTP headers used by Cross-Origin Resource Sharing (CORS) to manage requests between origins (domains), such as client-side JavaScript requests.
When to use Access-Control-Allow-Origin?
An origin uses this header in instances where it makes sense to enable serving resources to another origin. This may include domains that serve entirely public information (such as web fonts) and want to make it accessible to other domains but also for web applications that exchange data (such as payment services).
How does CORS handle non-simple requests?
Requests that include non-simple verbs (such as PUT or DELETE) or request headers (such as custom headers or cookies) must first pass a preflight request under COST. This is because the browser will first send an OPTIONS request to the server, and if the server responds with headers that allow non-simple headers or methods, the browser will proceed with the actual request.
Does CORS protect against cross-origin attacks?
No, CORS does not address vulnerabilities associated with cross-origin attacks, such as CSRF and XSS. CORS is concerned with handling cross-origin requests safely, and its purpose is to enable greater freedom and functionality than is afforded by a strict same-origin security policy. A bad CORS setup may make cross-origin attacks easier, though.