So I have wanted a good solution to OpenID authentication in my Django projects for a while now. I had been hearing good things about django-alluth for a little while and it seems that this project had the most traction currently. This presentation was especially useful in making me opt for Django-alluth: https://speakerdeck.com/tedtieken/signing-up-and-signing-in-users-in-django-with-django-allauth
In hindsight I would say that setting up django-allauth for a new project is quite easy, though it did take me a couple of hours of trial and error to get it right. This post is intended to remind me how I did it and maybe help others.
One of the biggest head-scratchers came right at the beginning. Namely, how do I install this thing?? To be honest I’m still not sure I did this correctly.
So first I set my virtualenv, pip installed what I needed and started a new Django project. Aside from my ‘essentials’ (django-extensions, django-debug-toolbar etc.), I pip installed django-allauth, which has it’s own dependencies.
1. So, much like my previous go-to for authentication, django-registration, this package has it’s own templates which will inevitably require customization at some point. So my solution was to grab the django-allauth source code from github and copy just the templates directory into my_project/allauth/. The allauth/ directory is completely empty except for the templates/ directory. This seems to work, and means that I am free to customize those templates as part of my project.
2. Now with django-allauth installed I need to set it up in Django. From my point of view this comprises essentially two setup paths. One, in the Django code so that allauth can function, and the other via the Django admin to setup the various APIs. The second one may seem optional, but without any social app APIs set, there will be no social login, so I would deem it pretty much essential.
So the Django code configuration steps run like this:
Note: more expansive details on this section can be found here.
a) Add the following to settings.py:
TEMPLATE_CONTEXT_PROCESSORS = ( ... "django.core.context_processors.request", "allauth.account.context_processors.account", "allauth.socialaccount.context_processors.socialaccount", ... ) AUTHENTICATION_BACKENDS = ( ... "django.contrib.auth.backends.ModelBackend", "allauth.account.auth_backends.AuthenticationBackend", ... ) INSTALLED_APPS = ( ... 'allauth', 'allauth.account', 'allauth.socialaccount', # ... include the providers you want to enable: 'allauth.socialaccount.providers.bitly', 'allauth.socialaccount.providers.dropbox', 'allauth.socialaccount.providers.facebook', 'allauth.socialaccount.providers.github', 'allauth.socialaccount.providers.google', 'allauth.socialaccount.providers.linkedin', 'allauth.socialaccount.providers.openid', 'allauth.socialaccount.providers.persona', 'allauth.socialaccount.providers.soundcloud', 'allauth.socialaccount.providers.stackexchange', 'allauth.socialaccount.providers.twitch', 'allauth.socialaccount.providers.twitter', 'allauth.socialaccount.providers.vimeo', 'allauth.socialaccount.providers.vk', 'allauth.socialaccount.providers.weibo', ... )
b) Add the aullauth/templates directory to TEMPLATE_DIRS. I have recently started using Unipath, after reading the excellent Two Scoops of Django book.
from unipath import Path # the number you use as an argument for ancestor may vary # depending on where your settings.py is located. # I have mine in a settings module # (e.g. my_project/settings/base.py). PROJECT_DIR = Path(__file__).ancestor(3) TEMPLATE_DIRS = ( ... PROJECT_DIR.child("allauth").child("templates"), ... )
c) Add /accounts to the project urls.py
urlpatterns = patterns('', ... (r'^accounts/', include('allauth.urls')), ... )
d) Now do an initial syncdb. Becasue I want to build all tables initially, I did:
./manage.py syncdb --all
3. So now Django is setup to play nice with django-alluth, I can jump into the django admin and start configuring my app APIs. This should mirror the providers in the INSTALLED_APPS tuple of the settings.
Personally I wanted Google and LinkedIn logins, so I set about obtaining credentials for each of these:
Though the interface for registering apps vary, for our purposes we need just a couple of variables:
Client ID: something along the lines of Client ID or API key
Secret Key: the secret key part
These details can be added at localhost:8000admin/socialaccount/socialapp/
I also had to swap out the default site (www.example.com) for localhost:8000 (or wherever the devserver is using), and add it to ‘chosen sites’.
Hey presto! I can now log in using my LinkedIn or Google credentials.