Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle CSRF in preflighted CORS POST request in django?

I am trying to make POST request via AJAX from abc.com to URL from xyz.com (which is a Django application). I am getting CSRF token by making a GET request to a URL on xyz.com, but the token changes when an OPTIONS request is made to xyz.com in the preflighted request.

Is there any way to get the response of OPTIONS request in the preflighted request ?

Note:

I am following instructions from following sources :

  • https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
  • https://developer.mozilla.org/en/docs/HTTP/Access_control_CORS
  • http://www.html5rocks.com/en/tutorials/cors/
like image 259
vedarthk Avatar asked Nov 13 '13 08:11

vedarthk


People also ask

How does Django handle CSRF?

Django protects against CSRF attacks by generating a CSRF token in the server, send it to the client side, and mandating the client to send the token back in the request header. The server will then verify if the token from client is the same as the one generated previously; if not it will not authorise the request.

How do I ignore CSRF token in Django?

1. Using @csrf_exempt decorator. The is will import the @csrf_exempt decorator that allows you to easily disable CSRF validation for specific views. Just place @csrf_exempt decorator immediately above the view for which you do not want CSRF protection.

What is CSRF how it's preventing in Django?

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.


2 Answers

Django CSRF protection will allow OPTIONS requests, so no problem with the first stage:

https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#how-it-works

If I understand correctly, you then want the next request (e.g. a cross-domain POST) to be allowed through. For this to work and get past Django's CSRF protection, the request must send a CSRF token (in POST data or in header for AJAX) and a matching CSRF cookie.

Now, cross-domain restrictions make it impossible for abc.com to set or read a cookie for xyz.com, whether from javascript or from a server side response. Therefore, this approach is impossible.

Instead you will have to apply @csrf_exempt to the view. This would allow any site to post to it. Therefore, you'll need to build in some other protection to the view. You are, of course, on your own in checking the security of your protection. Remember that 'Referer' and 'Origin' headers can easily be forged with something as basic as curl.

like image 152
spookylukey Avatar answered Oct 20 '22 07:10

spookylukey


See django-cors-headers, you may find it how it works more suitable to solve your problem:

https://github.com/ottoyiu/django-cors-headers/

Django-rest-framework recommends http://www.django-rest-framework.org/topics/ajax-csrf-cors

like image 45
Mario César Avatar answered Oct 20 '22 05:10

Mario César