django-registration updates
Since announcing its resurrection a couple weeks ago, I’ve been working on django-registration
pretty much continuously. There are over 30 commits since that last post, and I think it’s finally getting close to release quality; what’s left at this point is, I think, mostly stylistic cleanups and editing and pushing some more documentation.
There are a couple big highlights from the past few weeks’ work, and I’d like to take a moment to go over those in a shameless attempt to build up hype and excitement for the forthcoming release.
No more “default” workflow
In the oldest versions of django-registration
, the two-step (signup then activate) workflow using a model to store and check an activation key was the only built-in registration workflow. Later, a second one-step workflow was added, but the two-step model-backed workflow remained the default (and was found in registration.backends.default
to indicate that fact).
As of the forthcoming release, though, it’s no longer called the “default” workflow, and in fact there isn’t officially a default. Imports from registration.backends.default
still work, and will work for at least two releases (1.8, coming soon, plus 1.9 afterward), but then they’ll stop working. Any attempt to import from, or include()
URLs from, registration.backends.default
will now raise a DeprecationWarning
telling you that it’s going to be removed. Going forward, the location to refer to is registration.backends.model_activation
.
The reason for this is simply that the model-activation system is old, and is showing its age. It was the big stumbling block when implementing support for custom User models years ago (though it does work with custom User models, if for some reason you want that), and it really reflects the state of Django as it existed way back in 2007 when django-registration
was first written.
So although it continues to be bundled with django-registration
, and will continue to be supported (in its new, non-“default” home within the codebase), the model-based activation system needs to give way to something a bit more modern. Which is…
The HMAC activation workflow
One of the great things about actually updating my various apps is that I get a chance to use nice new features that show up in modern versions of Django. One of the really interesting ones, originally introduced in Django 1.4, is the cryptographic signing framework. This provides easy, sane support for HMAC-verified values in Django applications. And as it turns out, the key used to activate an account is a pretty good place to take advantage of that.
The new workflow using HMAC lives in registration.backends.hmac
, and it implements the same two-step process (sign up, then activate) as the former “default” model-based system, but does so without having to store the activation key. This is handy because it means there are no models required, and especially no foreign keys to the User model required. In fact, you can use it without adding registration
to your INSTALLED_APPS
(and the documentation explicitly encourages you not to put registration
in INSTALLED_APPS
unless you’re using the model-based system).
The process is extremely simple:
- User signs up, an inactive account is created from the username/email/password supplied during registration.
- Django’s
TimestampSigner
is used to sign the username. This value becomes the activation key, and is put into a link emailed to the user. - When the user clicks the link, the activation process validates the key (again using
TimestampSigner
), checking both the HMAC and that the timestamp is within the permitted activation window, and if validation succeeds the account is activated.
The code to do this is also pretty simple. In fact, there’s about as much code involved in custom User support as in using Django’s signing tools.
Odds and ends
The HMAC activation code is still slightly in flux as I figure out exactly what API I want those views to have (since it’d be nice, if other useful cryptographic signing implementations crop up, to be able to just subclass the HMAC views and override a couple things to take advantage), but as of this weekend I think it’s mostly stable.
So my focus going forward is going to be on documentation updates; the documentation for django-registration
is mostly OK, but there are still areas where I think it could and should be better. Once it’s in a state I feel slightly more comfortable with, I’ll probably cut a preview package and invite people to poke at it before doing a final release. And then django-registration
will be up-to-date and will stay that way for the foreseeable future.