django allauth facebook redirects to signup when retrieved email matches an existing user's email?

前端 未结 1 1128
无人及你
无人及你 2021-01-31 05:02

I am successfully able to login via Google and Facebook using Django (1.6.4) and allauth (0.16.1) and Python (2.7) with expected redirect to settings.LOGIN_REDIRECT_URL in case

相关标签:
1条回答
  • 2021-01-31 05:47

    I have solved it after digging in deep into google and source code of django and django-allauth

    Problem being solved: I just want the ability to interchangeably login using facebook and google with same email id and always redirect to LOGIN_REDIRECT_URL after successful login, but django-allauth doesn't let me do that. Instead, it presents me with a signup page which I don't want.

    Solution:: Use @receiver(pre_social_login) to call a function link_to_local_user() which logs in 1st and then raises ImmediateHttpResponse which in turn redirects to LOGIN_REDIRECT_URL

    #! myproject.adapter.py
    from allauth.account.adapter import DefaultAccountAdapter
    from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
    from allauth.exceptions import ImmediateHttpResponse
    from allauth.socialaccount.signals import pre_social_login
    from allauth.account.utils import perform_login
    from allauth.utils import get_user_model
    from django.http import HttpResponse
    from django.dispatch import receiver
    from django.shortcuts import redirect
    from django.conf import settings
    import json
    
    
    class MyLoginAccountAdapter(DefaultAccountAdapter):
        '''
        Overrides allauth.account.adapter.DefaultAccountAdapter.ajax_response to avoid changing
        the HTTP status_code to 400
        '''
    
        def get_login_redirect_url(self, request):
            """ 
            """
            if request.user.is_authenticated():
                return settings.LOGIN_REDIRECT_URL.format(
                    id=request.user.id)
            else:
                return "/"
    
    
    class MySocialAccountAdapter(DefaultSocialAccountAdapter):
        '''
        Overrides allauth.socialaccount.adapter.DefaultSocialAccountAdapter.pre_social_login to 
        perform some actions right after successful login
        '''
        def pre_social_login(self, request, sociallogin):
            pass    # TODOFuture: To perform some actions right after successful login
    
    @receiver(pre_social_login)
    def link_to_local_user(sender, request, sociallogin, **kwargs):
        ''' Login and redirect
        This is done in order to tackle the situation where user's email retrieved
        from one provider is different from already existing email in the database
        (e.g facebook and google both use same email-id). Specifically, this is done to
        tackle following issues:
        * https://github.com/pennersr/django-allauth/issues/215
    
        '''
        email_address = sociallogin.account.extra_data['email']
        User = get_user_model()
        users = User.objects.filter(email=email_address)
        if users:
            # allauth.account.app_settings.EmailVerificationMethod
            perform_login(request, users[0], email_verification='optional')
            raise ImmediateHttpResponse(redirect(settings.LOGIN_REDIRECT_URL.format(id=request.user.id)))
    
    
    #! settings.py
    ACCOUNT_AUTHENTICATION_METHOD = "email" # Defaults to username_email
    ACCOUNT_USERNAME_REQUIRED = False       # Defaults to True
    ACCOUNT_EMAIL_REQUIRED = True           # Defaults to False
    SOCIALACCOUNT_QUERY_EMAIL = ACCOUNT_EMAIL_REQUIRED
    SOCIALACCOUNT_AUTO_SIGNUP = True
    SOCIALACCOUNT_EMAIL_REQUIRED = False
    ACCOUNT_ADAPTER = "myproject.adapter.MyLoginAccountAdapter"
    SOCIALACCOUNT_ADAPTER = 'myproject.adapter.MySocialAccountAdapter'
    LOGIN_URL = "/"
    LOGIN_REDIRECT_URL = "/users/{id}/mytags"
    
    0 讨论(0)
提交回复
热议问题