Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Rest Framework, CSRF and Vue.js

I'm trying to use Vue.js to do some POST methods to my REST Api that I created with Django Rest Framework. Problem is, I'm getting the CSRF Failed: CSRF token missing or incorrect. error when I post. But I can see the csrf cookie, and it's being added to the headers.

Here's my settings:

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
        'rest_framework.permissions.DjangoModelPermissions'
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication'
    )
}

Here's my Vue.js config:

var csrftoken = Cookies.get('csrftoken');
Vue.http.headers.common['HTTP_X_CSRFTOKEN'] = csrftoken;

And here's the relevant part of the headers that were sent:

Cookie:djdt=hide; tabstyle=raw-tab; sessionid=1gl533mrneudxw3l9l2vg0ja1yowwmeo; csrftoken=dN85bhztB1oVRov87BsUrWTM29Ff9sjn
Host:127.0.0.1:8000
HTTP_X_CSRFTOKEN:dN85bhztB1oVRov87BsUrWTM29Ff9sjn
Origin:http://127.0.0.1:8000
Referer:http://127.0.0.1:8000/agencies/6/add-profiles/

As you can see, Cookie.csrf and the HTTP_X_CSRFTOKEN header match

I'm really stumped. Any suggestions?

like image 646
Dave Merwin Avatar asked Mar 09 '16 01:03

Dave Merwin


People also ask

Can I use Vue JS with Django?

Django is a Python-based backend framework used to create native applications or APIs using the Django rest framework package. We can also combine it with Vue. js, a JavaScript-based front-end framework, in building applications.

Does REST framework need CSRF token?

If you're using SessionAuthentication you'll need to include valid CSRF tokens for any POST , PUT , PATCH or DELETE operations. In order to make AJAX requests, you need to include CSRF token in the HTTP header, as described in the Django documentation.

How does Django prevent CSRF?

Django features a percent csrf token percent tag that is used to prevent malicious attacks. When generating the page on the server, it generates a token and ensures that any requests coming back in are cross-checked against this token. The token is not included in the incoming requests; thus they are not executed.

How does Django handle CSRF?

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.


2 Answers

So I'm posting this as an answer to close the question.

The issue was because of the wrong CSRF header name that was sent on request. According to documentation:

As with other HTTP headers in request.META, the header name received from the server is normalized by converting all characters to uppercase, replacing any hyphens with underscores, and adding an 'HTTP_' prefix to the name. For example, if your client sends a 'X-XSRF-TOKEN' header, the setting should be 'HTTP_X_XSRF_TOKEN'.

Also I'm leaving here a reference to my question, which accumulates several problems that may lead to CSRF Failed: CSRF token missing or incorrect. error in Django.

like image 115
Damaged Organic Avatar answered Oct 12 '22 14:10

Damaged Organic


Get token from cookie:

function readCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    }
    return null;
}

var csrftoken = readCookie('csrftoken');

Send token in headers POST:

  this.$http.post('http://'+document.location.host+'/api//',{params: {foo: 'bar'}}, {headers: {"X-CSRFToken":csrftoken }}).then(function (response) {
            this.response = response.data;
        },
        function (response) {
            console.log(response);
        });
like image 34
Ruslan Avatar answered Oct 12 '22 14:10

Ruslan