In Django, when the CSRF_COOKIE_HTTPONLY
setting is set to True, the CSRF cookie gains the httponly flag, which is desirable from a security perspective, but breaks the standard angular solution of adding this cookie to the httpProvider like so:
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
Through Django 1.9, there was a workaround where you could just pass the cookie directly to the app by putting this in the template:
<script>
window.csrf_token = "{{ csrf_token }}";
</script>
And putting this in the angular app:
angularApp.config(["$httpProvider", function($httpProvider) {
$httpProvider.defaults.headers.common["X-CSRFToken"] = window.csrf_token;
}]
Unfortunately, this doesn't work for single page angular apps in Django 1.10+ since the CSRF cookie changes after every request. How do you make post requests from Angular to Django 1.10+ with the CSRF_COOKIE_HTTPONLY
setting on?
NB: Disabling CSRF protection is not an acceptable answer.
The CSRF token is like an alphanumeric code or random secret value that's peculiar to that particular site. Hence, no other site has the same code. In Django, the token is set by CsrfViewMiddleware in the settings.py file. A hidden form field with a csrfmiddlewaretoken field is present in all outgoing requests.
Add the csrftoken input: var form = document. getElementById('name-form'), input = document. createElement('input'); input.name = "csrfmiddlewaretoken"; input.
csrf_token. Django has a {% csrf_token %} tag that is implemented to avoid malicious attacks. It generates a token on the server-side when rendering the page and makes sure to cross-check this token for any requests coming back in. If the incoming requests do not contain the token, they are not executed.
csrf_exempt (view) This decorator marks a view as being exempt from the protection ensured by the middleware. Example: from django.http import HttpResponse from django.views.decorators.csrf import csrf_exempt @csrf_exempt def my_view(request): return HttpResponse('Hello world')
I think this question was answered well in this discussion.
https://groups.google.com/forum/#!topic/django-developers/nXjfLd8ba5k
https://code.djangoproject.com/ticket/27534
CSRF_COOKIE_HTTPONLY does not provide any additional security for single page apps. Some people reccomended this solution
var csrftoken = getCookie('csrftoken');
if (csrftoken === null) {
csrftoken = $('input[name="csrfmiddlewaretoken"]').val();
if (csrftoken === null) {
console.log('No csrf token');
}
}
however either or if you are exposing csrftoken for your app restfully nothing stops the malcious user from taking it and using it as well. If you are running a single page app you might as well set CSRF_COOKIE_HTTPONLY=False, As per comment bellow:
Gavin Wahl 5/4/15
How so? You cannot just ajax-fetch stuff from different domains.
I'm talking about a single domain. Injected javascript on a page that doesn't contain the CSRF token can fetch a different page on the same domain to get it.
If you already injected javascript onto the victims page (XSS) there is no need to fetch the CSRF token, you already got greater control.
Well, the HttpOnly flag is intended to reduce the damage an attacker can do once the already can inject javascript. But I agree -- hiding the CSRF token from javascript doesn't increase security in any way, but the documentation implies it does. I want to make it clear in the documentation that this setting has no meaningful effect.
If you still think you have a valid attack vector there, please send it to [email protected] and add a bit more explanation.
There is no attack vector. This is just about misleading documentation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With