Django and Google OAuth — limiting to certain users

I recently started a Django project that used django-allauth to perform authentication based on Google accounts. One problem I encountered was how to limit who can actually log into the site. I didn’t want anyone with a Google account to be able to log in!

Google’s API does have provisions to limit only certain users from passing the authentication, but it only works during the testing phase of your API. The feature wasn’t meant for production, and is limited to 100 users. On top of that, I wanted my Google API to be a set-and-forget experience. I didn’t want the inconvenience of having to log into my Google API console just to allow a new user — there had to be a way to do it on the Django side.

The solution wasn’t that complicated at all, and I wanted to share it here in case it helps anyone else.

In your settings.py, add a line for ALLOWED_EMAILS:

ALLOWED_EMAILS=[
'none@none.com',
'example@example.com',
'me@me.com',
]

Basically, all you want to do is check the request.user.email against this list.

How I chose to implement it:

It’s probably easier to digest from bottom-to-top. The @user_passes_test(email_check) decorator will only allow users whose emails match ALLOWED_EMAILS to view the index view. Otherwise, it kicks the user back to the login view (more on that in a second).

The email_check function basically returns true is the email is found in the list, and returns false otherwise. The split up false statements was just to make it more readable for myself. If the user is anonymous, then they won’t have user.email and so I’m trying to catch that case before a “field does not exist” error is thrown. There are probably more Pythonic ways to do it — feel free to tell me yours in the comments!

Finally, the login() view has to catch the user if they got bounced by another view (such as index). If the user got bounced back to the login view by the @user_passes_test(email_check) decorator, then they are “authenticated” (as far as Google OAuth and Django session cookies are concerned), but they are not allowed based on their email — so we generate a messages.error() to let them know. In any case (authenticated-but-bounced, or not authenticated at all), we render the login.html page with a “Login with Google” button.

I hope this helps somebody! Feel free to share any improvements or corrections in the comments!

Tech junkie, entrepreneur dreamer, practical engineer