Alternative to the 120k limit on rounds for hashed password imports using auth.UserImportHash.pbkdf2_sha256
I'm looking to migrate users from Django to firebase, below is the code I'm using for testing. The issue I'm facing is that it seems that the passwords have been hashed using 150k rounds when the firebase docs says the maximum is 120k for SHA256: https://firebase.google.com/docs/auth/admin/import-users#python
Is there an alternative?
Here is the error I get:
ValueError: rounds must not be larger than 120000.
import firebase_admin
from firebase_admin import auth, exceptions
from passlib.utils import to_bytes
server_path = ''
fb_credentials = firebase_admin.credentials.Certificate(server_path + 'files/serviceAccount.json')
firebase_admin.initialize_app(fb_credentials)
old_hash = 'pbkdf2_sha256$150000$rsWX3Dbbd3K6$EYgXPBAz/Ero9PIgIFs/8pWGmGT+diTOQs1DZv4Ytjw='
email = '[email protected]'
rounds = int(old_hash.split('$')[1])
salt = old_hash.split('$')[2]
users = [
auth.ImportUserRecord(
uid='70sSUptkmkN95QTFJ0gWduzdlpP1',
email=email,
password_hash=to_bytes(old_hash),
password_salt=to_bytes(salt)
),
]
hash_alg = auth.UserImportHash.pbkdf2_sha256(rounds=rounds)
try:
result = auth.import_users(users, hash_alg=hash_alg)
for err in result.errors:
print('Failed to import user:', err.reason)
except exceptions.FirebaseError as error:
print('Error importing users:', error)
I found a few problems with this issue:
- I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.
- This issue does not seem to follow the issue template. Make sure you provide all the required information.
Hey @FarmboxPierre can you file a support ticket on this issue?
Hey @FarmboxPierre can you file a support ticket on this issue?
Done, thanks. Let's see what happens. I'll keep you posted, the limit in "_user_import.py" might need to be updated.
firebase
Hello @FarmboxPierre, did you find a workaround to migrate your users from django to firebase ?
Hello!
No I didn't get any return from the ticket I filed.
One possible workaround would have been to create a custom form for our user to login, matching against Django's credentials and simultaneously save the new hash of the login to firebase. We decided it was not worth the hustle and just reset our users' passwords.
I just faced the same issue, but seems like Django provides a way to update iterations (aka. rounds)
The PBKDF2 and bcrypt algorithms use a number of iterations or rounds of hashing [...] but you may wish to tune it up or down [...]. To do so, you’ll subclass the appropriate algorithm and override the iterations parameters.
Check this link for details: https://docs.djangoproject.com/en/3.1/topics/auth/passwords/#increasing-the-work-factor
So theoretically you can change rounds back to 12000 with a single migration.
So theoretically you can change rounds back to 12000 with a single migration.
@darekfrynas did you actually manage this? Surely it's impossible (or at least computationally infeasible) to decrease the number of rounds without knowing the original password, so you'd have to wait for the user to login?
I was excited to see that firebase supported many different hashing algorithms for importing users, so this was a really disappointing limitation to run into.
From those same Django docs:
However, as computing power increases, the number of iterations needs to be increased. We’ve chosen a reasonable default (and will increase it with each release of Django)
At least in Django's opinion, 120k stopped being a reasonable default 3 years ago, when they changed it to 150k for the release of Django 2.2. And as promised, they've increased it regularly:
- https://github.com/django/django/commit/06670015f7e55a8be8137dbd95b7f4c536c3782b
- https://github.com/django/django/commit/b5db65c4fbcf05cb03d039166abf115930dc7577
- https://github.com/django/django/commit/f2187a227f7a3c80282658e699ae9b04023724e5
- https://github.com/django/django/commit/a948d9df394aafded78d72b1daa785a0abfeab48
That last commit changed it to 320k a few months ago for Django 4.0.
If Google wants to use fewer rounds to save computing time, I can understand that, but in that case I suggest allowing importing a hash with many rounds and then downgrading it after the user signs in once.
No I didn't get any return from the ticket I filed.
Are firebase tickets all private? Is there no way we can see the ticket or add our own voice?
Here are some more places complaining about this:
- https://stackoverflow.com/questions/65178042/how-to-migrate-django-users-to-firebase-when-the-rounds-are-too-high
- https://www.reddit.com/r/django/comments/cqndz0/export_django_user_to_firebase/
- https://github.com/firebase/firebase-admin-node/issues/1219
The last one says:
Internally tracked at b/184668782
I put in a feature request for this and got this response:
This sounds like a good candidate for a feature request, in fact I've found some other requests in the past and the team is checking for options. As an action, I’ve filed a new request on your behalf, this will increase the priority on this matter since more developers depend on this feature.
Please note that filing a feature request doesn't guarantee its approval, but having more and more developers talking about the same issue is a good way to indicate the severity and importance of this for the community. For now, you can keep an eye out for updates on our official blog and release notes.