We’ve all been in this situation. And for me personally, I would steer away from the site that forces me to register just to see some part of forum or similar. Mostly this is because I don’t want to provide my details and follow lengthy registration process.
I don’t mind to have an account (even though I forget about the website next day), but the whole process of typing in all the stuff, deciphering captcha images, logging in to my email account just to confirm registration, etc, etc. Why don’t they use OpenId? These days if you have Yahoo or Gmail account (and just who doesn’t?) you can use them to login to all websites that support OpenId.
In a nutshell, OpenId is a decentralised authentication standard. User (U) who has an OpenId account with a trusted company (C) wants to login to a website (W). W prompts with a login screen. U enters his/her OpenId URL (no personal information here provided at all). W then redirects to C login screen, where U is prompted to allow access to some parts of the information (usually it’s username only, sometimes email). If U is happy to provide this information, he then clicks login button and information is passed back to W. In this scenario, W will never get any personal information about U without explicit permission. And U benefits from having only one login that works for all websites.
Below is a simple diagram that shows how authentication is done when using OpenId to login to the websites:

Authentication with OpenID flow
Unfortunately Django does not have native support for OpenId, and their website recommends using django-authopenid library to perform authentication and login using OpenId.
Install required libraries
You need to install python-openid library first. Installation is a breeze, however there seems to be some issues with internal version number in the package, but let’s assume it’s all fine:
# easy_install python-openid Searching for python-openid Reading http://pypi.python.org/simple/python-openid/ Reading http://openidenabled.com/python-openid/ Reading http://www.openidenabled.com/openid/libraries/python/ Best match: python-openid 2.2.4 Downloading http://openidenabled.com/files/python-openid/packages/python-openid-2.2.4.zip Processing python-openid-2.2.4.zip Running python-openid-2.2.4/setup.py -q bdist_egg --dist-dir /tmp/easy_install-Xyxx61/python-openid-2.2.4/egg-dist-tmp-oexXVf zip_safe flag not set; analyzing archive contents... Adding python-openid 2.2.4 to easy-install.pth file Installed /usr/lib/python2.5/site-packages/python_openid-2.2.4-py2.5.egg Processing dependencies for python-openid Finished processing dependencies for python-openid # python Python 2.5.1 (r251:54863, Jul 31 2008, 23:17:43) [GCC 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> openid.__version__ '2.2.1' >>> openid.__path__ ['/usr/lib/python2.5/site-packages/python_openid-2.2.4-py2.5.egg/openid'] >>> openid.version_info (2, 2, 1) >>>
Then install django-authopenid. Installation seems to spit out some errors, but I guess these can be ignored as they don’t seem to cause any issues:
# easy_install django-authopenid
Searching for django-authopenid
Reading http://pypi.python.org/simple/django-authopenid/
Reading http://hg.e-engura.org/django-authopenid/
Reading http://code.google.com/p/django-authopenid/
Best match: django-authopenid 1.0.1
Downloading http://pypi.python.org/packages/source/d/django-authopenid/django-authopenid-1.0.1.tar.gz#md5=93d44b4ce40de55bed36c9ed292adb49
Processing django-authopenid-1.0.1.tar.gz
Running django-authopenid-1.0.1/setup.py -q bdist_egg --dist-dir /tmp/easy_install-UtVC7d/django-authopenid-1.0.1/egg-dist-tmp-oWjnYf
warning: no files found matching 'CHANGES.MD'
Sorry: TypeError: ('compile() expected string without null bytes',)
...
Adding django-authopenid 1.0.1 to easy-install.pth file
Installed /usr/lib/python2.5/site-packages/django_authopenid-1.0.1-py2.5.egg
Processing dependencies for django-authopenid
Finished processing dependencies for django-authopenidPrepare Django application environment
There are several things you’d need to do:
- Create directory for application files
- Create directory for static content such as JS, CSS, HTML and images
- If you are using Apache web server add Virtual host definition and specify where web root is and when to pass control to mod_python module (note that all requests that do not start with /static/ will be passed to Django):
- Also create database and configure appropriately in settings.py.
- Enable administration application for Django
I will use /var/app/application/ in this example
I will use /var/www/application/ in this example
ServerName test.example.com
DocumentRoot /var/www/application/
ErrorLog /var/log/apache2/application-error.log
CustomLog /var/log/apache2/application-access.log combined
SetHandler mod_python
PythonHandler django.core.handlers.modpython
PythonPath sys.path+['/var/app/']
SetEnv DJANGO_SETTINGS_MODULE application.settings
SetEnv PYTHON_EGG_CACHE /tmp
<Location "/static/">
SetHandler None
</Location>
Enable OpenID support
These were the basic steps to get your Django environment set-up, now let’s enable OpenID module:
- In settings.py add OpenID middleware, application and also tell Django where to find templates
- In urls.py just include urls from django_authopenid package:
- Add the following context processors list (majority is what’s loaded by default anyway, you just need to add one line, but since it’s a tuple, you cannot modify it, so you must redefine it):
TEMPLATE_CONTEXT_PROCESSORS = ( 'django.core.context_processors.auth', 'django.core.context_processors.debug', 'django.core.context_processors.i18n', 'django.core.context_processors.media', 'django.core.context_processors.request', 'django_authopenid.context_processors.authopenid', )
- Copy templates from the examples folder. Of course you’ll want them eventually to be fully integrated with your site, so that they match styles or even be incorporated in other pages, but for now, let’s just use the ones provided with the package. Location of the example templates obviously depends on your Linux distribution. On my Debian installation it was in /usr/lib/python2.5/site-packages/django_authopenid-1.0.1-py2.5.egg/example/templates. Copy examples/ directory to your Django application directory.
MIDDLEWARE_CLASSES = ( ... 'django_authopenid.middleware.OpenIDMiddleware', ) INSTALLED_APPS = ( ... 'django_authopenid', 'registration', ) LOGIN_URL = "/account/signin/" TEMPLATE_DIRS = ( ... os.path.join(os.path.dirname(__file__), 'templates') )
urlpatterns = patterns('', ... (r'^account/', include('django_authopenid.urls')), )
Test it
Once you’re done, test it. Navigate to http:///account/signin/ and if you followed this manual you should see something like this:

Django authopenid login screen
You may wonder what the login prompt on the left side is doing there. This is because Django authopenId logoc is to associate your OpenId account with local account and use standard Django “registration” middleware classes to handle all user management functions. If user does not exist – after you have selected your OpenID URL you will be asked to provide local username. You don’t need to memorise nor use it – it’s just to allow authopenId create association.
This may feel bit unintuitive, and I don’t particularly like this. I’m going to make some changes so that internal association is hidden from the end user and happens behind the scenes. This way my users are going to see only OpenId selector and login screen.
Related posts:
Nice write up, thanks for that!
Just wanted to say that your selection of front page pictures for articles is spot on!
thanks!
Thanks for the tutorial, I think I’ll apply this to my future projects.