4
votes

I am working on a project with the following architecture:

  • UI: React on client and server-side rendering via a Node server, Apollo Client for GraphQL,

  • API: Django handles GraphQL queries through Graphene.

I use Auth0 (JWT based) for my frontend authentication. I would like to use the token I get to authenticate my user in the context of the GraphQL queries API side.

[Edit2]

To pass the token to my API, I use:

const idToken = cookie.load('idToken') || null;
networkInterface.use([{
  applyMiddleware(req, next) {
    if (!req.options.headers) {
      req.options.headers = {};  // Create the header object if needed.
    }
    req.options.headers.authorization = `Bearer ${idToken}`;
    next();
  }
}]);

Then I need to retrieve it in Django: I use django-jwt-auth and the code proposed by @Craig Ambrose.

My authorization header is received and decoded (I can get the payload) but there is a problem when verifying the signature: I get "Error decoding signature."

This is strange since the signature is verified when I test it on jwt.io.

How can I authenticate on Django side ?

2
From what I understand you are trying to do the following. - Authenticate using Auth0, - Use the token that Auth0 returns to make calls to a Django app which then queries using Graphene? Is that correct?ShrekOverflow
Yes absolutely! I would like to set up my Django project so that when a GraphQL query is made with a JWT header, I can use : @with_context in my graphql-django-view and use context.user.is_authenticated() like in User-based Queryset Filteringvwrobel
So what problem are you facing exactly? Currently, the id_token will work but Auth0 is soon going to add features that allow you to setup resource servers and request an access token to be able to make request to those request servers.ShrekOverflow
Hi @Abhishrek. My problem was that I could not find any docs explaining what my Django settings should look like for this configuration (may be this configuration is not that special). django-auth0, django-jwt-auth or djangorestframework-auth0 did not seem to fit. So I was requesting some kind of inputs / guidance about that. I did not have the time to try some solution. Would you have any advice on where I should look-at? I will post my settings once I have something up and running.vwrobel

2 Answers

5
votes

I've just done this using django-jwt-auth (not using Auth0)

That package provides a JSONWebTokenAuthMixin that you can combine with the GraphQLView from graphene_django, for example.

from jwt_auth.mixins import JSONWebTokenAuthMixin

class AuthGraphQLView(JSONWebTokenAuthMixin, GraphQLView):
    pass

urlpatterns = [
    url(r'^graphql', csrf_exempt(AuthGraphQLView.as_view(schema=schema))),
    url(r'^graphiql', include('django_graphiql.urls')),
]

This works, but I found that graphiql stopped working, because it wasn't sending to token. I wanted to keep using cookie based auth for that, for dev purposes, so changed it to the following.

from jwt_auth.mixins import JSONWebTokenAuthMixin

class OptionalJWTMixin(JSONWebTokenAuthMixin):
    def dispatch(self, request, *args, **kwargs):
        auth = get_authorization_header(request)
        if auth:
            return super(OptionalJWTMixin, self).dispatch(request, *args, **kwargs)
        else:
            return super(JSONWebTokenAuthMixin, self).dispatch(request, *args, **kwargs)


class AuthGraphQLView(OptionalJWTMixin, GraphQLView):
    pass

urlpatterns = [
    url(r'^graphql', csrf_exempt(AuthGraphQLView.as_view(schema=schema))),
    url(r'^graphiql', include('django_graphiql.urls')),
]
0
votes

My setting is working now:

I have used code from @Craig Ambrose with django-jwt-auth. I had to fork the package on Github to handle the Audience 'aud' payload present in Auth0 Token.

def jwt_get_user_id_from_payload_handler(payload):
    sub = payload.get('sub')
    Auth0User = import_string('project.models.Auth0User')
    auth0_user = Auth0User.objects.filter(auth0_id=sub)[0]
    user_id = auth0_user.user.id
    return user_id

JWT_PAYLOAD_GET_USER_ID_HANDLER = jwt_get_user_id_from_payload_handler
auth0_key = '<MyAuth0SECRET>'
JWT_SECRET_KEY = base64.b64decode(auth0_key.replace("_","/").replace("-","+"))
JWT_VERIFY = True
JWT_AUTH_HEADER_PREFIX = 'Bearer'
JWT_AUDIENCE = '<MyAuth0CLIENT_ID>'

With Aut0User a model with OnoToOne relation with classic Django user and a field with auth0_id.