flavors / django-graphql-jwt

JSON Web Token (JWT) authentication for Graphene Django
https://django-graphql-jwt.domake.io
MIT License
820 stars 173 forks source link

AttributeError: 'int' object has no attribute 'session' #113

Open bendog opened 5 years ago

bendog commented 5 years ago

While I've got graphql_jwt in Graphene['Middleware'] I can't get any response from the GraphiQL interface or load the Schema.

However, if I provide the JWT it does work.

I am running a custom JWT_DECODE_HANDLER script to Authenticate against AWS Cognito.

I'm assuming that somewhere I might need to (or have explicitly failed to) define how to handle anonymous connections?

Python 3.7.3 django==2.2.3 graphene-django==2.3.2 django-graphql-jwt==0.2.1 django-cognito-jwt==0.0.3 used for from django_cognito_jwt.validator import TokenError, TokenValidator which is then extended to auth with cognito

settings.py

...
from django_cognito_jwt.validator import TokenError, TokenValidator
...
COGNITO_AWS_REGION = os.environ.get('AWS_DEFAULT_REGION')
COGNITO_USER_POOL = os.environ.get('COGNITO_USER_POOL')
COGNITO_AUDIENCE = os.environ.get('COGNITO_CLIENT_ID')

COGNITO_PUBLIC_KEYS_CACHING_ENABLED = True
COGNITO_PUBLIC_KEYS_CACHING_TIMEOUT = 60 * 60 * 24

class GraphQLTokenValidator(TokenValidator):

    def validate(self, token, context):
        """ extend the validate function to also take a context argument """
        response = super().validate(token)
        return response

validator = GraphQLTokenValidator(COGNITO_AWS_REGION, COGNITO_USER_POOL, COGNITO_AUDIENCE)

JWT_ALGORITHM = 'RS256'
JWT_ISSUER = "https://cognito-idp.{}.amazonaws.com/{}".format(
    COGNITO_AWS_REGION, COGNITO_USER_POOL
)

GRAPHQL_JWT = {
    'JWT_ALGORITHM': JWT_ALGORITHM,
    'JWT_VERIFY_EXPIRATION': True,
    'JWT_AUTH_HEADER_PREFIX': 'Bearer',
    'JWT_ISSUER': JWT_ISSUER,
    'JWT_DECODE_HANDLER': validator.validate,
    'JWT_PAYLOAD_GET_USERNAME_HANDLER': lambda payload: payload.get('sub'),
}

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'graphql_jwt.backends.JSONWebTokenBackend',
]

GRAPHENE = {
    'SCHEMA': 'rfid.schema.schema',
    'MIDDLEWARE': [
        'graphql_jwt.middleware.JSONWebTokenMiddleware', # removing this line everything works as expected, except obviously the authentication part
    ],
}

graphql error

{
  "errors": [
    {
      "message": "'int' object has no attribute 'session'",
      "locations": [
        {
          "line": 3,
          "column": 5
        }
      ],
      "path": [
        "__schema"
      ]
    }
  ],
  "data": null
}

Django error message

"GET /graphql HTTP/1.1" 200 1285
An error occurred while resolving field Query.__schema
Traceback (most recent call last):
  File "$PROJDIR/.venv/lib/python3.7/site-packages/graphql/execution/executor.py", line 450, in resolve_or_error
    return executor.execute(resolve_fn, source, info, **args)
  File "$PROJDIR/.venv/lib/python3.7/site-packages/graphql/execution/executors/sync.py", line 16, in execute
    return fn(*args, **kwargs)
  File "$PROJDIR/.venv/lib/python3.7/site-packages/graphql_jwt/middleware.py", line 112, in resolve
    if ((_authenticate(context) or token_argument is not None) and
  File "$PROJDIR/.venv/lib/python3.7/site-packages/graphql_jwt/middleware.py", line 39, in _authenticate
    is_anonymous = not hasattr(request, 'user') or request.user.is_anonymous
  File "$PROJDIR/.venv/lib/python3.7/site-packages/django/utils/functional.py", line 256, in inner
    self._setup()
  File "$PROJDIR/.venv/lib/python3.7/site-packages/django/utils/functional.py", line 392, in _setup
    self._wrapped = self._setupfunc()
  File "$PROJDIR/.venv/lib/python3.7/site-packages/django/contrib/auth/middleware.py", line 24, in <lambda>
    request.user = SimpleLazyObject(lambda: get_user(request))
  File "$PROJDIR/.venv/lib/python3.7/site-packages/django/contrib/auth/middleware.py", line 12, in get_user
    request._cached_user = auth.get_user(request)
  File "$PROJDIR/.venv/lib/python3.7/site-packages/django/contrib/auth/__init__.py", line 189, in get_user
    user = get_user(user_id)
  File "$PROJDIR/.venv/lib/python3.7/site-packages/django/contrib/auth/__init__.py", line 182, in get_user
    user_id = _get_user_session_key(request)
  File "$PROJDIR/.venv/lib/python3.7/site-packages/django/contrib/auth/__init__.py", line 59, in _get_user_session_key
    return get_user_model()._meta.pk.to_python(request.session[SESSION_KEY])
mongkok commented 4 years ago

Hi @bendog, any updates?

bendog commented 4 years ago

@mongkok I'm not working on the project i was using this for anymore, so I can't see how i resolved it, if i even did...

jackton1 commented 3 years ago

@mongkok @bendog I think the problem here is with this line

'JWT_PAYLOAD_GET_USERNAME_HANDLER': lambda payload: payload.get('sub'),

You’ll need to update the JWT_GET_USER_BY_NATURAL_KEY_HANDLER to handle retrieving the user by id.