[Answered ]-Django hash integrate with legacy database

1👍

Django first specifies the hashing algorithm that is used, since it can for example use different hashing algorithms for each user.

There are basically two ways to solve this:

  1. changing the passwords in the database; or
  2. make a (slightly) different authentication backend that will prepend it with the password.

Option 1: update the password

You can update the records in bulk with:

from django.db.models import F, Value
from django.db.models.functions import Concat

MyModel.objects.update(
    password=Concat(Value('bcrypt$'), F('password'))
)

This will thus update the password field (if the passwords are stored in another field, you use that field name) by prepending 'bcrypt$' to the hashes.

Option 2: make a custom authentication method

We can subclass the ModelBackend and slightly rewrite this to:

# app_name/backends.py

django.contrib.auth.backends import ModelBackend

class MyModelBackend(ModelBackend):

    def authenticate(self, request, username=None, password=None, **kwargs):
        if username is None:
            username = kwargs.get(UserModel.USERNAME_FIELD)
        if username is None or password is None:
            return
        try:
            user = UserModel._default_manager.get_by_natural_key(username)
        except UserModel.DoesNotExist:
            # Run the default password hasher once to reduce the timing
            # difference between an existing and a nonexistent user (#20760).
            UserModel().set_password(password)
        else:
            if user.password.startswith('bcrypt'):
                u = user
            else:
                u = UserModel(password=f'bcrypt_sha256${user.password}')
            if u.check_password(password) and self.user_can_authenticate(user):
                return user

We can then register this backend in the AUTHENTICATION_BACKENDS [Django-doc]:

# settings.py

# …

AUTHENTICATION_BACKENDS = [
    'app_name.backends.MyModelBackend',
    'django.contrib.auth.backends.ModelBackend'
]

# …

Leave a comment