How to Use Access-Control-Allow-Origin? Does It Just Go in Between The HTML Head Tags

How do I use Access-Control-Allow-Origin? Does it just go in between the html head tags?

That is an HTTP header. You would configure your webserver or webapp to send this header ideally. Perhaps in htaccess or PHP.

Alternatively you might be able to use

<head>...<meta http-equiv="Access-Control-Allow-Origin" content="*">...</head>

I do not know if that would work. Not all HTTP headers can be configured directly in the HTML.

This works as an alternative to many HTTP headers, but see @EricLaw's comment below. This particular header is different.

Caveat

This answer is strictly about how to set headers. I do not know anything about allowing cross domain requests.

About HTTP Headers

Every request and response has headers. The browser sends this to the webserver

GET /index.htm HTTP/1.1

Then the headers

Host: www.example.com
User-Agent: (Browser/OS name and version information)
.. Additional headers indicating supported compression types and content types and other info

Then the server sends a response

Content-type: text/html
Content-length: (number of bytes in file (optional))
Date: (server clock)
Server: (Webserver name and version information)

Additional headers can be configured for example Cache-Control, it all depends on your language (PHP, CGI, Java, htaccess) and webserver (Apache, etc).

What is an origin header and where do I insert Access-Control-Allow-Origin?

Access-Control-Allow-Origin can't go inside the head tags, it is an html header so it belongs in php script.

How does the 'Access-Control-Allow-Origin' header work?

Access-Control-Allow-Origin is a CORS (cross-origin resource sharing) header.

When Site A tries to fetch content from Site B, Site B can send an Access-Control-Allow-Origin response header to tell the browser that the content of this page is accessible to certain origins. (An origin is a domain, plus a scheme and port number.) By default, Site B's pages are not accessible to any other origin; using the Access-Control-Allow-Origin header opens a door for cross-origin access by specific requesting origins.

For each resource/page that Site B wants to make accessible to Site A, Site B should serve its pages with the response header:

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

Modern browsers will not block cross-domain requests outright. If Site A requests a page from Site B, the browser will actually fetch the requested page on the network level and check if the response headers list Site A as a permitted requester domain. If Site B has not indicated that Site A is allowed to access this page, the browser will trigger the XMLHttpRequest's error event and deny the response data to the requesting JavaScript code.

Non-simple requests

What happens on the network level can be slightly more complex than explained above. If the request is a "non-simple" request, the browser first sends a data-less "preflight" OPTIONS request, to verify that the server will accept the request. A request is non-simple when either (or both):

  • using an HTTP verb other than GET or POST (e.g. PUT, DELETE)
  • using non-simple request headers; the only simple requests headers are:
  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type (this is only simple when its value is application/x-www-form-urlencoded, multipart/form-data, or text/plain)

If the server responds to the OPTIONS preflight with appropriate response headers (Access-Control-Allow-Headers for non-simple headers, Access-Control-Allow-Methods for non-simple verbs) that match the non-simple verb and/or non-simple headers, then the browser sends the actual request.

Supposing that Site A wants to send a PUT request for /somePage, with a non-simple Content-Type value of application/json, the browser would first send a preflight request:

OPTIONS /somePage HTTP/1.1
Origin: http://siteA.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type

Note that Access-Control-Request-Method and Access-Control-Request-Headers are added by the browser automatically; you do not need to add them. This OPTIONS preflight gets the successful response headers:

Access-Control-Allow-Origin: http://siteA.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type

When sending the actual request (after preflight is done), the behavior is identical to how a simple request is handled. In other words, a non-simple request whose preflight is successful is treated the same as a simple request (i.e., the server must still send Access-Control-Allow-Origin again for the actual response).

The browsers sends the actual request:

PUT /somePage HTTP/1.1
Origin: http://siteA.com
Content-Type: application/json

{ "myRequestContent": "JSON is so great" }

And the server sends back an Access-Control-Allow-Origin, just as it would for a simple request:

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

See Understanding XMLHttpRequest over CORS for a little more information about non-simple requests.

Set Access-Control-Allow-Origin without server side scripting

Try using url-rewrite. You will have to configure the Filter in your web application, but you won't have to write any Java code to do it.

Access-Control-Allow-Origin Multiple Origin Domains?

Sounds like the recommended way to do it is to have your server read the Origin header from the client, compare that to the list of domains you would like to allow, and if it matches, echo the value of the Origin header back to the client as the Access-Control-Allow-Origin header in the response.

With .htaccess you can do it like this:

# ----------------------------------------------------------------------
# Allow loading of external fonts
# ----------------------------------------------------------------------
<FilesMatch "\.(ttf|otf|eot|woff|woff2)$">
<IfModule mod_headers.c>
SetEnvIf Origin "http(s)?://(www\.)?(google.com|staging.google.com|development.google.com|otherdomain.example|dev02.otherdomain.example)$" AccessControlAllowOrigin=$0
Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
Header merge Vary Origin
</IfModule>
</FilesMatch>

The 'Access-Control-Allow-Origin' header contains multiple values

I added

config.EnableCors(new EnableCorsAttribute(Properties.Settings.Default.Cors, "", ""))

as well as

app.UseCors(CorsOptions.AllowAll);

on the server. This results in two header entries. Just use the latter one and it works.

Set cookies for cross origin requests

Cross site approach

To allow receiving & sending cookies by a CORS request successfully, do the following.

Back-end (server) HTTP header settings:

  • Set the HTTP header Access-Control-Allow-Credentials value to true.

  • Make sure the HTTP headers Access-Control-Allow-Origin and Access-Control-Allow-Headers are set. Don't use a wildcard *. When you set the allowed origin make sure to use the entire origin including the scheme, i.e. http is not same as https in CORS.

For more info on setting CORS in express js read the docs here.

Cookie settings:
Cookie settings per Chrome and Firefox update in 2021:

  • SameSite=None
  • Secure

When doing SameSite=None, setting Secure is a requirement. See docs on SameSite and on requirement of Secure. Also note that Chrome devtools now have improved filtering and highlighting of problems with cookies in the Network tab and Application tab.

Front-end (client): Set the XMLHttpRequest.withCredentials flag to true, this can be achieved in different ways depending on the request-response library used:

  • ES6 fetch() This is the preferred method for HTTP. Use credentials: 'include'.

  • jQuery 1.5.1 Mentioned for legacy purposes. Use xhrFields: { withCredentials: true }.

  • axios As an example of a popular NPM library. Use withCredentials: true.

Proxy approach

Avoid having to do cross site (CORS) stuff altogether. You can achieve this with a proxy. Simply send all traffic to the same top level domain name and route using DNS (subdomain) and/or load balancing. With Nginx this is relatively little effort.

This approach is a perfect marriage with JAMStack. JAMStack dictates API and Webapp code to be completely decoupled by design. More and more users block 3rd party cookies. If API and Webapp can easily be served on the same host, the 3rd party problem (cross site / CORS) dissolves. Read about JAMStack here or here.

Sidenote

It turned out that Chrome won't set the cookie if the domain contains a port. Setting it for localhost (without port) is not a problem. Many thanks to Erwin for this tip!

Access-Control-Allow-Origin' issue when API call made from React (Isomorphic app)

CORS is a browser feature. Servers need to opt into CORS to allow browsers to bypass same-origin policy. Your server would not have that same restriction and be able to make requests to any server with a public API. https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Create an endpoint on your server with CORS enabled that can act as a proxy for your web app.

I get No 'Access-Control-Allow-Origin' header error even though I set it

Your problem is related with the fact that 'Access-Control-Allow-Origin': '*' needs to be set at the server. By doing this you enable CORS (Cross-Origin Resource Sharing)

Browsers have a security policy that prevents your javascript code to make requests from services that are not within your domain. For example if your javascript code is executed in http://example.com and the service you are targeting is found at http://example.com/api/myservice then your request will go through normally. If however, the service you are trying to access is at http://someotherdomain.net then the browser will not complete your request successfully even if the server responds normally.

You will have to read documentation about whatever web server software you're using on how to set headers on it. When you set 'Access-Control-Allow-Origin': '*' on your server your are essentially saying to the world - "You can load my data onto any browser application that lives in any domain". This means anyone in the world can call your service and if you wish to prevent this, you will have to implement authentication (common for this are API key models).



Related Topics



Leave a reply



Submit