3

i'm developing a simple Ruby authentication app with Sinatra and DataMapper.

I have successfully implemented an hashing password method for when the users get registered, but i'm unable to get the authentication route to work, it simply doesn't match the provided password with the hashed version, stored into the DB (MySQL).

After reading a lot of documentation, a lot of questions here on stackoverflow, and more documentation again, i'm here asking for your help.

I've created a simple GET route to try to understand how the BCrypt library works, without storing the password into the db, the purpose of this route is simply to understand how to use the library:

get "/test" do
  password_hash = BCrypt::Password.create("wazz")
  password = "wazz"
  puts password_hash
  if BCrypt::Password.new(password_hash).is_password? password
    status 201
  end
  halt(500, {error: password_hash}.to_json)
end

So basically all i have to do is to send a GET request to /test and all should be done, but it's not, BCrypt::Password.new seems not validating the original password against the hashed one.

Thank you in advance, any help would be very appreciated.

  • I cannot see anything wrong with your code, and if I cut&paste the first part into IRB, it works for me. Could you give more detail - what does "all should be done" mean, i.e. what do you expect to happen for your code snippet, and how are you testing it? What actually happens? NB you could also have `password_hash.is_password?( password )` as the test – Neil Slater Mar 12 '15 at 10:07
  • Oh, hang on, when the password matches ok you call `status 201`, then halt with the status set back to 500 . . . so this code always halts with a server error, irrespective of what happened to the password. Nothing wrong with bcrypt, just you need to invert the logic in the Sinatra route – Neil Slater Mar 12 '15 at 10:13
  • What am i expecting to happen is that if a send a GET request to the /test route, it will generate an hash of the "wazz" password, and than compares the hash with the original password, giving me a 201 status. – Axel Fooley Mar 12 '15 at 10:14
  • Thank you neil, i knew that the solution was in front of my nose and i was not seeing it :) i changed the code moving the halt inside an "else" statement into "if password_hash.is_password?( password )". Thank you so much, now it works. – Axel Fooley Mar 12 '15 at 10:16

1 Answers1

2

Your use of bcrypt works, but the program flow is wrong. Most importantly, the call to status 201 does not exit from the controller at that point, it continues on, so you have set things up so that whether or not the bcrypt works is irrelevant.

Do something like this instead:

get "/test" do
  password_hash = BCrypt::Password.create("wazz")
  password = "wazz"

  unless BCrypt::Password.new(password_hash).is_password? password
    halt(500, {error: password_hash}.to_json)
  end

  status 201
  {message: 'Session created'}.to_json
end
Neil Slater
  • 26,512
  • 6
  • 76
  • 94