KundaPanda / strawberry-django-jwt

[UNMAINTAINED] JSON Web Token (JWT) authentication for Django with Strawberry GraphQL
MIT License
37 stars 16 forks source link

RefreshTokenMixin yields ValueError #355

Closed fleverest closed 2 years ago

fleverest commented 2 years ago

Django: 4.1 Python: 3.10.4 strawberry-django-jwt 0.2.2

I've followed the setup instructions on the README and included the optional refresh token configuration. When invoking the refreshToken mutation I run into the following error:

GraphQL request:2:3
2 |   refreshToken (token:"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NjMzMTE4
  |   ^
...
  File "/usr/local/lib/python3.10/site-packages/strawberry_django_jwt/mixins.py", line 107, in _refresh
    result = TokenDataType(payload, token, refresh_expires_in)
TypeError: TokenDataType.__init__() takes 1 positional argument but 4 were given

It appears this line attempts to instantiate TokenDataType using 3 positional arguments when there are 4 members: https://github.com/KundaPanda/strawberry-django-jwt/blob/54ad4b0a45f211b702b2f4c6541d4d8c5762050d/strawberry_django_jwt/object_types.py#L45-L50

I think this could be resolved by changing the call to result = TokenDataType(payload=payload, token=token, refresh_expired_in=refresh_expires_in).

oleksandr-luxmedien commented 2 years ago

Django: 3.2 Python: 3.10.6

Same for me. Introduced with strawberry-django-jwt 0.2.2, version 0.2.1 was working fine.

oleksandr-luxmedien commented 2 years ago

Here is my workaround using wrapt decorator library. Basically it patches the way the instance of RefreshedTokenType is created suppressing the default instance constructor. Here is the code:

# monkeypatch.py

import wrapt
from strawberry_django_jwt.refresh_token.object_types import RefreshedTokenType

def patched_init(wrapped, instance, args, kwargs):
    # here, wrapped is the original __init__,
    # instance is `self` instance,
    # args and kwargs are tuple and dict respectively.

    payload, token, refresh_token = args
    refresh_expires_in = kwargs.get('refresh_expires_in', 0)
    # note it is already bound to the instance
    wrapped(
        payload=payload, token=token, refresh_token=refresh_token,
        refresh_expires_in=refresh_expires_in)

wrapt.wrap_function_wrapper(RefreshedTokenType, '__init__', patched_init)

Then import this module into your root schema file.

fleverest commented 2 years ago

Thanks for sharing your patch! I'm sure it will be useful when I get around to working on this again.

wodCZ commented 2 years ago

Maybe this is also related to this release: https://github.com/strawberry-graphql/strawberry/releases/tag/0.128.0 ?

Whenever instantiating a Strawberry type make sure that you only pass values are keyword arguments

Here Oleksandr's patch without wrapt library. Again, call the patch function before initializing the schema.

def patch_refresh_token_mixin():
    # Fixes https://github.com/KundaPanda/strawberry-django-jwt/issues/355
    import strawberry_django_jwt.refresh_token.object_types

    class MyRefreshedTokenType(strawberry_django_jwt.refresh_token.object_types.RefreshedTokenType):
        def __init__(self, *args, **kwargs):
            payload, token, refresh_token = args
            refresh_expires_in = kwargs.get("refresh_expires_in", 0)

            super().__init__(
                payload=payload, token=token, refresh_token=refresh_token, refresh_expires_in=refresh_expires_in
            )

    strawberry_django_jwt.refresh_token.object_types.RefreshedTokenType = MyRefreshedTokenType