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:
- changing the passwords in the database; or
- 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'
]
# …
Source:stackexchange.com