Tapestry to Rails 1: Migrate User authentication from Spring Security to Devise
So, here I am, migrating an application from Tapestry to Rails. First issue I ran into is how to authenticate existing users. The Spring Security setup I used wasn’t to advanced, but still I had to figure out all of the defaults and how to implement them in Ruby.
But first things first, I needed a hash to test against. I setup an user using a simple password (“password”). The resulting hash is “94fd377436677640be814ac7b2d98b219f1f96d4″, encoded by the password and a salt. Ok, for the password, what’s missing is the digest to use and the salt.
To figure out the used encoder, I injected it and output it simply via:
System.out.println(encoder); //org.springframework.security.authentication.encoding.ShaPasswordEncoder
The same I did with the saltSource to figure out which Salt is used all over the system (I did not set up a custom salt, nor user-based salt, shame on me):
System.out.println(saltSource.getSalt(user)); // DEADBEEF
I ended up with the information, that the Encoder used is the SHAPasswordEncoder and a system wide salt of “DEADBEEF”. Looking at the source, the line of interest can be found in BasePasswordEncoder#mergePasswordAndSalt(String password, Object salt, boolean strict):
return password + "{" + salt.toString() + "}";
That can be easily written in Ruby (irb or rails console) as:
require 'digest'
Digest::SHA1.new.hexdigest "password{DEADBEEF}"
=> "94fd377436677640be814ac7b2d98b219f1f96d4"
To be able to use Devise with our old passwords, the solution is to override the “valid_password?” method, as suggested in this Wiki entry.
The above code used, it is now possible to authenticate existing users with Devise and still use all the nifty new features coming with it.