Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass Django CSRF token to Angular with CSRF_COOKIE_HTTPONLY

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.

like image 453
Zags Avatar asked Nov 28 '16 18:11

Zags


People also ask

Where should I put CSRF token Django?

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.

What is the correct way to insert CSRF token for forms in Django template?

Add the csrftoken input: var form = document. getElementById('name-form'), input = document. createElement('input'); input.name = "csrfmiddlewaretoken"; input.

What does {% Csrf_token %} do?

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.

What is Csrf_exempt in Django?

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')


1 Answers

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.

like image 87
PhilippeT Avatar answered Sep 21 '22 05:09

PhilippeT