django-allauth: Only allow users from a specific google apps domain

后端 未结 3 1161
梦谈多话
梦谈多话 2020-12-16 22:00

I am a newbie at Django. Using django-allauth I have set up single click sign in. I obtained my domain credentials ( client_id and secret_key) from google api console. But t

相关标签:
3条回答
  • 2020-12-16 22:41

    You could do something in the line of overriding allauth's allauth.socialaccount.forms.SignupForm and checking the domain during the signup process. Discalmer: this is all written without testing, but something in the line of that should work.

    # settings.py
    # not necesarry, but it would be a smart way to go instead of hardcoding it
    ALLOWED_DOMAIN = 'example.com'
    

    .

    # forms.py
    from django.conf import settings
    from allauth.socialaccount.forms import SignupForm
    
    
    class MySignupForm(SignupForm):
    
        def clean_email(self):
            data = self.cleaned_data['email']
            if data.split('@')[1].lower() == settings.ALLOWED_DOMAIN:
                raise forms.ValidationError(_(u'domena!'))
            return data
    

    in your urls override allauth defaults (put this before the include of django-allauth)

    # urls.py
    
    from allauth.socialaccount.views import SignupView
    from .forms import MySignupForm
    
    
    urlpatterns = patterns('',
        # ...
        url(r"^social/signup/$", SignupView.as_view(form_class=MySignupForm), name="account_signup"),
        # ...
    )
    

    I'm not sure for the "^social/signup/$", recheck that.

    0 讨论(0)
  • 2020-12-16 22:54

    Here's an alternate solution:

    from allauth.account.adapter import DefaultAccountAdapter
    from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
    
    class CustomAccountAdapter(DefaultAccountAdapter):
        def is_open_for_signup(self, request):
            return False # No email/password signups allowed
    
    class CustomSocialAccountAdapter(DefaultSocialAccountAdapter):
        def is_open_for_signup(self, request, sociallogin):
            u = sociallogin.user
            # Optionally, set as staff now as well.
            # This is useful if you are using this for the Django Admin login.
            # Be careful with the staff setting, as some providers don't verify
            # email address, so that could be considered a security flaw.
            #u.is_staff = u.email.split('@')[1] == "customdomain.com"
            return u.email.split('@')[1] == "customdomain.com"
    

    This code can live anywhere, but assuming it's in mysite/adapters.py, you'll also need the following in your settings.py:

    ACCOUNT_ADAPTER = 'mysite.adapters.CustomAccountAdapter'
    SOCIALACCOUNT_ADAPTER = 'mysite.adapters.CustomSocialAccountAdapter'
    
    0 讨论(0)
  • 2020-12-16 23:03

    Answering my own question-

    What you want to do is stall the login after a user has been authenticated by a social account provider and before they can proceed to their profile page. You can do this with the

    pre_social_login method of the DefaultSocialAccountAdapter class in allauth/socialaccount/adaptor.py

    Invoked just after a user successfully authenticates via a social provider, but before the login is actually processed (and before the pre_social_login signal is emitted). You can use this hook to intervene, e.g. abort the login by raising an ImmediateHttpResponse Why both an adapter hook and the signal? Intervening in e.g. the flow from within a signal handler is bad -- multiple handlers may be active and are executed in undetermined order.

    Do something like

    from allauth.socialaccount.adaptor import DefaultSocialAccountAdapter
    
    class MySocialAccount(DefaultSocialAccountAdapter):
        def pre_social_login(self, request, sociallogin):
            u = sociallogin.account.user
            if not u.email.split('@')[1] == "example.com"
                raise ImmediateHttpResponse(render_to_response('error.html'))
    

    This is not an exact implementation but something like this works.

    0 讨论(0)
提交回复
热议问题