I recently had to migrate a users database from a django app to a brand new rails app. Is it possible to do that without having to request all our users to change their passwords ?
As you probably already know, plain-text passwords are not, and should never be stored in your database. When a user sign up, his/her password is hashed before the resulting hash is saved to the database. When signin in, the user given password is hashed again, so both hashes (one is stored, the other is provided during the login process) can be checked against each other.
If you’re working with rails then you probably know about Devise: an awesome authentication solution for rails.
Both django and rails/devise properly hash the users passwords. However the process is not the same, and a django encrypted password will not be recognized by the Devise engine as it is.
The pbkdf2-password-hasher gem
The app I had to deal with uses pbkdf2 encryption algorithm (I’m guessing it is a django standard but I have honestly no idea wether it is or not). The idea is then to teach devise how to check such an encrypted password.
I had some trouble to find something satisfying, so I wrote a gem : pbkdf2-password-hasher to solve this issue. Basically, it implements in ruby the pbkdf2 encryption process, so we can easily check a password against a hashed string:
1 2 3 4 5 6 7 8
To use this gem in your rails application, simply call it from your Gemfile:
bundle install. Now that the gem is installed, we simply need to tell devise how to use it. To do this, let’s override the
valid_password? method on our model.
Let’s say you created a
User model, then simply add
1 2 3 4 5 6 7
to your model’s definition.
And voilà ! Old users can login using their old passwords, whereas new users will still be able to create new accounts, that will be dealt with in the usual devise way.
Isn’t that nice ?