After upgrading from Django 1.2.7 to Django 1.4.3, we had a problem where users were unable to log in.
This was due to an upgrade in the crypto algorithms used to store passwords.
When a user attempts to log in, the authentication process checks the "password" field in the User table.
The password field contains 3 components: algorithm$salt$hash
The algorithm is used to determine which crypto to use. The salt is a randomly generated salt upon setting of password, which in this case is an empty string "".
For now, you can temporarily fix this error by adding a new file "working_unsalted\hasher.py".
from django.contrib.auth.hashers import UnsaltedMD5PasswordHasher
from django.utils.crypto import constant_time_compare
class WorkingUnsaltedMD5PasswordHasher(UnsaltedMD5PasswordHasher):
"""
The default UnsaltedMD5PasswordHasher uses constant_time_compare(), but passes it the wrong values.
"""
algorithm = "working_unsalted_md5"
def verify(self, password, encoded):
encoded_2 = self.encode(password, '')
return constant_time_compare(encoded[22:], encoded_2)
In your settings file, be sure to define the new hasher.
PASSWORD_HASHERS = (
'django.contrib.auth.hashers.BCryptPasswordHasher',
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.SHA1PasswordHasher',
'django.contrib.auth.hashers.UnsaltedMD5PasswordHasher',
'django.contrib.auth.hashers.MD5PasswordHasher',
'django.contrib.auth.hashers.CryptPasswordHasher',
'working_unsalted.hashers.WorkingUnsaltedMD5PasswordHasher',
)
Lastly, change the algorithm in the database by changing auth_user.password values from "md5$..." to "working_unsalted_md5$...". When the user tries to log in, the new hasher will take effect.
I've made a ticket and pull request for this issue, so hopefully it'll be fixed in Django 1.4.4.