jazzband / django-rest-knox

Authentication Module for django rest auth
MIT License
1.17k stars 215 forks source link

How to use knox with social login #257

Closed eakenbor closed 10 months ago

eakenbor commented 3 years ago

I can successfully log in using email and password, but when I try to use social authentication in combination with django allauth and dj rest auth, I get the following error:

raise type(exc)(msg)
AttributeError: Got AttributeError when attempting to get a value for field `token` on serializer `KnoxSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `tuple` instance.
Original exception text was: 'tuple' object has no attribute 'token'.

Here is my views.py

from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter
from allauth.socialaccount.providers.google.views import GoogleOAuth2Adapter
from dj_rest_auth.registration.views import SocialLoginView

class FacebookLogin(SocialLoginView):
    adapter_class = FacebookOAuth2Adapter

class GoogleLogin(SocialLoginView):
    adapter_class = GoogleOAuth2Adapter
    client_class = OAuth2Client

urls.py

from users.views import  FacebookLogin, GoogleLogin

    path('social-rest-auth/login/facebook/',
         FacebookLogin.as_view(), name='fb_login'),
    path('social-rest-auth/login/google/',
         GoogleLogin.as_view(), name='google_login'),

serializers.py

class KnoxSerializer(serializers.Serializer):
    """
    Serializer for Knox authentication.
    """
    token = serializers.CharField()
    user = UserSerializer(many=False, read_only=True)

settings.py

REST_AUTH_SERIALIZERS = {
    'USER_DETAILS_SERIALIZER': 'users.serializers.UserSerializer',
    'TOKEN_SERIALIZER': 'users.serializers.KnoxSerializer',
    'PASSWORD_RESET_SERIALIZER': 'users.serializers.PasswordResetSerializer'
}
REST_FRAMEWORK = {
    # 'DEFAULT_PERMISSION_CLASSES': (
    #     'rest_framework.permissions.IsAuthenticated',
    # ),
    'EXCEPTION_HANDLER': 'users.exceptions.custom_exception_handler',
    'DEFAULT_AUTHENTICATION_CLASSES': (
        # 'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        # 'rest_framework.authentication.TokenAuthentication',
        'knox.auth.TokenAuthentication',
    )
}

Please can someone help me with this?

olaokoroafor commented 2 years ago

Did you ever resolve this issue? I am looking to conduct a similar thing as you by combining social authentication with knox!

eakenbor commented 2 years ago

@olaokoroafor, try this:

settings.py

REST_AUTH_SERIALIZERS = {
    ...
    "TOKEN_SERIALIZER": "users.serializers.KnoxSerializer",
    ...
}

REST_AUTH_TOKEN_MODEL = "knox.models.AuthToken"

REST_AUTH_TOKEN_CREATOR = "users.utils.create_knox_token"

REST_FRAMEWORK = {
    ...
    "DEFAULT_AUTHENTICATION_CLASSES": (
        ...
        "knox.auth.TokenAuthentication",
    ),
}
utils.py

def create_knox_token(token_model, user, serializer):
    instance, token = AuthToken.objects.create(user=user)
    return {"expiry": instance.expiry, "user": instance.user, "token": token}
olaokoroafor commented 2 years ago

Thank you so much!!! This is very helpful.

olaokoroafor commented 2 years ago

Would everything from your previous implementation stay the same?

eakenbor commented 2 years ago

Yes