简体   繁体   中英

JWT Authentication: Use UI token to authenticate Graphene/Django (GraphQL) queries?

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 ?

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')),
]

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM