diff --git a/apps/patchwork/context_processors.py b/apps/patchwork/context_processors.py
index f4ab5a9..b458eef 100644
--- a/apps/patchwork/context_processors.py
+++ b/apps/patchwork/context_processors.py
@@ -17,9 +17,9 @@
 # along with Patchwork; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
+from django.conf import settings
 
 from patchwork.models import Bundle
-from patchwork.utils import order_map, get_order
 
 def bundle(request):
     user = request.user
@@ -28,5 +28,5 @@ def bundle(request):
     return {'bundles': Bundle.objects.filter(owner = user)}
 
 
-def patchlists(request):
-
+def login_url(request):
+    return dict(login_url=settings.LOGIN_URL)
diff --git a/apps/patchwork/forms.py b/apps/patchwork/forms.py
index 1c5aeef..72c2c42 100644
--- a/apps/patchwork/forms.py
+++ b/apps/patchwork/forms.py
@@ -45,9 +45,11 @@ class RegistrationForm(RegistrationFormUniqueEmail):
         user.last_name = self.cleaned_data.get('last_name', '')
         user.save()
 
-	# saving the userprofile causes the firstname/lastname to propagate
-	# to the person objects.
-	user.get_profile().save()
+        # XXX: I think the code below is no longer needed as the signal
+        # handler responsible for creating the UserProfile already saves it.
+        # saving the userprofile causes the firstname/lastname to propagate
+        # to the person objects.
+        user.get_profile().save()
 
         return user
 
diff --git a/apps/patchwork/models.py b/apps/patchwork/models.py
index 6842622..3ee007f 100644
--- a/apps/patchwork/models.py
+++ b/apps/patchwork/models.py
@@ -18,6 +18,7 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
 from django.db import models
+from django.db.models.signals import post_save
 from django.contrib.auth.models import User
 from django.core.urlresolvers import reverse
 from django.contrib.sites.models import Site
@@ -126,8 +127,8 @@ class UserProfile(models.Model):
             person.save()
         else:
             for person in people:
-                 person.link_to_user(self.user)
-                 person.save()
+                person.link_to_user(self.user)
+                person.save()
 
     def __str__(self):
         return self.name()
@@ -400,3 +401,9 @@ class UserPersonConfirmation(models.Model):
         super(UserPersonConfirmation, self).save()
 
 
+def register_userprofile(sender, **kwargs):
+    if kwargs['created']:
+        UserProfile(user=kwargs['instance']).save()
+
+
+post_save.connect(register_userprofile, User)
diff --git a/apps/patchwork/tests/utils.py b/apps/patchwork/tests/utils.py
index a85e168..819e5b9 100644
--- a/apps/patchwork/tests/utils.py
+++ b/apps/patchwork/tests/utils.py
@@ -59,10 +59,6 @@ def create_user():
 
     user = User.objects.create_user(userid, email, userid)
     user.save()
-
-    profile = UserProfile(user = user)
-    profile.save()
-
     return user
 
 def create_maintainer(project):
diff --git a/apps/patchwork/utils.py b/apps/patchwork/utils.py
index fa26aef..ba019e6 100644
--- a/apps/patchwork/utils.py
+++ b/apps/patchwork/utils.py
@@ -200,8 +200,3 @@ def set_patches(user, project, action, data, patches, context):
         context.add_message(str)
 
     return (errors, form)
-
-def userprofile_register_callback(user):
-    profile = UserProfile(user = user)
-    profile.save()
-
diff --git a/apps/settings.py b/apps/settings.py
index 68837b3..32886de 100644
--- a/apps/settings.py
+++ b/apps/settings.py
@@ -69,6 +69,12 @@ ROOT_URLCONF = 'apps.urls'
 
 LOGIN_URL = '/accounts/login'
 LOGIN_REDIRECT_URL = '/user/'
+# If you want to make your Patchwork instance an OpenID relying party, you
+# just need to uncomment the lines below.
+# OPENID_CREATE_USERS = True
+# OPENID_UPDATE_DETAILS_FROM_SREG = True
+# LOGIN_URL = '/openid/login/'
+# OPENID_SSO_SERVER_URL = 'https://login.launchpad.net/'
 
 TEMPLATE_DIRS = (
     # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
@@ -80,7 +86,14 @@ 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.media",
+    "patchwork.context_processors.login_url",
+    )
+
+AUTHENTICATION_BACKENDS = (
+    'django_openid_auth.auth.OpenIDBackend',
+    'django.contrib.auth.backends.ModelBackend',
+)
 
 AUTH_PROFILE_MODULE = "patchwork.userprofile"
 
@@ -90,6 +103,7 @@ INSTALLED_APPS = (
     'django.contrib.sessions',
     'django.contrib.sites',
     'django.contrib.admin',
+    'django_openid_auth',
     'patchwork',
     'registration',
 )
diff --git a/apps/urls.py b/apps/urls.py
index 5c4ac57..de0769e 100644
--- a/apps/urls.py
+++ b/apps/urls.py
@@ -23,17 +23,16 @@ from patchwork.admin import admin_site
 
 from registration.views import register
 from patchwork.forms import RegistrationForm
-from patchwork.utils import userprofile_register_callback
 
 urlpatterns = patterns('',
     # Example:
+    (r'^openid/', include('django_openid_auth.urls')),
     (r'^', include('patchwork.urls')),
 
     # override the default registration form
     url(r'^accounts/register/$',
         register,
-        {'form_class': RegistrationForm,
-         'profile_callback': userprofile_register_callback},
+        {'form_class': RegistrationForm},
         name='registration_register'),
 
     (r'^accounts/', include('registration.urls')),
diff --git a/docs/INSTALL b/docs/INSTALL
index 57e8042..aac619f 100644
--- a/docs/INSTALL
+++ b/docs/INSTALL
@@ -92,6 +92,21 @@ in brackets):
          cd ../python
          ln -s ../lib/packages/django-registration/registration ./registration
 
+        Two other libraries we may use, in case you use OpenID for
+        authentication, are django-openid-auth and the Python OpenID library.
+        The former is named python-django-openid-auth in Debian/Ubuntu and the
+        latter python-openid, but if they're not available in your
+        distribution, you can follow the steps below to get them:
+
+         cd lib/packages
+         wget http://launchpad.net/django-openid-auth/trunk/0.3/+download/django-openid-auth-0.3.tar.gz
+         wget --no-check-certificate https://github.com/openid/python-openid/tarball/2.2.5 -O python-openid-2.2.5.tgz
+         tar zxvf django-openid-auth-0.3.tar.gz
+         tar zxvf python-openid-2.2.5.tgz
+         cd ../python
+         ln -s ../packages/django-openid-auth-0.3/django_openid_auth ./django_openid_auth
+         ln -s ../packages/openid-python-openid-b666238/openid ./openid
+
         We also use some Javascript libraries:
 
          cd lib/packages
diff --git a/templates/base.html b/templates/base.html
index ec0204d..365200e 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -28,7 +28,7 @@
      <a href="{% url patchwork.views.user.profile %}">profile</a> ::
      <a href="{% url auth_logout %}">logout</a>
 {% else %}
-     <a href="{% url auth_login %}">login</a>
+     <a href="{{ login_url }}">login</a>
      <br/>
      <a href="{% url registration_register %}">register</a>
      <br/>
