Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Google login with auth code flow #488

Merged
merged 1 commit into from
Feb 26, 2023
Merged

Fix Google login with auth code flow #488

merged 1 commit into from
Feb 26, 2023

Conversation

c-w
Copy link
Contributor

@c-w c-w commented Feb 21, 2023

In #482 a regression was introduced for logging in with Google using the auth-code flow:

Traceback (most recent call last):
  File "/venv/lib/python3.11/site-packages/allauth/socialaccount/providers/google/views.py", line 21, in complete_login
    identity_data = jwt.decode(
                    ^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/jwt/api_jwt.py", line 168, in decode
    decoded = self.decode_complete(
              ^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/jwt/api_jwt.py", line 120, in decode_complete
    decoded = api_jws.decode_complete(
              ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/jwt/api_jws.py", line 191, in decode_complete
    payload, signing_input, header, signature = self._load(jwt)
                                                ^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/jwt/api_jws.py", line 247, in _load
    raise DecodeError(f"Invalid token type. Token must be a {bytes}")
jwt.exceptions.DecodeError: Invalid token type. Token must be a <class 'bytes'>

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/opt/project/backend/profiles/tests.py", line 209, in test_social_login_google
    response = self.client.post(
               ^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/django/test/client.py", line 852, in post
    response = super().post(
               ^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/django/test/client.py", line 441, in post
    return self.generic(
           ^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/django/test/client.py", line 541, in generic
    return self.request(**r)
           ^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/django/test/client.py", line 810, in request
    self.check_exception(response)
  File "/venv/lib/python3.11/site-packages/django/test/client.py", line 663, in check_exception
    raise exc_value
  File "/venv/lib/python3.11/site-packages/django/core/handlers/exception.py", line 56, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/django/views/decorators/csrf.py", line 55, in wrapped_view
    return view_func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/django/views/generic/base.py", line 103, in view
    return self.dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/venv/lib/python3.11/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/venv/lib/python3.11/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/project/backend/profiles/views.py", line 147, in post
    serializer.is_valid(raise_exception=True)
  File "/venv/lib/python3.11/site-packages/rest_framework/serializers.py", line 227, in is_valid
    self._validated_data = self.run_validation(self.initial_data)
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/rest_framework/serializers.py", line 429, in run_validation
    value = self.validate(value)
            ^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/dj_rest_auth/registration/serializers.py", line 151, in validate
    login = self.get_social_login(adapter, app, social_token, response={'id_token': token})
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/dj_rest_auth/registration/serializers.py", line 60, in get_social_login
    social_login = adapter.complete_login(request, app, token, response=response)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/allauth/socialaccount/providers/google/views.py", line 39, in complete_login
    raise OAuth2Error("Invalid id_token") from e
allauth.socialaccount.providers.oauth2.client.OAuth2Error: Invalid id_token

For the latest allauth, in the auth-code flow, the token variable already holds a dictionary with an id_token field so it's unnecessary to wrap the response. This pull request fixes the regression.

@sp-luciano-chinke
Copy link

My fault on that! Sorry and thanks! ❤️

@iMerica iMerica merged commit 8378083 into iMerica:master Feb 26, 2023
@c-w c-w deleted the fix-google-login branch February 27, 2023 08:00
@ghost
Copy link

ghost commented Apr 12, 2023

Is there an ETA on when this fix is going to be released?

@tadamcz
Copy link

tadamcz commented Dec 22, 2023

I'm confused: the commit with the fix is tagged as 5.0.2. I am on 5.0.2, and I still get the issue.

Specifically, my versions for dj-rest-auth and django-allauth are:

# pyproject.toml
dj-rest-auth = {extras = ["with-social"], version = "^5.0.2"}
# poetry.lock

[[package]]
name = "dj-rest-auth"
version = "5.0.2"
description = "Authentication and Registration in Django Rest Framework"
optional = false
python-versions = ">=3.6"
files = [
    {file = "dj-rest-auth-5.0.2.tar.gz", hash = "sha256:aad7d912476169e9991547bf98645344d3939be2d7052098048d819524c115d9"},
]

[package.dependencies]
Django = ">=3.2"
django-allauth = {version = ">=0.56.0,<0.58.0", optional = true, markers = "extra == \"with-social\""}
djangorestframework = ">=3.13.0"

[package.extras]
with-social = ["django-allauth (>=0.56.0,<0.58.0)"]

...

[[package]]
name = "django-allauth"
version = "0.57.0"
description = "Integrated set of Django applications addressing authentication, registration, account management as well as 3rd party (social) account authentication."
optional = false
python-versions = ">=3.7"
files = [
    {file = "django-allauth-0.57.0.tar.gz", hash = "sha256:a095ef0db7de305d9175772c78e765ebd5fceb004ae61c1383d7fc1af0f7c5b1"},
]

My traceback is (as far as I can tell) exactly identical to the OP:

Expand
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/allauth/socialaccount/providers/google/views.py", line 42, in complete_login
    identity_data = jwt.decode(
                    ^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/jwt/api_jwt.py", line 210, in decode
    decoded = self.decode_complete(
              ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/jwt/api_jwt.py", line 151, in decode_complete
    decoded = api_jws.decode_complete(
              ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/jwt/api_jws.py", line 198, in decode_complete
    payload, signing_input, header, signature = self._load(jwt)
                                                ^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/jwt/api_jws.py", line 254, in _load
    raise DecodeError(f"Invalid token type. Token must be a {bytes}")
jwt.exceptions.DecodeError: Invalid token type. Token must be a <class 'bytes'>

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/asgiref/sync.py", line 534, in thread_handler
    raise exc_info[1]
  File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 42, in inner
    response = await get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/asgiref/sync.py", line 534, in thread_handler
    raise exc_info[1]
  File "/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py", line 253, in _get_response_async
    response = await wrapped_callback(
               ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/asgiref/sync.py", line 479, in __call__
    ret: _R = await loop.run_in_executor(
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/asgiref/current_thread_executor.py", line 40, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/asgiref/sync.py", line 538, in thread_handler
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/contextlib.py", line 81, in inner
    return func(*args, **kwds)
           ^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/views/decorators/csrf.py", line 56, in wrapper_view
    return view_func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 104, in view
    return self.dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/utils/decorators.py", line 46, in _wrapper
    return bound_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/views/decorators/debug.py", line 92, in sensitive_post_parameters_wrapper
    return view(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/dj_rest_auth/views.py", line 48, in dispatch
    return super().dispatch(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/usr/local/lib/python3.11/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/usr/local/lib/python3.11/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/api/views.py", line 35, in post
    return super(GoogleLogin, self).post(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/dj_rest_auth/views.py", line 125, in post
    self.serializer.is_valid(raise_exception=True)
  File "/usr/local/lib/python3.11/site-packages/rest_framework/serializers.py", line 227, in is_valid
    self._validated_data = self.run_validation(self.initial_data)
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/rest_framework/serializers.py", line 429, in run_validation
    value = self.validate(value)
            ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/dj_rest_auth/registration/serializers.py", line 158, in validate
    login = self.get_social_login(adapter, app, social_token, response={'id_token': id_token})
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/dj_rest_auth/registration/serializers.py", line 62, in get_social_login
    social_login = adapter.complete_login(request, app, token, response=response)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/allauth/socialaccount/providers/google/views.py", line 60, in complete_login
    raise OAuth2Error("Invalid id_token") from e
allauth.socialaccount.providers.oauth2.client.OAuth2Error: Invalid id_token

@tadamcz
Copy link

tadamcz commented Dec 22, 2023

Upon further investigation, it looks like the commit was first released under 4.0.0, but this doesn't explain why the problem should still occur. Should this be a new issue?

@mcbarin
Copy link

mcbarin commented Jan 23, 2024

I'm having the exact same error; seems like it's still not fixed or we're doing something wrong.

Django==3.2.18
dj-rest-auth==5.0.2
django-allauth==0.60.1

Have you fixed this or found a workaround @tadamcz ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants