Firefox Django CSRF token error - django

I recently made some changes to a form to do some more advanced error checking than celery provides (errors based on input from multiple fields). Everything was working fine until a coworker found that the form didn't work on Firefox anymore (dev and testing done on Chrome).
The specific error being thrown is:
django.request [WARNING] > Forbidden (CSRF token missing or incorrect.): /[url]
I suspect the root of this issue comes from the change:
<form action="{% url '[submit url]' %}"> to
<form onsubmit="sendData()"> where sendData constructs an XMLHttpRequest and sends it. I've tried adding csrftoken header to the request from {{csrf_token}} but it fails for the same reason - and even breaks the process on Chrome!

The csrf_token should be in your XMLHttpRequest not in the form since you are using JS to send data:
var xhttp = new XMLHttpRequest();
xhttp.open("POST", url, true);
xhttp.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
xhttp.send();

Related

django CSRF token cookie not set for some users

I have been getting sporadic CSRF errors in an app that is mostly working ok. I do everything as I'm supposed to do: I use {% csrf_token %} in my template for normal forms and in my ajax POSTs I set the X-CSRFToken header:
$.ajaxSetup({
beforeSend: function(xhr, settings) {
xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
},
});
I'm even forcing the cookie to be set in all views by writing a custom Middleware that calls get_token
def CSRFForceCookieMiddleware(get_response):
def middleware(request):
response = get_response(request)
get_token(request) # Force to set cookie in all responses
return response
return middleware
Everything works OK in my localhost and in production for most users. But for some users I get 403 CSRF validation error.
I added a lot of debug info. Turns out that even if CsrfViewMiddleware is setting the csrftoken is setting the cookie in the response, in the actual browser the cookie is not set ($.cookie('csrftoken') is null). So when the ajax call is made, there is no cookie present in the request.
So, I guess this pretty much means that some users' browsers are blocking this cookie? Anyone else had this experience?
Most browsers have an option to "block all cookies". You may want to detect that in javascript and give your users a warning that some functional cookies are required for the site to work correctly. There's another SO question that shows how to do that.
Alternatively, grab the token from a hidden input field ({% csrf_token %} will add that field in your template). That should always work.

CRSF cookie not set in iframed Django View within another site

I have a Django app with about a dozen views that I am currently hosting on Heroku. I can do POST requests just fine to the app when directly going to the app url, and I have the 'django.middleware.csrf.CsrfViewMiddleware' enabled. I am running Django 2.1
I am currently having an issue where I am trying to embed this Django app within an iframe, on another site that I host on Weebly. I always get a 403 error when trying to do a post on any of the Django forms. The reason is "CSRF cookie not set."
I am doing this through Chrome on Ubuntu. I checked the Applications tab in the Developer console, and do see the csrftoken key-value pair set in the cookie for the Heroku domain. The Weebly domain does not contain the csrftoken key-value pair. I figured it would just use the cookie from the Heroku app domain and use the csrftoken, but that doesn't appear to be the case.
In Django, here are my settings regarding CSRF:
CSRF_COOKIE_SECURE = False
CSRF_TRUSTED_ORIGINS = ['example123.herokuapp.com',
'app123.weebly.com']
I REALLY don't want to disable security or use the csrf_exempt decorator, as that feels like a hack. I am pulling my hair out on this one!
EDIT:
{% csrf_token %} is in the form, and I can see the hidden field "csrfmiddlewaretoken":
<input type="hidden" name="csrfmiddlewaretoken" value="XXXXXXXXXXXXXXXXXXXXXXywkFTfTC9ttYiOTD0O8uF49SvRjaUWgWeLU0h2PjP2">
There are two different things with csrf in django
1. Csrfmiddlewaretoken : {% csrf_token %}
example of set-token header
2. CSRFcookie : I don't think that you did this one.
example of same request giving different csrf-token
here the images shown are both the examples of one of my app for a specific request
We do often confuse second with the first one. In the second case, the server sets a cookie in the first get request with a csrf token (this is a cookie and not the csrfmiddlewaretoken ), it needs to be sent every-time for csrf cookie verification. This is done by the browser itself and we mostly don't notice it. However the problem arises with using CORS (different origins of request like android/angular app etc).

Django CSRF error with AJAX on iOS 8

I am trying to make an AJAX call to a Django function, but have started getting a CSRF Verification failed error in iOS 8. It works with the latest iOS and used to work with iOS 8.
This may be related to the recent updates to TLS. My host recently deprecated TLS 1.0 and TLS_RSA_WITH_3DES_EDE_CBC_SHA.
I add the CSRF token as a post parameter. If I make the function (server-side) #csrf_exempt then the call works, but I obviously don't want to take away the security.
I have only tested this in Safari. I'm using Django 1.5.2.
HTML:
# this creates an input with the CSRF token as its value
<div id = "csrf_token" class = "hidden">{% csrf_token %}</div>
Javascript:
csrfmiddlewaretoken = $('#csrf_token input').val();
$.ajax({
type: "POST",
url: "<my_url>",
data: {"csrfmiddlewaretoken":csrfmiddlewaretoken},
success: function(data){
alert("ok");
}
,error: function(xhr, status, error) {
alert("error " + xhr.responseText);
}
});
Is there any solution to this or must I stop supporting iOS 8? I still have some users who use it.
The problem turned out to be that referer wasn't being passed in iOS 8, which causes a CSRF fail. Referer wasn't being passed because the page was using the referrer meta tag.
<meta name="referrer" content="always">
<meta name="referrer" content="unsafe-url">
This doesn't work in iOS 8.

django posts receive CSRF verification failed after switching to load balancer

I have a working login template that does a post and looks like:
<form action="" method="post">
{% csrf_token %}
<br>
{{form.email}}
<div class="text-center">
<button type="submit">Login</i></button>
</div>
</form>
My SSL settings look like:
ssl
SECURE_SSL_REDIRECT = False
SECURE_HSTS_SECONDS = 3600
SESSION_COOKIE_SECURE = False
SECURE_PROXY_SSL_HEADER = None
CSRF_COOKIE_SECURE = False
I made two changes. I switched to an aws ec2 elastic load balancer and from https to http.
Now I am getting an error:
Forbidden (403) CSRF verification failed. Request aborted.
You are seeing this message because this site requires a CSRF cookie
when submitting forms. This cookie is required for security reasons,
to ensure that your browser is not being hijacked by third parties.
If you have configured your browser to disable cookies, please
re-enable them, at least for this site, or for 'same-origin' requests.
Does anyone know why this is occurring?
I must have a stale cookie. When I go to Chrome incognito mode, all works as would expect with a 200 response.
Forbidden (403)
CSRF verification failed. Request aborted.
You are seeing this message because this site requires a CSRF cookie when submitting forms. This cookie is required for security reasons, to ensure that your browser is not being hijacked by third parties.
If you have configured your browser to disable cookies, please re-enable them, at least for this site, or for 'same-origin' requests.
More information is available with DEBUG=True.

Unable to jQuery $.post data to a view in django due to CSRF

Before posting this i've tried every solution method posted online, including solutions on Stackoverflow and Django. (I think the reason for error perhaps is due to the fact that i'm on a newer verison of jQuery and django and most solutions are dated, using jQuery 1.9 and django 1.5.1)
Here are some URL's to solutions that don't work:
Django CSRF check failing with an Ajax POST request
How to use $.post with django?
https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax
Any help would be appreciated. Another possibility for error is the fact that i'm not actually sure where to place these snippets exactly. So far i've pasted everything inside the jquery on document load, i've also tried pasting the code in the very start of the .js file. (My javascript code is fragmented in chunks, some are seperate .js files and some are inline with the html being rendered with django context, so any solutions with "{{ csrftoken }}" are bad.
Thanks!!
The CSRF token only gets set if it's present in the template or if the view is decorated with ensure_csrf_cookie(). Putting {% csrf_token %} in index.html will make it apply for all your pages.
From the docs:
The CSRF token is also present in the DOM, but only if explicitly included using csrf_token in a template.
...
If your view is not rendering a template containing the csrf_token template tag, Django might not set the CSRF token cookie. This is common in cases where forms are dynamically added to the page. To address this case, Django provides a view decorator which forces setting of the cookie: ensure_csrf_cookie().
Can you try this:
$.ajax({
type: "POST",
url: '{% url "some_url_which_accepts_post" %}',
data: {'csrfmiddlewaretoken': '{{csrf_token}}', 'comment_id':1},
success: function(data, textStatus){
//something
},
});