Disabling CSRF protection

6,625 views
Skip to first unread message

David Horn

unread,
Jun 21, 2012, 12:01:10 AM6/21/12
to django-res...@googlegroups.com
Hey everyone,

I'm trying out DRF on a new api-centric project. I wrote a pretty quick-and-dirty OAuth 2.0 authentication middleware that will check for a passed access token and use that token to find a django user and log that django user in for the remainder of the request (this is all happening over https in an internal environment, so I'm not concerned).

The problem I'm running into is that CSRF protection is keeping users from making POST requests. What's the DRF-equivalent of decorating @csrf_exempt? The django approach outlined at https://docs.djangoproject.com/en/dev/topics/class-based-views/#decorating-class-based-views doesn't appear to work here.

Right now I'm digging through the DRF source to figure out a solution, but any tips to save time here would be appreciated.

Thanks,
David

Tom Christie

unread,
Jun 21, 2012, 11:06:24 AM6/21/12
to django-res...@googlegroups.com
Hi David,
REST framework views are CSRF exempt by default unless your using UserLoggedInAuthentication, which explicitly requires it. Try removing that, or making sure your OAuth authentication class is listed before UserLoggedInAuthentication.

Cheers,
Tom

David Horn

unread,
Jun 25, 2012, 8:27:46 PM6/25/12
to django-res...@googlegroups.com
I resolved this. Thanks for the tip, Tom.

I used django's built-in middleware to create an OAuth authentication backend (https://docs.djangoproject.com/en/dev/topics/auth/#writing-an-authentication-backend). That custom backend was successfully authenticating users, but DRF was running the UserLoggedInAuthentication authenticate method. I had to write a DRF-style authentication class to re-authenticate with the django authentication backend and then have all my views include that authentication method.

I suppose this is to allow for projects where we may want different authentication mechanisms for the API vs the front-end? Wouldn't it make more sense to just let django's auth backends deal with authentication? Or am I missing something?

David

Tom Christie

unread,
Jun 26, 2012, 6:20:00 AM6/26/12
to django-res...@googlegroups.com
Using per-view-class authentication rather than global middleware authentication is just more flexible, as it allows you to specify different authentication for different views.  (As you mention, this is particularly useful if your serving both the API and a regular web site.)

The UserLoggedInAuthentication gives you the default behavior of passing through a session authenticated user, while still letting you specify additional or different behavior by writing custom authentication classes.

If I understand it correctly it sounds like you'd have been able to avoid the middleware-plus-rest-framework-reauthentication dance by writing the oauth as a REST framework authentication class, rather than as a Django authentication middleware + backend?

When I finally get around to working on the next version I'll try to make sure the documentation ends up being more clear around this subject.

Cheers!

  Tom

Rex

unread,
Jul 6, 2012, 11:04:59 PM7/6/12
to django-res...@googlegroups.com
Hi Tom,
I have the same problem with Mixins, here is my code:

class ExampleView(ResponseMixin,View)
    renderers=DEFAULT_RENDERERS
    def get(self,request):
         retrun (self.render(Response(200,{'msg':'called with GET'})))
    def post(self,request):
         retrun (self.render(Response(200,{'msg':'called with POST'})))

curl -X GET http://django.example.com/example
works and returns {msg:'called with GET'}
but curl -X POST http://django.example.com/example/
or curl -X POST -H 'X-Requested-With: XMLHttpRequest' http://django.example.com/example
fails with CSRF error.

any help is appreciated, deeply.
Cheers,
Rex

jamescw

unread,
Jul 14, 2012, 1:58:49 PM7/14/12
to django-res...@googlegroups.com
I have the same issue using ResponseMixin and CSRF errors, I managed to get round it using this on my class based views:

@method_decorator(csrf_exempt)
    def dispatch(self, *args, **kwargs):
        return super(SomeView, self).dispatch(*args, **kwargs)

It works but it would be interesting to here Tom's view on this.

J

Tom Christie

unread,
Jul 14, 2012, 6:04:42 PM7/14/12
to django-res...@googlegroups.com
Thanks for letting me know. I thought the behaviour there should all be correct, but perhaps that's not the case. I'll try to find some time to look into it in the next few days.

  t.


DZ

unread,
Aug 1, 2012, 3:15:03 AM8/1/12
to django-res...@googlegroups.com
I can confirm this. Ran into the same problem and this solution was the way to solve the CSRF_exempt not working with the response mixin

Tom Christie

unread,
Aug 25, 2012, 3:26:24 PM8/25/12
to django-res...@googlegroups.com
Aplogies for the late follow up.
Running the examples in latest version from tip...

bash: curl -X POST -H 'X-Requested-With: XMLHttpRequest' -d bar=123 -d baz=baz http://127.0.0.1:8000/resource-example/0/
"POST request to AnotherExampleResource 0, with content: {'baz': u'baz', 'foo': False, 'bar': 123}"

Could anyone who's seeing this problem let me know what version they're running, and confirm if they can see the same issue working against the examples?

Andy Madsen

unread,
Jun 20, 2013, 3:24:19 PM6/20/13
to django-res...@googlegroups.com
I know this is an "ancient" thread, but just wanted to say after implementing my own "Login" method via Rest (questionable approach, but certainly not crazy), I had to disable CSRF, and was forced to override the "perform_authentication" method:

class AuthenticationApi(APIView):
    """
    Login/Signup.
    """
    
    def perform_authentication(self, request):
        pass
    
@csrf_exempt and @method_decorator(csrf_exempt) on the dispatch method had no effect.

Hopefully this helps someone who might be having a similar issue.

Errfan Wadia

unread,
Aug 19, 2014, 2:02:30 AM8/19/14
to django-res...@googlegroups.com
I was facing the same problem. It worked for me. Thanks
Reply all
Reply to author
Forward
0 new messages