1

I am now making about user registration like this. I already allow any permission to make this request. But, when I post from postman, I got

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

How shall I do?

class RegistrationView(APIView):
    """ Allow registration of new users. """
    permission_classes = (permissions.AllowAny,)

    def post(self, request):
        serializer = RegistrationSerializer(data=request.DATA)

        # Check format and unique constraint
        if not serializer.is_valid():
            return Response(serializer.errors,\
                        status=status.HTTP_400_BAD_REQUEST)
        data = serializer.data

    # u = User.objects.create_user(username=data['username'],
    #                              email=data['email'],
    #                              password='password')

    u = User.objects.create(username=data['username'])
    u.set_password(data['password'])
    u.save()

    # Create OAuth2 client
    name = u.username
    client = Client(user=u, name=name, url='' + name,\
            client_id=name, client_secret='', client_type=1)
    client.save()
    return Response(serializer.data, status=status.HTTP_201_CREATED)
ilse2005
  • 11,189
  • 5
  • 51
  • 75
Khant Thu Linn
  • 5,905
  • 7
  • 52
  • 120
  • Possible duplicate of [Django Rest Framework remove csrf](http://stackoverflow.com/questions/30871033/django-rest-framework-remove-csrf) – Ali Mar 12 '16 at 12:40
  • @Ali Thanks. I still need csrf though. But I wanna disable for registration. – Khant Thu Linn Mar 12 '16 at 12:45

3 Answers3

1

CSRF have nothing to do with permission classes. APIView are by default csrf-exempt. A very good discussion on APIView and csrf here

Because APIViews can both be used from a browser (which needs CSRF protection) or a server (which does not need CSRF protection) by default the CSRF protection is turned off. However, also by default an APIView has an authentication class called SessionAuthentication. This class will dynamically re-apply django's CSRF middleware if the current request object contains an active user.

So most probably you are getting that error because of you already logged in.

Satyajeet
  • 2,004
  • 15
  • 22
  • I have tried from postman. I haven't login though. How shall I do? – Khant Thu Linn Mar 12 '16 at 15:32
  • @KhantThuLinn Then you are sending it wrong... Or if you want to completely disable ```csrf``` then disable authentication classes...```authentication_classes = () ``` in – Satyajeet Mar 12 '16 at 17:44
0

You may find more details here: https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/

Form:

<form action="." method="post">{% csrf_token %}

AJAX:

Get CSRF from cookie:

// using jQuery
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]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) == (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
var csrftoken = getCookie('csrftoken');

JQuery AJAX:

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function sameOrigin(url) {
    // test that a given url is a same-origin URL
    // url could be relative or scheme relative or absolute
    var host = document.location.host; // host + port
    var protocol = document.location.protocol;
    var sr_origin = '//' + host;
    var origin = protocol + sr_origin;
    // Allow absolute or scheme relative URLs to same origin
    return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
        (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
        // or any other URL that isn't scheme relative or absolute i.e relative.
        !(/^(\/\/|http:|https:).*/.test(url));
}
$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
            // Send the token to same-origin, relative URLs only.
            // Send the token only if the method warrants CSRF protection
            // Using the CSRFToken value acquired earlier
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});
nlgn
  • 378
  • 3
  • 13
-1

As you are using Session Authentication, it usually requires CSRF to be checked. So you must pass the CSRF token in the X-CSRFToken header.

Since you are in fact have not logged in, you have to use csrf_exempt decorator.

from django.views.decorators.csrf import csrf_exempt

class RegistrationView(APIView):
    permission_classes = (permissions.AllowAny,)

    @csrf_exempt
    def post(self, request):
        # Do what needs to be done
        pass
Karthik RP
  • 1,028
  • 16
  • 26