CSRF Verification fails in production for Cross Domain POST request - django

The HTTP_X_CSRFTOKEN header does not match what is inside the csrftoken cookie.
How can I examine the cookie? Set-Cookie is not displayed in the Response header for Cross Domain requests.
I have already followed instructions found in:
CSRF with Django, React+Redux using Axios
Interestingly I found "X-CSRFTOKEN" translates to "HTTP_X_CSRFTOKEN" on the server request header.
Works fine in the development env under localhost (although I am using 2 different ports - one for django and the other my frontend).
UPDATE:
It seems the csrktoken cookie is not correctly set for cross domain rquests (although the browser displays it in the Request Header) so the X-CSRFTOKEN does not get sent.
I ended up adding an API call to return the current csrftoken using a GET request and then sending it back using the X-CSRFTOKEN header.

You haven't mentioned how you're getting the csrftoken from the server in the first place, so I'm assuming it's already present in your browser.
Along with the X-CSRFToken header, also include the cookies in the request using withCredentials: true.
I'm using the js-cookie library to get the csrftoken from the cookies.
import Cookies from 'js-cookie';
axios({
url: 'http://localhost:8000/graphql',
method: 'post',
withCredentials: true,
data: {
query: `
{
// Your query here
}
`
},
headers: {
"X-CSRFToken": Cookies.get('csrftoken')
}
})
Also add CORS_ALLOW_CREDENTIALS = True to your settings.py, assuming you are using django-cors-headers. Otherwise, the cookies won't be accepted.

You will have to make the X-CSRFTOKEN header accessible via the CORS Access-Control-Expose-Headers directive. Example:
Access-Control-Expose-Headers: X-CSRFTOKEN
This header has to be set by your API or web server, so that the browser will see it during the CORS preflight request.

Related

Axios send X-XSRF-TOKEN taken from wrong cookie

I have app on domain.com and sub.domain.com. Both apps set cookie with name X-XSRF-TOKEN but with different domain value.
I use this settings for Axios, so Axios take token from cookies and set it to headers:
axios.defaults.xsrfCookieName = "XSRF-TOKEN"
axios.defaults.xsrfHeaderName = "X-XSRF-TOKEN"
My app on subdomain send X-XSRF-TOKEN header from cookie taken from main domain (because it returned first when axios looking for XSRF-TOKEN cookie). How to deal with this ?
How to tell Axios take cookie from current domain ?

Cookie not added into request header

Like to ask a CORS cookie question again, I have spent quite some time on this but cannot resolve it.
Here is the situation.
I got a Backend api in nodejs(http://localhost:5000), and a React Frontend app(http://localhost:3000).
In Backend side, Cors setting is like this.
private initializeCors(){
this.app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "http://localhost:3000");
res.header("Access-Control-Allow-Headers", "Content-Type, Accept");
res.header("Access-Control-Allow-Credentials", "true");
next();
});
}
I have set { credentials: "include" } in Fetch Api when login with username/password.
Set-Cookie has been set in response and I can see it saved in browser.
Cookie is with the format "Authorize=TOKEN;HttpOnly;Max-Age=3600;"
Cookie in browser
Then when route to another url and it cannot retrieve data from Backend with 401 exception.
Here is the code of the sequence call.
const credentialsInclude : "include" | "omit" | "same-origin" | undefined = "include";
function getAllPayments() {
const requestOptions = {
method: 'GET',
credentials: credentialsInclude
};
return fetch(apiUrls.GET_ALL_PAYMENTS, requestOptions).then(handleResponse);
}
I can see the cookie not added into header.
No cookie in header
I have followed the best answer of here, but cannot get it work.
Any suggestions? Thanks.
I have just figured out. The issue was not caused by the CORS settings. It caused by the Cookie itself.
For my case, I need to add Path=/; into Set-Cookie in response headers. So that the cookie from response could be added to sequenced requests after successful login.

Ionic app post fails with "Referer checking failed - no Referer."

From the Django docs:
Django’s CSRF protection requires that the request have a Referer header that matches the origin present in the Host header.
Using Ionic 3.9.2 (Angular 5.2.10), how does one satisfy this requirement when posting forms since one can't add the referer header? Disabling csrf protection is not an option. The same URL works via browser (even Ionic's in-app browser but the experience is just not desirable). I'm posting JSON data.
My code:
let headers = new Headers({'Content-Type': 'application/x-www-form-urlencoded', 'HTTP_X_CSRFTOKEN': csrftoken});
return this.http.post(
hostUrl + "/auth/reset_password?org=" + org, body, {headers: headers}
).toPromise();

How to configure loopback to use access_token in the header

I'm using access_token handling logic form loopback. It works fine, but unfortunately expects the access_token in the URL.
Can I configure loopback to use the access_token in the header custom field instead?
Initialize Loopback Token Middleware
check the docs
A sample code for enabling loopback.token middleware
app.use(loopback.token({
cookies: ['access_token'],
headers: ['access_token', 'X-Access-Token'],
params: ['access_token']
//additional keys (check docs for more info)
}));
It checks for these values in cookies, headers, and query string parameters
Docs- https://loopback.io/doc/en/lb3/Making-authenticated-requests.html
Pass the following header in request config (use your token)-
headers: {
Authorization: '1vKbyJc9D2pJaE5sZWDqKxcJYlOfPab4eO8giuRMkfOxvoHKGUBRDcNvP4JwDIxe'
}
No configuration needed in server.

Dart BrowserClient POST not including my cookies

I'm doing a BrowserClient POST across domains and don't see my cookies being included.
This the response I'm getting:
When I send another POST request, I don't see the cookies being included:
Going straight to the test page, I can see the cookies being included:
The Dart code I use to make a POST:
var client = new BrowserClient();
client.post(url, body: request, headers:{"Content-Type" : "application/json", "Access-Control-Allow-Credentials":"true"}).then((res) {
if (res.statusCode == 200) {
var response = JSON.decode(res.body);
callback(response);
} else {
print(res.body);
print(res.reasonPhrase);
}
}).whenComplete(() {
client.close();
});
Not sure about the Access-Control-Allow-Credentials header I'm including, with or without it, nothing changes.
Am I missing headers on the server side that needs to be set on the response or is Dartium blocking cross-domain cookies?
More details on Information Security and the reasoning behind setting cookies via the server.
Update: Enhancement request logged: https://code.google.com/p/dart/issues/detail?id=23088
Update: Enhancement implemented, one should now be able to do var client = new BrowserClient()..withCredentials=true; based on
https://github.com/dart-lang/http/commit/9d76e5e3c08e526b12d545517860c092e089a313
For cookies being sent to CORS requests, you need to set withCredentials = true. The browser client in the http package doesn't support this argument. You can use the HttpRequest from dart:html instead.
See How to use dart-protobuf for an example.