Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

403 by graphene-django. don't use csrf_exempt

Tags:

django

graphql

I use graphene-django. Creating an application, GraphiQL worked well for login and other functions. But when I use Insomnia, I get a 403 Forbidden error.

I referred to this documentation, https://github.com/howtographql/howtographql/blob/master/content/backend/graphql-python/4-authentication.md

And I tried:

  1. using csrf_exempt; It works fine, but of course I will not use it.
  2. using django-cors-headers; It does not work well.

How can I solve this 403 error?

like image 302
Kouji Kawasaki Avatar asked Aug 09 '18 10:08

Kouji Kawasaki


4 Answers

I would not recommend @yestema 's second method to work around the problem you are facing.

Avoid using GET methods for querying your GraphQL endpoint

If one wants to implements this workaround and is also using Graphql for mutations, it looks like bad design.

It has been established as a standard that GET requests must not alter the state of the server nor the database, and mutations are, most of the times, used for altering the state of one or another (probably only the database, since your app should be stateless).

Note that you could also use query methods to alter the state of your backend, but, again, this would be against the established standard, as explained in the grapqhl documentation:

[...] In REST, any request might end up causing some side-effects on the server, but by convention it's suggested that one doesn't use GET requests to modify data. GraphQL is similar - technically any query could be implemented to cause a data write. However, it's useful to establish a convention that any operations that cause writes should be sent explicitly via a mutation.

When is it safe to use the csrf_exempt decorator?

To give hints to people wondering how bad it is to get rid of the default CSRF checks, here is my two cents explanation.

A service is exposed to CSRF attacks when the authentication parameters are automatically sent by the browser, which is the case with the default Django's authentication system, based on sessions.

If you use your Django app only as an API backend, chances are that you rely on another authentication mechanism, such as DRF's TokenAuthentication or some kind of JWT implementation.

Basically, these authentication systems are immune to CSRF attacks, because if a malicious website wants to access your server on behalf of your users — which is what CSRF is all about —, it won't be able to set the Authorization HTTP header expected by your server to actually authenticate the request (provided that you stored the token securely, in a cookie only accessible by your front application domain...).


tl;dr

Keep sending your GraphQL queries with POST requests, this is the best practice.

If your GraphQL endpoint is accessible only by authenticated users and your authentication system does not rely on Django's sessions, it's OK to exempt your endpoint from CSRF checking.

However, if you use the Django's default authentication system — ie, a sessionid stored in a cookie, then you must enforce the csrf verification. At this point, your only chance is, as said by previous answers, to add the X-CSRFToken header in your HTTP requests, and give it the value of the csrftoken cookie that was automatically set by previous requests to the server.


I initially posted this answer on GitHub, but thought it could be useful also here.

like image 118
edthrn Avatar answered Nov 09 '22 15:11

edthrn


What you are looking for is csrf_exempt in your url(r'^graphql', csrf_exempt(GraphQLView.as_view(graphiql=True))),

You can import it like this: from django.views.decorators.csrf import csrf_exempt.

csrf token is not required on the GraphQL endpoint, since it is an API.

CSRF tokens are required in production by default because django doesn't know which POST request is for a form and which isn't. Also CSRF might be useful in the case you want to use the GraphQL endpoint only on your website (so having the token is an additional security measure). But for you case it is totally fine to remove the CSRF token check in production.

like image 4
Ash Singh Avatar answered Nov 09 '22 15:11

Ash Singh


Var. 1) Set Header X-CSRFToken (also you can try X-CSRFTOKEN and csrftoken) X-CSRFToken in header

Var. 2) Not very correct solution, but it's easy & it works! Use GET request instead of POST. Somehow it works... GET REQUEST

OR

Var. 3) Didn't work for me Also. You can try go right way and add to cookie X-CSRFTOKEN a) click Cookie TAB b) Manage Cookie button c) Actions -> Add Cookie P.S. Actually Insomnia inject csrftoken automaticly, you can try usual REST POST and you will see, that it works fine and there is csrftoken automaticly added by insomnia... enter image description here

like image 3
yestema Avatar answered Nov 09 '22 15:11

yestema


If you want to use CSRF middleware with Graphene then you need to set CSRF token in the cookie of your request headers.

I don't have experience with Insomnia but I am sure it will let you customize request header, like Apollo link does.

like image 1
Exis Zhang Avatar answered Nov 09 '22 16:11

Exis Zhang