简体   繁体   中英

Ruby on Rails Devise encrypted password read from C# .NET

We have a Ruby on Rails app that uses the Devise gem for user handling, including creating and authenticating user passwords. The passwords are encrypted in the MySQL database obviously. We are using Devise defaults for how it encrypts the password. Now we have another small same-LAN side app that (a C# ASP.NET app) needs to authenticate with a user/password directly with the database to do some read-only operations.

How can we best mimic what Devise does for user/password authentication in the C# ASP.NET app against the very same data in the MySQL database?

Essentially, I need to figure out how to recreate Devise's valid_password? method in C# .NET

http://www.rubydoc.info/github/plataformatec/devise/Devise/Models/DatabaseAuthenticatable#valid_password%3F-instance_method

# File 'lib/devise/models/database_authenticatable.rb', line 46

def valid_password?(password)
  return false if encrypted_password.blank?
  bcrypt   = ::BCrypt::Password.new(encrypted_password)
  password = ::BCrypt::Engine.hash_secret("#{password}#{self.class.pepper}", bcrypt.salt)
  Devise.secure_compare(password, encrypted_password)
end

I think I understand the question correctly. What you want to do is authenticate a user on you .NET application using the credentials on your rails application. If so, I would suggest implementing an oauth server on the ruby side and a client in you .NET code. As for the server you have several gems that provide this functionality including

  1. oauth-ruby
  2. doorkeeper
  3. oauth2-provider

Devise uses BCrypt for password storage, and so thankfully the verification process is fairly simple. Install the BCrypt.Net NuGet package (or any other BCrypt implementation), and then do this:

public static bool ValidPassword(string userSuppliedPassword, string hashedAndSaltedPassFromDatabase)
{
    return BCrypt.Net.BCrypt.Verify(userSuppliedPassword, hashedAndSaltedPassFromDatabase);
}

I was having a similar requirement of verifying already existing users from the C# application.

I used package bcrypt.net - next for BCrypt.

Here is the code snippet which I used

static void Main(string[] args)
    {
        const string DEVISE_PEPPER = "Here comes the devise pepper value";

        // One pass
        string pass = "reE8TuLcZ44XwRz";
        const string passHash = "$2a$10$1Rm.BC0hnF1laC7MFJ/B0eFu2rtG1Asy6fRqJVdqcfBO6LASn4Nqa";

        // Second pass
        const string secondPass = "FpRfaaqzNNRAum9";
        const string secondPassHash = "$2a$10$/Ex4x9LkvxIncaXhByqVP.YRdwRlZFJ7p4H96BfqHk1oGmw3YwLMC";

        // How Ruby BCyrpt verify? Ref - https://www.freecodecamp.org/news/how-does-devise-keep-your-passwords-safe-d367f6e816eb/
        // 1. Fetch the input password
        // 2. Fetch the salt of the stored password
        // 3. Generate the hash from the password and salt using the same bcrypt version and cost factor 
        // 4. Check if the stored hash is the same one as the computed on step 3

        // Ref - https://github.com/heartcombo/devise/blob/5d5636f03ac19e8188d99c044d4b5e90124313af/lib/devise/encryptor.rb#L14
        var finalPass = $"{secondPass}{DEVISE_PEPPER}";

        var verified = BCrypt.Net.BCrypt.Verify(finalPass, secondPassHash);
        var verifiedTxt = verified ? "verified!" : "didn't verified.";
        
        Console.WriteLine($"Password and hash {verifiedTxt}");

        Console.ReadKey();
    }

I was successfully able to verify the password.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM