Django returns 403 error when sending a POST request

Question:

when I’m using following Python code to send a POST request to my Django website I’m getting 403: Forbidden error.

url = 'http://www.sub.example.com/'
values = { 'var': 'test' }

try:
    data = urllib.urlencode(values, doseq=True)
    req = urllib2.Request(url, data)
    response = urllib2.urlopen(req)
    the_page = response.read()
except:
    the_page = sys.exc_info()
    raise

When I’m opening any other website it works properly.
example.com is Django website too, and it works properly too.
I think, that’s Django config problem, can anyone tell me what should I do to provide access to my script?

Asked By: Djent

||

Answers:

Does the view that you are posting to have a Django Form on it? If so, I wonder if it’s giving a csrf error. I think that manifests itself as a 403. In that case, you’d need to add the {{ csrf_token }} tag. Just a thought.

Answered By: Joe J

Look here https://docs.djangoproject.com/en/dev/ref/csrf/#how-to-use-it.

Try marking your view with @csrf_exempt. That way, Django’s CSRF middleware will ignore CSRF protection. You’ll also need to use from django.views.decorators.csrf import csrf_exempt. See: https://docs.djangoproject.com/en/dev/ref/csrf/#utilities

Please be advised that by disabling CSRF protection on your view, you are opening a gate for CSRF attacks.

If security is vital to you then consider using @csrf_exempt followed by @requires_csrf_token (see: https://docs.djangoproject.com/en/dev/ref/csrf/#unprotected-view-needs-the-csrf-token). Then, in your script pass this token and that’s it.

Answered By: bx2

The response is 403 because django requires a csrf token (included in the post data) in every POST request you make.

There are various ways to do this such as:

Acquiring the token from cookie and the method has been explained in article enter link description here

or

You can access it from DOM using {{ csrf_token }}, available in the template

So now using the second method:

var post_data = {
  ...
  'csrfmiddlewaretoken':"{{ csrf_token }}"
  ...
}

$.ajax({
  url:'url',
  type:'POST'
  data:post_data,
  success:function(data){
    console.log(data);
  },
  error:function(error){
    console.log(error);
  }
});
Answered By: Hiro

Or you can allow the permission to make this post request.

Note: Should be used in the cases where you don’t need to authenticate the users for posting anything on our server, say, when a new user registers for the first time.

from rest_framework.permissions import AllowAny

class CreateUser(APIView):
    permission_classes = (AllowAny,)
    def post(self, request, format=None):
        return(Response("hi"))

Further Note that, If you want to make that post request form a different domain (in case when the front of the application is in React or angular and the backend is in Django), make sure the add following in the settings file:

  1. Update the INSTALLED_APPS to use ‘coreHeaders’ :

    INSTALLED_APPS = [
    ‘corsheaders’,
    ]

  2. White list your front end domain by adding following to settings file again:

    CORS_ORIGIN_WHITELIST = (
    ‘localhost:8080’,
    )

Answered By: Santosh Pillai

Django documentation provides several ways to ensure that CSRF tokens are included. See https://docs.djangoproject.com/en/1.11/ref/csrf/ for details.

Answered By: polarise

I got this error when an authentication Token was expired or when no Token was sent with the request. Using a renewed token fixed the problem.

curl -X POST -H "Authorization: Token mytoken" -d "name=myname&age=0" 127.0.0.1:8000/myapi/

or

curl -X POST -H "Authorization: JWT mytoken" -d "name=myname&age=0" 127.0.0.1:8000/myapi/

depending on Token type.

Answered By: DevB2F

I too had this problem, because I Tried to access the Main endpoint from another endpoint using '../url' URL Jumping.
My Solution was to add another path for the same viewset;

router.register('main/url',ViewSet,'name');
router.register('secondary/url',ViewSet,'name')

But in Your Case You are Trying to access it from a completely different Location, From Django’s Point of view So You need to mark you ViewSet with @crsf_exempt middleware which will Disable Security Protocols Related to CRSF.

Answered By: ax39T-Venom