Session cookie not sending with XHR requests - reactjs

My react app (from domain react-app.com) is loaded inside a website beautiful-site.com and the requests sending from react app doesn't sending the session cookie associated with it.
The workaround I had was added the below header in server and in react app XHR requests sent with withCredentials: true
Access-Control-Allow-Origin: https://beautiful-site.com
Access-Control-Allow-Credentials: true
The issue is I can specify a particular site in Access-Control-Allow-Origin, because the react app will be added to many sites not one.
Is there any way to get the session cookie send from react app?

Answer is no, but you have workaround: when you set the withCredentials you can't have an Access-Control-Allow-Origin: *.
The fix must be done server side: your API service must returns domain of the request in the Access-Control-Allow-Origin, commonly taken from the Origin header.
See No 'Access-Control-Allow-Origin' header is present on the requested resource—when trying to get data from a REST API (the How to fix “Access-Control-Allow-Origin header must not be the wildcard” problems subsection) for techincal details.

Related

Cookie not set in request header when request is sent from React

My backend is in Django and Frontend is in React.
I have set up CROS header and added settings as follows.
Django settings
For sending request I am using fetch and i have set credentials: 'include'.
I am using the session based authentication, So when I signin session of a user starts. Then from the parent component (from useEffect) I send a request to backend to fetch Jobs. Things work fine in this case. Below is the header of this particular request. It has COOKIE
Request header 1
when I send request from child component of react, COOKIE is not present in the header. Below is the header of this particular request.
Request header 2
I am not able to get why this thing is happening, One more difference in both the request headers is the value of HTTP_SEC_FETCH_SITE in request header.
In first request value of HTTP_SEC_FETCH_SITE is same-site whereas in second request HTTP_SEC_FETCH_SITE is cross-site. Even though request is sent through http://localhost:3000 in both cases why value of HTTP_SEC_FETCH_SITE is different.
value of HTTP_SEC_FETCH_SITE was different for these two requests beccause baseurl for first request was set to http://localhost:8000/ where as for second request it was
http://127.0.0.1:8000/.
Event though both are local servers on same port, don't know why this thing happens.
I changed both baseurl to http://localhost:8000/ and things worked. Cookie was set in both the requests.

CORS and ReactJS using Etsy APIs

I'm a n00b trying to learn React. I'm building a website that uses Etsy's APIs. Registered an app there and everything. They have a page that talks about CORS and proxying here: https://www.etsy.com/developers/documentation/getting_started/jsonp
So for example, I'm trying to do a fetch on a store's listings:
fetch('https://openapi.etsy.com/v2/shops/[shopId]/listings/active?api_key=[apiKey]')
But that violates the browser's CORS policy. No problem, says the documentation on Etsy. You can always use their proxy: beta-api.etsy.com. So I add that to my package.json file:
"proxy": "https://beta-api.etsy.com/"
And then I change my fetch line:
fetch('/v2/shops/[shopId]/listings/active?api_key=[apiKey]')
But CORS is still being violated in the browser.
Access to fetch at 'https://www.etsy.com/shop/beta-api/v2/shops/[shopId]/listings/active?api_key=[apiKey]' (redirected from 'http://localhost:3000/v2/shops/[shopId]/listings/active?api_key=[apiKey]') from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I don't want an opaque response, either, so doing "no-cors" really doesn't help. Does anyone have any recommendations on how I can at least get a local website up and running?
You are getting that error because your server has set Access-Control-Allow-Origin to restrict cross-domain traffic. You are sending your request from your localhost so that is considered cross-domain.
If you are able to change your server settings to set Access-Control-Allow-Origin: * then you can make those requests without a CORS error but I don't suggest doing this.
The best solution would probably be a proxy server. You can use cors-anywhere heroku app to easily do this.
Excerpt from Medium Article on this issue
The cors-anywhere server is a proxy that adds CORS headers to a
request. A proxy acts as an intermediary between a client and server.
In this case, the cors-anywhere proxy server operates in between the
frontend web app making the request, and the server that responds with
data.
Similar to the Allow-control-allow-origin plugin, it adds the
more open Access-Control-Allow-Origin: * header to the response.
Say your frontend is trying to make a GET request to:
https://joke-api-strict-cors.appspot.com/jokes/random
But this api does not have a Access-Control-Allow-Origin value
in place that permits the web application domain to access it.
So instead, send your GET request to:
https://cors-anywhere.herokuapp.com/https://joke-api-strict-cors.appspot.com/jokes/random
The proxy server receives the
https://joke-api-strict-cors.appspot.com/jokes/random
from the url above. Then it makes the request to get that server’s
response. And finally, the proxy applies the Access-Control-Allow-
Origin: * to that original response.

CORS issue between web/android/ios

when trying to $.ajax to fetch some content from other websites in my website, I got the error.
Failed to load https://www.pinterest.com/: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8100' is therefore not allowed access.
I knew if the target website didn't allow localhost:8100 to fetch the data, I cannot fetch it in the client side on the web.
However, I found that mobile app (not mobile browser, but android/ios application) does not have the issue, they can simply get the website content by their default mobile built-in HTTP get function.
Do i want to ask why mobile will not encounter CORS issue (mobile can fetch the webcontent simply by the built-in http get function)?
thanks.
CORS is enforced by the browser to fulfill the security standard they have to meet. It does not affect requests made programmatically from any language, like a curl call on bash.
This is how CORS works, based on Wikipedia:
The browser sends the OPTIONS request with an Origin HTTP header. The value of this header is the domain that served the parent page. When a page from http://www.example.com attempts to access a user's data in service.example.com, the following request header would be sent to service.example.com: Origin: http://www.example.com.
The server at service.example.com may respond with:
An Access-Control-Allow-Origin (ACAO) header in its response indicating which origin sites are allowed. For example Access-Control-Allow-Origin: http://www.example.com
An error page if the server does not allow the cross-origin request
An Access-Control-Allow-Origin (ACAO) header with a wildcard that allows all domains: Access-Control-Allow-Origin: *
The way CORS works means it is optional. Browsers enforce it to prevent Javascript AJAX calls to perform malicious calls. But other types of consumers built by hand don't need to enforce CORS.
Think in this example:
You are the owner of somesite.com
Users authenticate to your site using the traditional cookie method
User logins into anothersite.com, built by an attacker. This site has the following code:
<script>fetch('http://somesite.com/posts/1', { method: 'DELETE' });</script>
... effectively performing a request to your site and doing bad things.
Happily, the browser will perform a preflight request when it sees a cross-domain request, and if your site does not respond saying that requests coming from anothersite.com are OK, you will be covered by default from a potential attack
This is why CORS only makes sense in the context of a browser. Javascript you send to the browser can not (at least easily) circumvent CORS because the only API that allows you to perform requests from the browser is written in stone. Additionally, there are no local storage or cookies outside of the browser.
Corolarium: Enforcing CORS is a deliberate action from the requester, or whoever is making the requests for you, not the sender. Javascript APIs in browsers enforce it. Other languages don't have the need for the reasons explained.
When running on a device, your files are served over the file:// protocol, not http://, and your origin will therefore not exist. That's why the request from the native device does not trigger CORS.

Access-Control-Allow-Origin error but request goes through

I'm currently deploying a basic API to my live server and I'm running into (what I think is) a CORS problem but there is some behavior going on that I can't explain.
I'm communicating from an AngularJS front-end to a Laravel 5 (+ laravel-cors) back-end.
I started testing with a simple jQuery AJAX call (below) and when I make a request from my local Vagrant environment (http://dev.example.local/test.html) to http://api.example.com/v1/matches I get an error about Access-Control-Allow-Origin. The weird thing is that the request does come through because the information is stored in the database via the Laravel-based API correctly.
$.ajax({
method: 'POST',
url: 'http://api.example.com/v1/players',
data: {
"username": "username",
"first_name": "First",
"last_name": "Last",
"nickname": ""
}
}).always(function(r) {
console.log(r);
});
Error:
XMLHttpRequest cannot load http://api.example.com/v1/players. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://other.example.com' is therefore not allowed access.
The console.log(r) returns {readyState: 0, responseJSON: undefined, status: 0, statusText: "error"}
I developed the application locally using a Homestead VM (API) and a Vagrant environment (application) and it's working correctly within these environments...
Some observations:
Each of these requests shows up with Method: POST, Status: 200 OK, Type: xhr in my Chrome Developer Tools.
Tools like Postman and PhpStorm's RESTful service tester correctly execute the request and the data is added without errors.
Any ideas on how to further debug this problem are welcome... I've been trying to wrap my head around this for the entire day now and I just don't know what's causing it.
Your server must return an appropriate Access-Control-Allow-Origin header in the response. For example, if the request is being sent from http://stackoverflow.com, then your server must return this header: Access-Control-Allow-Origin: http://stackoverflow.com. You can determine, server-side, what the origin is by looking at the Origin header on the request. If your server does not return this header in the response, you will not have any access to the properties of the response browser-side (such as the status code, headers, or message body). The Same Origin Policy is at the center of this restriction.
The reason you are not seeing any similar issues when the request is sent by Postman or PhpStorm's RESTful service tester is due to the fact that these services do not send an Origin header with the request, as they are not subject to the Same Origin policy. By default, the browser will append this header to any cross-origin ajax requests, as browsers are subject to the Same Origin Policy. In my previous scenario, the request header would look like this: Origin: http://stackoverflow.com. Browsers that implement the CORS spec are required to add this request header so the server is able to determine if the origin of the request has been whitelisted for cross-origin ajax requests. If this is the case, the server will return the proper Access-Control-Allow-Origin header. If not, it can simply omit the header. Browsers that do not implement the CORS spec will simply refuse to send such an ajax request.
Regarding your bewilderment as to why the request is being sent in the first place, that comes down to a distinction between "simple" and "non-simple" CORS requests. For simple CORS requests, the request will always be sent to the server, but the client/JS will not be able to parse the response without proper acknowledgement from the server. Some CORS requests are not simple, so to speak. These are, for example, DELETE or PATCH requests, or POST/GET requests that contain non-standard headers (such as X-headers or a Content-Type of "application/json" as opposed to "multipart/form-data"). In other words, a request is not simple if it cannot be sent without JavaScript. For example, a <form> submit, or a GET request from a <script src="..."> will always send "simple" requests. For non-simple requests, the browser must "preflight" the request. This means that the browser sends an intermediate request, called a preflight, before the original request. This preflight request is an OPTIONS request. The server must than return headers in the response to this preflight that acknowledge any non-standard properties of the original request. If it does, then the browser will send the original request.
You can read more about preflighting and CORS in general on MDN.

CORS with XMLHttpRequest

I'm trying to make a POST request between two sites.
I've seen the need to change header of request on server side using the access-allow. My problem is that when I send request I can't see this modification in the response header.
If I go on directly on page the headers are change. If I sent request with GET, I can see too that the headers has been changed. Maybe there is server configuration of http which is forbidden across domain POST request?
I'm using a Ngnix server that serves Drupal sites.
As far as I know, the header you should change is the response header of the site that receive the request (or site 2). Thus, it allows the client (or site 1) to perform a CORS request, adding the header "Access-Control-Allow-Origin" and the domain of site 1 (or '*') into the response.

Resources