Django CSRF failure, using React forms - django

I'm having a problem with CSRF with Django and React.
I have read through the already high number of questions around this, as well as the django docs naturally. I have tried every possible combination of different things that should address the issue but am still struggling with it.
Firstly I tried to create a register page, but when I POST to register/ I get CSRF cookie not set, 403.
I have gone so far as disabling the CSRF middleware [bad I know, just trying to get somewhere] and I am getting 405s, method not allowed [attempting to post]. I just thought maybe this is something someone has run into before or sounds familiar and could give some guidance?
I have tried:
- adding the decorator #csrf_exempt,
- adding the CSRF to the header of a request,
- attaching the whole cookie,
- attaching a hidden form field with the token.
I am using this seed project: https://github.com/Seedstars/django-react-redux-base if anyone wants to have a look, I've done a bit in React, but not a lot on the Django side, so it isn't far off what's there

You should not disable the csrf check in django.
Instead in your form/template simply do
{% csrf_token %} not {{ csrf_token }}
It will print a hidden form element with value assigned to your csrf token already.
If you are using ajax, you can simply set your ajax headers globally as:
$.ajaxSetup({
beforeSend: function (xhr, settings) {
// this time double brackets
xhr.setRequestHeader("X-CSRFToken", "{{csrf_token}}");
}
});
if you are using fetch then:
fetch('some/url/here', {
method: 'GET',
headers: {
'X-CSRFToken': window.CSRF_TOKEN // or pass it in your own way
}
}).then(function (response) {
return response.json()
})
These are pretty much all the ones i can think of.
Hope this helps.

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.

How to render Flask-Security forgot password form?

I have application with ready UI and I want to add login/logout/register/restore features with Flask-Security. Before I worked with that default behavior - when user clicked "forgot password" he was redirected to specific endpoint.
Now I want to have forgot password form on the same page (just in different panel which show when user clicks corresponding link).
I faced an issue that I cannot just add the same form with same endpoint because Flask-Security wants CSRF token. I think that I can somehow render its form on page and adjust styles. But I do not know how.
I do not want to turn off csrf check unless I definitely know that there is not other ways.
Since you are generating the form dynamically I will assume that you are using AJAX, the documentation speaks about it.
You have to enable the CSRF module with
from flask_wtf.csrf import CsrfProtect
CsrfProtect(app)
you will have access to csrf_token() on every page, and you can get it with:
<meta name="csrf-token" content="{{ csrf_token() }}">
var csrftoken = $('meta[name=csrf-token]').attr('content')
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken)
}
}
})

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
},
});

Django and JEditable: CSRF error

I started using the Jeditable plugin with Django and quickly ran into a CSRF error: "CSRF verification failed. Request aborted.", "CSRF token missing or incorrect"
As of this writing the Jeditable plugin seems have been last updated in 2008--sometime after this Django began requiring CSRF tokens for POST requests.
How do you add Django CSRF data to Jeditable?
The answer to this question came from a similar jeditable post on CSRF. The CSRF token may be added in the "submitdata" variable.
Expanding the 1st jeditable example for a Django post look something like this:
$(document).ready(function() {
$('.edit').editable('http://www.example.com/save.php', {
submitdata : { csrfmiddlewaretoken : "{{ csrf_token }}"}
});
});
Note, in order to show the "csrf_token" value instead of an entire form field, the "csrf_token" is wrapped in {{..}} instead of {% .. %}.
The preferred method for providing the CSRF token through AJAX requests is by setting the X-CSRFToken header to the value of the CSRF token. You'll need to modify the constructed request object to set the header value.
There's also a helper function provided to get the CSRF token from the cookie, rather than relying on providing it in the template, which considerably simpifies things, i.e. you don't have to ship the JS code inline or set the token as a variable in JS in the template itself.

Csrf token verification fails between two Django web applications

I am trying to pass csrf token between two web application to make one POST data to the other.
"client" application (C) asks csrf token to "server" application (S) via a GET operation.
S responds to C with a form:
<form id='csrfRequestForm' name='csrfForm' action='http://{{ context_path }}/ajax/getcsrf' method='post'>
<!-- csrf token -->
{% csrf_token %}
<!-- datas to POST follow -->
...
</form>
C has to submit this form to action (mapped on a url used by S) in order to POST datas to S.
When C tries to do it, csrf verification fails. I've checked GET's result and csrf token is received with the form. I have django.middleware.csrf.CsrfViewMiddleware keyword listed under MIDDLEWARE CLASSES in settings.py and RequestContext is passed when rendering form's view with render_to_response(... RequestContext(request))
What am I doing wrong?
Thanks
Try defining your context and returning it like this...
context = RequestContext(request, {
'request': request
})
return render_to_response(..., context_instance=context)
This is by design, and disallows for cross site POST execution. One option you have is to mark the methods you would like to be able to execute as safe, as per the django docs:
https://docs.djangoproject.com/en/dev/ref/contrib/csrf/
I wasn't able to resolve it in your way, but I managed out how to do it:
C go directly to S via javascript opening a popup with:
window.open("http://<S_address>/<path_to_request_form>");
In this way, user using C that is logged via a third party authentication server (I forgot to mention it earlier, sorry), is still logged in the popup window in S and receives the form in it with a correct csrf token. I don't know if it's correct but it works.
Thanks for your time