CSRF Failed: CSRF token missing or incorrect
Asked Answered
F

20

109

I'm using Django 1.7 and django-rest-framework.

I made an API that returns me some JSON data putting this in my settings.py

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.AllowAny',),
    'DEFAULT_RENDERER_CLASSES': (
    #   'rest_framework.renderers.XMLRenderer',
    'rest_framework.renderers.JSONRenderer',
    #   'rest_framework.renderers.BrowsableAPIRenderer',
    )
}

When I make GET calls, it returns me all the data, but when I try with PUT/PATCH I get:

--------Response Headers---------
Status Code: 403
Date: Wed, 29 Oct 2014 18:51:42 GMT
Vary: Cookie
Server: WSGIServer/0.1 Python/2.7.8
Allow: GET, POST, PUT, PATCH, HEAD, OPTIONS
X-Frame-Options: SAMEORIGIN
Content-Type: application/json
---------------------------------

--------Response Body-----------
{"detail": "CSRF Failed: CSRF token missing or incorrect."}
---------------------------------

This only happens when I am logged in, if I am anonymous I can PUT/PATCH correctly.

I have tried with @csrf_exempt and I got errors, I have included the rest_framework.permissions.AllowAny in the setting...

I have no idea what's going on. Does anyone know what the issue is?

Finkle answered 29/10, 2014 at 19:40 Comment(0)
W
133

When you are using SessionAuthentication, you are using Django's authentication which usually requires CSRF to be checked. Django REST Framework enforces this, only for SessionAuthentication, so you must pass the CSRF token in the X-CSRFToken header.

The Django documentation provides more information on retrieving the CSRF token using jQuery and sending it in requests. The CSRF token is saved as a cookie called csrftoken that you can retrieve from a HTTP response, which varies depending on the language that is being used.

If you cannot retrieve the CSRF cookie, this is usually a sign that you should not be using SessionAuthentication. I recommend looking into TokenAuthentication or OAuth 2.0 depending on your needs.

Wouldst answered 29/10, 2014 at 20:19 Comment(7)
I know I should give the CSRF Token when I am authenticated, but, actually I am using a .NET Windows Forms Application to communicate with this API, and it makes the GET call by HTTPRequest and HTTPResponse methods, I have no idea how could I get the CSRF Token in this situation, I am not using AJAX nor HTML Forms. EDIT The .NET app receives plain text in JSON format, and it return the sameFinkle
You are all right, with the cookie I can handle the csrftoken and put it back in the header data, so i can make PUT/PATCH calls if I am logged in. THANK YOU!Finkle
@AlexLordMordor Can you explain a little bit your solution please? and why it didn't work when you were a logged-in user, but in annonymous ways it worked. (I have EXACTLY the same problem)Feigned
When you use SessionAuthentication, by default django requires two "keys" one of them could be found in the cookies when a logged-in user is active and the other is the csrf-token, if they do not match, then an error is raised, so, there is the documentation like @Kevin said to make it authenticate in the correct way.Finkle
An other way to implement this can be found in this post: blog.kevinastone.com/…, in the section "Interlude: AngularJS + CSRF Protection". In this case using AngularJSFeigned
when I moved the 'django.middleware.csrf.CsrfViewMiddleware', before the 'django.contrib.sessions.middleware.SessionMiddleware', it stopped crying for the CSRF token for my DRF_extensions requests. Django==2.1.7, djangorestframework==3.9.2, drf-extensions==0.4.0Marxmarxian
I just spent the last half hour trying to find the header key, X-CSRFToken. I tried literally everything else. Thank you!Humid
C
36

I think it is a cookie issue.

Permanent Solution: If you are using Postman, First, clear the existing cookies by clicking 'X' s. Then add correct cookie.

Temporary Solution (for debugging): Try this in your settings.py:

'DEFAULT_AUTHENTICATION_CLASSES': [
    # 'rest_framework.authentication.SessionAuthentication',
    'rest_framework.authentication.BasicAuthentication',
]
Cankerous answered 26/3, 2020 at 8:39 Comment(5)
clear cookies solved my problemCabinet
I make use of Insomnia and clearing the cache solved the problemRusselrussell
Great answer, link to the exact setting of this variable: django-rest-framework.org/api-guide/authentication/…Giacometti
Whenever testing CSRF, using anything other than a browser is not fruitful and can lead to misleading investigation. The reason is that tools like Postman, Insomnia or Curl bypass all sorts of CSRFs restrictions as this is something enforced by a browser. So one might believe things are working when in fact they are notNephritis
Changing session Authentication to basic authentication solved the problem.Lysis
S
23

This is what i did to solve it, i included csrf token to the form and using jquery/ javascrip got the csrf token like this when document loaded

var $crf_token = $('[name="csrfmiddlewaretoken"]').attr('value');

the included it on jquery headers as follow

 $.ajax({
            type: "POST",
            url: "/api/endpoint/",
            data: newEndpoint,
            headers:{"X-CSRFToken": $crf_token},
            success: function (newEnd) {
                console.log(newEnd);
                add_end(newEnd);
            },
            error: function () {
                alert("There was an error")
            }
        });
Shakeup answered 5/5, 2018 at 15:31 Comment(1)
This works. In case anyone is wondering, the value for $crf_token comes from the csrftoken cookie picked up during Basic Auth login.Douglassdougy
K
17

1- Search for the Cookie header

enter image description here

2- Separate the csrftoken from the sessionid

3- Add the X-CSRFToken={..the csrftoken that you extracted in step 2..} see below

enter image description here 4- Post again

Kenaz answered 12/10, 2018 at 15:12 Comment(0)
A
7

We had this problem and it turned out to be Postman's fault. They were automatically sending csrftoken and sessionid default values which we weren't passing in the header. Following this tutorial helped fix the issue: https://avilpage.com/2019/02/django-tips-csrf-token-postman-curl.html

Auguste answered 10/6, 2019 at 19:13 Comment(0)
O
5

The simplest solution that worked for me is:

Add CSRF token in the headers of the AJAX POST call, and this can be done by including this one line of code

headers: { "X-CSRFToken": '{{csrf_token}}' },

And this line should be added above the success

Osric answered 22/9, 2021 at 17:51 Comment(0)
G
3

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 request:

  this.$http.post(server,{params: {foo: 'bar'}}, {headers: {"X-CSRFToken":csrftoken }}).then(function (response) {
            this.response = response.data;
        },
        function (response) {
            console.log(response);
        });
Gismo answered 7/7, 2018 at 9:34 Comment(1)
This is the only valid answer that has actual code.Digiovanni
Y
3

The easiest way to solve this error, I found on here. It works for me perfectly.

Steps:

Inherit the SessionAuthentication class:

from rest_framework.authentication import SessionAuthentication, BasicAuthentication 

class CsrfExemptSessionAuthentication(SessionAuthentication):

    def enforce_csrf(self, request):
        return  # To not perform the csrf check previously happening

Then in the APIView you have created, do this:

class Object(APIView):
    authentication_classes = (CsrfExemptSessionAuthentication, BasicAuthentication)

    def post(self, request, format=None):

This will keep you logged-in and your CSRF token will no longer be checked for this APIView.

Yehudit answered 13/12, 2019 at 10:58 Comment(1)
And you've opened yourself up to CSRF attacks.Zelda
M
3

If your using the djangorestframework

the default setting is

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ]
}

comment or remove the SessionAuthentication like this

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
    ]
}
Modie answered 21/3, 2023 at 12:0 Comment(1)
after that it start to say detail: 'Authentication credentials were not provided.'Astute
W
2

I solved it creating a custom middleware in my project like this:

from django.utils.deprecation import MiddlewareMixin

class DisableCSRFMiddleware(MiddlewareMixin):
    def process_request(self, request):
        setattr(request, '_dont_enforce_csrf_checks', True)

And then I called it in my settings.py like this:

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    # "django.middleware.csrf.CsrfViewMiddleware",
    "todoproject.middlewares.DisableCSRFMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
]

It works for me!

Whitehouse answered 26/2, 2023 at 14:0 Comment(0)
P
2

I had this problem when i tried to send POST request using Postman:

I tried the same with cURL and it works:

curl -X POST http://localhost:8000/api/v1/auth/register/ | jq

To fix this using Postman you need to click on cookies and delete them:

Petronel answered 7/4, 2023 at 17:50 Comment(0)
K
2

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
    ],
}
Kike answered 19/6, 2023 at 15:17 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Assertive
T
1

I had a similar problem where I'd wrapped the views with csrf_exempt and was still encountering errors. It turned out that I was getting the URL wrong, so it was resolved to a "not found" callback (which wasn't exempt from CSRF) and was hence throwing an exception before I could be told that the URL was wrong.

Toniatonic answered 8/7, 2018 at 5:14 Comment(1)
For me it was simply that I'd forgotten to add the trailing '/' to my URL. Like @Toniatonic said, the issue was nothing to do with CSRF and instead that the URL wasn't resolving to any of my endpoints.Whereunto
B
1

When you host django website on Apache server. Djando rest framework with TokenAuthentication and SessionAuthentication will get

CSRF Failed: CSRF token missing or incorrect

To fix this open Apache configuration file - httpd.conf Add following line:

WSGIPassAuthorization On
Biforate answered 24/12, 2018 at 2:23 Comment(0)
B
1
// USING AJAX TO UPDATE DATABASE THROUGH REST API
function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

var csrftoken = getCookie('csrftoken');

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

$.ajaxSetup({
    beforeSend: function (xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});
Biforate answered 5/2, 2019 at 20:38 Comment(0)
H
1

this happened to me while testing rest-auth registration using postman this happened because postman was sending incorrect headers some old cookies and wrong content type i think it is some kind of a bug or i was ding it wrong

Solution: so i disabled the default headers

manually entered content type and the json body(POST request)

then re-enabled the required headers

Hairline answered 5/1, 2021 at 20:33 Comment(0)
J
1

In settings.py file

INSTALLED_APPS = [
...
...
...
...
'rest_framework.authtoken',
...
]

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    ),
}

in project urls.py

from rest_framework.authtoken import views

urlpatterns = [
    ....
    path('api-token-auth/',views.obtain_auth_token,name='api-token-auth')

]

Open terminal as

$ pip3 install httpie
$ python3 manage.py createsuperuser # if not created
$ http POST http://localhost:8000/api-token-auth/ username="username" password = "password"   # You will get token key (Just copy it) ex:a243re43fdeg7r4rfgedwe89320

You token key will be also automatically saved in your databases

Go to postman header (like in example) Ex: screenshot from postman ,where and how to paste accessed toke

Then insert you token key.

You can take reference to get token key from this video

Joppa answered 13/2, 2021 at 8:29 Comment(0)
K
1

I faced same issue while testing API in postman, I solved it by cleaning cache in Postman for that request.

Kironde answered 10/12, 2021 at 8:29 Comment(0)
L
0

I had similar problem, I've wrapped my URLs under csrf_exempt method as -

from django.views.decorators.csrf import csrf_exempt

url(r'^api/v1/some-resource$', csrf_exempt(SomeApiView.as_view())),
Lust answered 20/2, 2018 at 7:3 Comment(0)
F
-10

django1.8 python2.7

{
    "detail": "CSRF Failed: CSRF token missing or incorrect."
}

I fix it by using other httpmethod; oh, I face it again, this time is because I paste it, there are some invisible characters

Foresaid answered 22/1, 2020 at 8:16 Comment(1)

© 2022 - 2024 — McMap. All rights reserved.