pythondjangooauth-2.0django-allauthdj-rest-auth

How to I override dj-rest-auth Registrations' SocialLoginSerializer?


my system uses a custom user entity and I need to create this entity inside SocialLoginSerializer.

It is not seemed to be mentioned here: https://dj-rest-auth.readthedocs.io/en/latest/configuration.html I tried adding in settings.py

REST_AUTH_SERIALIZERS = {   
'LOGIN_SERIALIZER': 'BackendApp.auth_serializers.LoginSerializer', 
'TOKEN_SERIALIZER': 'dj_rest_auth.serializers.TokenSerializer',  
"PASSWORD_RESET_SERIALIZER": "BackendApp.auth_serializers.PasswordResetSerializer", 
} 
REST_AUTH_REGISTER_SERIALIZERS = {   
'REGISTER_SERIALIZER':'BackendApp.auth_serializers.RegisterSerializer', 
'SOCIAL_LOGIN_SERIALIZER' :"BackendApp.auth_serializers.SocialLoginSerializer" 
}

While I can do postman but it is using the default SocialLoginSerializer. I need to do extra work os I used a customised one.

Any help is greatly appreciated

My customised SocialLoginSerializer.py (Original source code from dj-rest-auth)


class SocialLoginSerializer(serializers.Serializer):
    access_token = serializers.CharField(required=False, allow_blank=True)
    code = serializers.CharField(required=False, allow_blank=True)
    id_token = serializers.CharField(required=False, allow_blank=True)
    endUserType = serializers.CharField(required=True, write_only=True)
    
    ....
    
    def get_cleaned_data(self):
        return {
            'endUserType': self.validated_data.get('endUserType', '')
        }
    def validate(self, attrs):

        ....

        if not login.is_existing:
            # We have an account already signed up in a different flow
            # with the same email address: raise an exception.
            # This needs to be handled in the frontend. We can not just
            # link up the accounts due to security constraints
            if allauth_settings.UNIQUE_EMAIL:
                # Do we have an account already with this email address?
                account_exists = get_user_model().objects.filter(
                    email=login.user.email,
                ).exists()
                if account_exists:
                    raise serializers.ValidationError(
                        _('User is already registered with this e-mail address.'),
                    )

            login.lookup()
            login.save(request, connect=True)
            endUser = EndUser(
                email = login.user.email,
                endUserType = self.validated_data.get('endUserType', ''),
                password = "",
                salt = "",
                )# added this line and the line below only for my custom SocialLoginSerializer
            endUser.save() #

        attrs['user'] = login.account.user

        return attrs

Edit:

url.py

path('auth/google/', GoogleLogin.GoogleLoginView.as_view(), name='google_login'),

GoogleLogin.py

from allauth.socialaccount.providers.google.views import GoogleOAuth2Adapter
from allauth.socialaccount.providers.oauth2.client import OAuth2Client
# from dj_rest_auth.registration.views import SocialLoginView
from .SocialLogin import SocialLoginView
class GoogleLoginView(SocialLoginView):
    adapter_class = GoogleOAuth2Adapter
    #I do not know if this client id is the callback_url that this requires. -Rya
    callback_url = "http://localhost:8000/"
    client_class = OAuth2Client

I tried making a SocialLoginView that uses SocialLoginSerializer. My GoogleLoginView uses SocialLoginView.


Solution

  • What i did is to GoogleOAuth2Adapter from AllAuth so that i could create my custom entity. some of the imports in SocialLogin is not needed but I do not know what.

    SocialLogin.py

    from django.core.exceptions import ObjectDoesNotExist
    from allauth.socialaccount.providers.oauth2.views import (
        OAuth2Adapter,
        OAuth2CallbackView,
        OAuth2LoginView,
    )
    import requests
    from django.conf import settings
    from dj_rest_auth.registration.serializers import (
        SocialAccountSerializer, SocialConnectSerializer,     VerifyEmailSerializer,
    )
    from BackendApp.models import EndUser
    from BackendApp.auth_serializers import SocialLoginSerializer
    import logging
    
    class GoogleOAuth2Adapter(OAuth2Adapter):
        provider_id = GoogleProvider.id
        access_token_url = "https://accounts.google.com/o/oauth2/token"
        authorize_url = "https://accounts.google.com/o/oauth2/auth"
        profile_url = "https://www.googleapis.com/oauth2/v1/userinfo"
    
        def complete_login(self, request, app, token, **kwargs):
            resp = requests.get(
                self.profile_url,
                params={"access_token": token.token, "alt": "json"},
            )
            resp.raise_for_status()
            extra_data = resp.json()
    # Added these lines below
            login = self.get_provider().sociallogin_from_response(request, extra_data)
            try:
                EndUser.objects.get(email = login.email_addresses[0])
            except ObjectDoesNotExist:
                logger.info("EndUser Doesn't exist, creating a new endUser.")
                endUser = EndUser(
                    email = login.email_addresses[0],
                    endUserType = "",
                    password = "",
                    salt = "",
                )
                endUser.save()
    # End of my new lines
            return login
    
    
    oauth2_login = OAuth2LoginView.adapter_view(GoogleOAuth2Adapter)
    0ddafe7oauth2_callback = OAuth2CallbackView.adapter_view(GoogleOAuth2Adapter)
    
    

    GoogleLogin.py

    # from allauth.socialaccount.providers.google.views import GoogleOAuth2Adapter
    from allauth.socialaccount.providers.oauth2.client import OAuth2Client
    from dj_rest_auth.registration.views import SocialLoginView
    from .SocialLogin import GoogleOAuth2Adapter # Added this line
    from ..models import EndUser
    class GoogleLoginView(SocialLoginView):
    
        adapter_class = GoogleOAuth2Adapter
        callback_url = "http://localhost:8000/"
        client_class = OAuth2Client