2

I'm looking to write a custom middleware for my GraphQL endpoint using PyJWT. The problem is that I don't want to protect my login mutation. So I'm trying to write the Middleware to exclude the login mutation.

This was easy to do by writing a GraphQL middleware because the arguments passed to the Middleware provided me with the ability to check the name of the query.

class JWTMiddleware(object):
    def resolve(self, next, root, info, **args):
        if info.field_name == 'login':
            return next(root, info, **args
        # rest of auth logic

But because GraphQL always returns 200, I can't use the status code as my auth failure check on my client. And would have to check the errors array to see if the message is Unauthorized or something.

Example Error Response:

{
    errors: [
        {
            message: 'Unauthorized: JWT invalid',
            ...,
        },
        ...
    ],
    data: null
}

This is fine but I would prefer to use the status code of the response as my check so I decided to wrap the GraphQL view with a custom decorator.

def jwt_required(fn):
    def wrapper(request):
        # no access to query name, just the GraphQLString
        # need function to parse the AST of a GraphQLString
        graphql_string = request.body.decode('utf-8')
        query_name = ast[0].name  # or something like this
        if query_name == 'login':
             return fn(request)
        # rest of auth logic
        return fn(request)
    return wrapper


def protected_graphql_view():
    return jwt_required(GraphQLView.as_view())


urlpatterns = [
    path('admin/', admin.site.urls),
    path('graphiql', GraphQLView.as_view(graphiql=True)),
    path('graphql', protected_graphql_view()),
    path('token/refresh', refresh_token_view),
]

By doing it like this I now can return Responses with different status codes. But again the problem is I can't easily check if the request is for login and skip the auth logic unless I can parse the GraphQLString correctly.

I would prefer to not custom make something, if possible. I would assume GraphQL or Graphene would provide something like this.

Please let me know if I need to provide anymore information. Thank you for any help!

brandonbanks
  • 1,125
  • 1
  • 14
  • 21
  • 1
    I would suggest that you solve this problem differently and have two different API endpoints. Put the login and anything else that you don't want the middleware for in the second mutation. See this answer https://stackoverflow.com/questions/51116456/how-to-restrict-anonymous-users-from-graphql-api-endpoint/51213510#51213510 for details. – Mark Chackerian Mar 26 '19 at 13:07
  • I like that idea. I'll give it a shot. – brandonbanks Mar 26 '19 at 17:43

0 Answers0