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

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.

Related

Can a POST request be redirected as another GET request

I am working on a react application, where there is a need to send the object parameters inside a body because of confidentiality. So I am making a POST request from the react app client-side to the backend server like this
axios
.post('htps://java.backend.xyz/path1', {
data: password,
})
.catch(function (error) {
handle(error);
});
After making this POST request there is a preflight request with "method = OPTIONS" and "URL= 'htps://java.backend.xyz/path1'"...to which java-backend-server responds with status_code=200.
After the above preflight request, java-backend-server addresses the POST request and instead of sending a response the java-backend-server respond with a GET request (i.e redirect) as for example:
https://express-app.xyz/path2?query_para1=abc&query_param2=123, requestMethod=GET
And in response to the above GET request, the express app responds with status_code=200
But immediately after this GET request, there is a preflight request with request Method=OPTIONS and having the same URL as above i.e
https://express-app.xyz/path2?query_para1=abc&query_param2=123, requestMethod=OPTIONS
and for this above OPTIONS request express server responds with a status_code=204 which means that the client doesn't need to navigate away from its current page...this is something prohibiting my app to make a final redirect i.e after the backend server responds with a GET request, my react app is not able to make a redirect even search engine does not update the redirect URL which is
https://express-app.xyz/path2?query_para1=abc&query_param2=123
So, here Is this even possible? I am assuming that the preflight request after the GET request prohibits the client side to be able to make a final redirect. Can someone please help me with this scenario
I am not sure if I understand your problem correctly but what you can do is send a post response which will which will indicate client to redirect to specific location.
This can be achieved by sending response with status code 302 and location in header (location:redirect_url)
For more info :- https://en.m.wikipedia.org/wiki/HTTP_302

Session cookie not sending with XHR requests

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.

Prevent preflight request from internal redirect

I am working on a web application, both the backend and the frontend are hosted on different endpoints on an internal PaaS, which redirects to a SSO page if any request coming to it doesn't have the authenticated cookie.
When I send a GET request from the frontend to the backend, it also passes through the cookies (with credentials in axios). But when I make a POST request, the browser first makes a preflight OPTIONS request without cookie and internally the backend service redirects to the SSO, as a result it never gets to sending the POST request at all.
The preflight request by design exclude user credentials, how can I get around it?
Write a middleware in your backend, top in the heirarchy and check the request type in it.
if it is "OPTIONS", just verify the origin, if it is familiar respond right away with 200 instead of passing control to next, if not then respond with 403
if it is not "OPTIONS", just pass the control to next so that it deals accordingly
assuming a node-express server, the middleware would look like this
app.use((req,res,next)=>{
if(req.method==='OPTIONS' && whiteListUrls.includes(req.origin)){
res.status(200);
}else{
next();
}
})

Will Spring Security CSRF Token Repository Cookies Work for all Ajax Requests Automatically?

I'm going through the following security tutorial and it configures a CsrfTokenRepository like this:
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
Is that all that is required to get Ajax requests working across all libraries? The Angular documentation for $http says that Angular reads the CSRF cookie that Spring provides and sets a corresponding a header when it makes requests. So I'm assuming it does this because the cookie will not automatically be included when sending Ajax requests?
[Update]
I read the article again and it says that the CSRF protection is provided by the header. So if I interpret that the right way it's the fact that the client is sending back the cookie value in a unique way that is different than it was sent in the first place that provides the CSRF protection. In other words the client receives the cookie and changes the way it is sent back, so that the server knows that the client is indeed in control of the cookie?
CSRF protection with Spring CookieCsrfTokenRepository works as follows:
Client makes a GET request to Server (Spring backend), e.g. request for the main page
Spring sends the response for GET request along with Set-cookie header which contains securely generated XSRF Token
Browser sets the cookie with XSRF Token
While sending state changing request (e.g. POST) the client (Angular) copies the cookie value to the HTTP request header
The request is sent with both header and cookie (browser attaches the cookie automaticaly)
Spring compares the header and the cookie values, if they are the same the request is accepted, otherwise 403 is returned to the client
Note that only state changing requests (POST, PUT, DELETE) are CSRF protected by default and only these need to be protected when API is properly designed (i.e. GET requests don't have side effects and modify the state of the app for example).
The method withHttpOnlyFalse allows angular to read XSRF cookie. Make sure that Angular makes XHR request with withCreddentials flag set to true.

Set token in Header on API response

I am creating a login page in Angular. After login API call (POST), I get a token in response. In controller, I am trying to set this token in "common" header so that I can use it for authorization for all further API calls:
LoginSrv.authenticate($scope.credentials).then(
function(data){
$http.defaults.headers.common.Authorization = data.token;
$state.go('nextpage');
}
);
The next page there is again a POST API call. After this call when I check the request header in debugger I see that token in header. This response again navigate to third page (this time I am not setting header again). On third page when I call an API (GET or POST) the "Authorization" is not available in headers this time. I am not sure how this is removing by itself.
Given that your third request is cross domain, it appears your server is not correctly responding to the preflight browser OPTIONS request which is made to check what methods etc are available before it sends your request. It's not an Angular issue. One solution would be to configure your server to respond correctly to this OPTIONS request. This SO link (provided in the comments previously) explains in a bit more detail and discussions of potential solutions AngularJS performs an OPTIONS HTTP request for a cross-origin resource

Resources