JSONWebTokenMiddleware always returns Anonymous User - Possible Bug & Fix
See original GitHub issueHi Folks,
LOVE this project and its amazing contributions to the Graphene / GraphQL ecosystem in Python. I’ve been running into a weird bug that I think I finally traced and seems to be in your allow_any method in your JSONWebTokenMiddleware. I keep trying to authenticate with a JWT token and keep getting an error that my user is not authenticated. I had a JWT token and it was valid, so I tried to trace where this was coming from in your JSONWebTokenMiddleware with this modified code:
def resolve(self, next, root, info, **kwargs):
print(f"Resolve...")
context = info.context
token_argument = get_token_argument(context, **kwargs)
print("Check 1")
if jwt_settings.JWT_ALLOW_ARGUMENT and token_argument is None:
user = self.cached_authentication.parent(info.path)
print(f"User check 1: {user}")
if user is not None:
context.user = user
elif hasattr(context, "user"):
if hasattr(context, "session"):
context.user = get_user(context)
self.cached_authentication.insert(info.path, context.user)
else:
context.user = AnonymousUser()
print("Check 2")
if (
_authenticate(context) or token_argument is not None
) and self.authenticate_context(info, **kwargs):
user = authenticate(request=context, **kwargs)
print(f"User check 2: {user}")
if user is not None:
context.user = user
if jwt_settings.JWT_ALLOW_ARGUMENT:
self.cached_authentication.insert(info.path, user)
print("Return...")
print(f"context user: {info.context.user}")
return next(root, info, **kwargs)
Turns out the user keeps coming back as AnonymousUser:
gk_django | Resolve...
gk_django | Check 1
gk_django | Check 2
gk_django | Return...
gk_django | context user: AnonymousUser
I traced the code and found your allow_any method appears to be throwing an unexpected error which is handled by the Middleware as if the User is invalid.
This line in allow_any:
field = info.schema.get_type(operation_name).fields.get(info.field_name)
Results in this error:
"'NoneType' object has no attribute 'fields'"
It looks like, when I send a query for a model called corpus, for example, the operation_name argument resolves to “Query”. When I look at info.schema.types, however, Query is not one of the types. The CorpusNode name is in there, however. So, when I change the field = call to look to resolve to get_type(‘CorpusNode’)…
field = info.schema.get_type(info.return_type.graphene_type._meta.node._meta.name).fields.get(info.field_name)
It works (with the same JWT token that said I was unauthorized before)!
It looks like others have run into similar-ish sounding problems (see recent issue #289 where someone notes there is a problem in the Middleware), so possibly this is unexpected behavior? Not sure why more people aren’t running into this if it’s a bug though. If it helps, here’s the current list of graphene-related packages I’m using.
graphene 2.1.9
django-graphql-jwt 0.3.4
graphene-django 2.15.0
graphene-django-crud 1.3.2
graphene-django-extras 0.4.9
graphene-django-optimizer 0.9.1
graphene-django-plus 4.0.3
graphene-file-upload 1.3.0
graphene-permissions 1.1.4
graphene-subscriptions 1.0.2
graphql-core 2.3.2
graphql-relay 2.0.1
Issue Analytics
- State:
- Created 2 years ago
- Comments:10
Top GitHub Comments
We had the same issue with graphene v3. As a workaround, we copy-pasted the
allow_any
function from 2f670d7 and setJWT_ALLOW_ANY_HANDLER
to use that version of theallow_any
function.@msimav, I’ll try to give it a shot this weekend.