Graphene-django: Bypass csrf

Created on 17 Nov 2016  路  19Comments  路  Source: graphql-python/graphene-django

I have the use case of a mobile client app accessing graphql resource with Apollo Client. However, the client cannot access because of CSRF validation. In web I can get the token from cookie, but there is no cookie in mobile app. How can I solve this issue?

question

Most helpful comment

Hi @nlhkh!

You can do something like:

from django.conf.urls import url
from django.views.decorators.csrf import csrf_exempt
from graphene_django.views import GraphQLView

urlpatterns = patterns(
    # ...
    url(r'^graphql', csrf_exempt(GraphQLView.as_view(graphiql=True))),
    # ...
)

All 19 comments

Hi @nlhkh!

You can do something like:

from django.conf.urls import url
from django.views.decorators.csrf import csrf_exempt
from graphene_django.views import GraphQLView

urlpatterns = patterns(
    # ...
    url(r'^graphql', csrf_exempt(GraphQLView.as_view(graphiql=True))),
    # ...
)

Thanks @syrusakbary

@syrusakbary I had to do this after deploying my Django app to a live server to get GraphiQL to work on the web. Is that intended or should it find the CSRF token automatically?

@syrusakbary @nlhkh @Vitiell0
Now we can pass the csrf token in the request headers
https://github.com/reactql/kit/issues/77

I have been trying to make a solution like this but my JS foo isn't strong enough.

@syrusakbary is it possible to disable CSRF for a specific resolver/mutation instead of disabling it for everything?

I have a resolver that will be used by an external service (not my app), so it's not possible for it to use a CSRF token. But I don't want to disable CSRF entirely just because of that one resolver.

It would be great if the graphene-django docs could explain how to pass the CSRF token from a javascript client (preferably appollo). If I find out myself I will post it here. My latest attempt looks like this (note: doesn't work):

import ApolloClient from 'apollo-client';
import { createHttpLink } from "apollo-link-http"
import { InMemoryCache } from "apollo-cache-inmemory"
import { setContext } from "apollo-link-context"
import Cookies from 'js-cookie'

function createClient() {
  const httpLink = createHttpLink({
    uri: 'http://localhost:8000/graphql'
  });
  const authLink = setContext((_, { headers }) => {
    return {
      headers: {
        ...headers,
        "X-CSRFToken": Cookies.get('csrftoken'),
      }
    }
  });

  return new ApolloClient({
    link: authLink.concat(httpLink),
    cache: 'no-cache'
  });
}

@mnieber bruh

import { ApolloLink, concat } from 'apollo-link';
import { HttpLink } from 'apollo-link-http';

const httpLink = new HttpLink({
  uri: `/graphql`,
  credentials: 'same-origin',
});

const csrfMiddleware = new ApolloLink((operation, forward) => {
  operation.setContext(({ headers = {} }) => ({
    headers: {
      ...headers,
      'X-CSRFTOKEN':  Cookies.get('csrftoken'),
    }
  }));

  return forward(operation);
});

export const client = new ApolloClient({
  link: concat(csrfMiddleware, httpLink),
  cache,
});

Thanks @japrogramer, it looks a bit different from my attempt, but unfortunately it also doesn't work.

@mnieber maybe your Cookies.get('csrftoken') call isn't working ..
Im not actually calling Cookies.get I don't even have that installed. ..

@mnieber Hmm something like this should work.
document.cookies.match(new RegExp('csrftoken=([^;]*)(;|$)'))[0]

also try resetting your cache .. just in case.

The Cookies.get call is working (I checked it in this particular bit of code, and also, I'm using it in my jquery setup)

@mnieber
maybe its your package version.

"apollo-boost": "^0.1.10",
"apollo-link-ws": "^1.0.8",
"apollo-upload-client": "^9.1.0",
"graphql": "^14.0.2",
"graphql-tag": "^2.9.2",

@dspacejs you could splitting the schema and merging them, one would be csrf exempt and the combined schema wouldnt

In the end I solved my problem by using the graphql-request package. This also solved another problem where authentication headers were not included in the request. I would suggest to include this (or something similar) in the graphene-django docs, it would be a great help to get started with graphene-django.

import { request, GraphQLClient } from 'graphql-request'
import Cookies from 'js-cookie'


const client = new GraphQLClient(
  `/graphql`,
  {
    credentials: 'include',
    headers: {
      "X-CSRFToken": Cookies.get('csrftoken')
    }
  }
);

Strange I don't use that package at all, and my code works for me.

Many people have encountered the same problem. Usually, the solution for them is to import from 'apollo-client', but that did not work for me. Anyway, I'm happier with a simpler graphql client, so I like this solution.

It seems Graphiql cannot succesfully set correct CSRF token.

Is there a forked version that fixes this?

@gotexis You can try the advice from syrusakbary, it should work (https://github.com/graphql-python/graphene-django/issues/61#issuecomment-261199128)

@dspacejs You can put the query with that resolver in another scheme and provide another csrf-exempted view with that scheme.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nickhudkins picture nickhudkins  路  3Comments

hyusetiawan picture hyusetiawan  路  4Comments

BrianChapman picture BrianChapman  路  3Comments

StefanoSega picture StefanoSega  路  4Comments

MythicManiac picture MythicManiac  路  3Comments