cra
mr

Making Django 1.5 compatible with django-bcrypt

You're viewing an archived post which may have broken links or images. If this post was valuable and you'd like me to restore it, let me know!

Last night I took the opportunity to upgrade all of getsentry.com to Django 1.5. While most things were fairly trivial to sort out, we hit one less obvious (and pretty critical) bug during the migration surrounding django-bcrypt.

This bug would only present itself if you’ve transitioned from older versions of Django, and therefore have passwords in the database using the custom algorithm. Specifically, you’ll have passwords in your user’s table that look something like bc$$somestring$12$somestring.

The fix is actually fairly simple, and just requires you to define a slightly custom legacy backend for django-bcrypt:

from django.contrib.auth.hashers import BCryptPasswordHasher


class DjangoBCryptPasswordHasher(BCryptPasswordHasher):
    """
    Handles legacy passwords which were hashed with the 'bc$' algorithm via
    django-bcrypt.
    """
    algorithm = "bc"

Once you’ve defined the backend, the rest is as simple as adding it to your list of password hashers:

PASSWORD_HASHERS = (
    'django.contrib.auth.hashers.PBKDF2PasswordHasher',
    'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
    'django.contrib.auth.hashers.BCryptPasswordHasher',
    'getsentry.utils.auth.DjangoBCryptPasswordHasher',
    'django.contrib.auth.hashers.SHA1PasswordHasher',
    'django.contrib.auth.hashers.MD5PasswordHasher',
)

Update: As pointed out by @chrisstreeter it’s also fairly trivial to do a data migration: https://gist.github.com/streeter/5534008