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

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


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 asocial 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 byraising an ImmediateHttpResponseWhy both an adapter hook and the signal? Intervening ine.g. the flow from within a signal handler is bad -- multiplehandlers may be active and are executed in undetermined order.

Do something like

from allauth.socialaccount.adaptor import DefaultSocialAccountAdapterclass 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.


Here's an alternate solution:

from allauth.account.adapter import DefaultAccountAdapterfrom allauth.socialaccount.adapter import DefaultSocialAccountAdapterclass CustomAccountAdapter(DefaultAccountAdapter):    def is_open_for_signup(self, request):        return False # No email/password signups allowedclass 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'


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 itALLOWED_DOMAIN = 'example.com'

.

# forms.pyfrom django.conf import settingsfrom allauth.socialaccount.forms import SignupFormclass 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.pyfrom allauth.socialaccount.views import SignupViewfrom .forms import MySignupFormurlpatterns = patterns('',    # ...    url(r"^social/signup/$", SignupView.as_view(form_class=MySignupForm), name="account_signup"),    # ...)

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