Mixing OpenID into Django's authentication system

Posted by Ross Poulton on Mon 20 August 2007 #geeky #django #programming #openid #archived
From the archive. This post is old. It may be technically incorrect, or it may no longer reflect my current views, projects, or circumstances. I'm leaving it up for posterity, but treat anything in it as out of date.

NOTE: This code is now outdated, and it's certainly not the best way to do OpenID in Django. I recommend you take a look at django-authopenid, a fantastic registration system that combines Django's authentication framework with OpenID sign-in. Ross, 17th April 2008

According to the OpenID website, from a consumers point of view OpenID is "the elimination of multiple user names and passwords and a smoother, more secure, online experience. ". What it provides is a single identity for you to use at multiple websites. Instead of having a username and password for each website you peruse, you have an identity (usually a URL to your blog or an OpenID provider) that you use to login. The only password you have to remember is that of your OpenID provider - and you don't have to provide your password to any websites you visit.

Simon Willison has been a fantastic campaigner for OpenID, especially for integration with Django. He's written the fantastic django-openidconsumer package which provides the framework for a Django Application to act as an OpenID consumer (that is, people login to your Django app using their OpenID).

Simon's package creates a new OpenID object within your application, but is unrelated to the existing authentication system. So what I've done is mixed some glue to pull together these fantastic standalone applications:

The 'glue' provides a useful process flow for new users to your website. It lets people register with a username/password as they would have before OpenID, lets people login with OpenID's, and keeps it all intertwined. The basic functions are as follows:

  • A new user can sign up with a username/password, using django-registration
  • A new user can enter an OpenID, which is authenticated before creating a standard Django user. The account is verified using django-registration's email checker.
  • A user who is already logged in with a username/password, can login again using an OpenID, which is automatically associated with their username
  • A user can login with either their username/password (if they have one), or with their OpenID(s) (if they have any), and you'll always see them as 'request.user' - the same as if they had signed up with a username/password
  • This gives users a choice when they sign up and lets them change their mind by adding or removing OpenID's from their account as they wish.
  • Why do e-mail verification when users sign up with an OpenID? Because OpenID doesn't guarantee a users identity. It's merely a replacement for a username & password. E-Mail verification helps cut down on automated registrations, and ensures users are providing you with a valid contact address.

How would I use this in the real world? For sign-ups, I would show one form, clearly divided, asking a user to enter their OpenID if they have one, or otherwise enter their username/password/e-mail address. For logins, show users a username/password box with a link to toggle an OpenID entry field. If the user logs in with an OpenID, set a cookie so you can remember them in the future, showing them the OpenID login by default rather than the Username-driven login. Make it as easy as possible for people to adopt this fantastic technology.

I'm not using this code in a live environment yet, as it needs more testing. However, I've put a testbed online and made the source code available.

I would love it if you could try out this code both on my server and on yours, and provide feedback on the flow from a users point of view. I plan on cleaning up the code significantly before packaging it into something that is safe to use in a production environment.

The online demo is at http://openid.rossp.org. There is a link to the source code there.

Note: The database isn't accessible via the web, and it's a database set up specifically for this demonstration. I will NOT be extracting lists of usernames, passwords, e-mail addresses, openid's, etc. I may pu tup some usage statistics later, but certainly nothing identifiable. Please feel safe using this.


Buy Me A Coffee

Did you find this post interesting or helpful? Show your appreciation by buying me a beer or a coffee!