Weird issue with devise valid_password?

For the past 2 hours, I have been trying to debug a weird issue in devise which is not letting me login.

Here's the stuff I'm referring too:

password
=> 'vinodsobale'


password == 'vinodsobale'
=> true


resource.valid_password?(password)


=> false


resource.valid_password?('vinodsobale')


=> true

Attaching the screenshot as well:

enter image description here Note: I have enabled debugger inside devise so the above code is devise internal code.

To me, it looks like a issue in Devise.secure_compare.

4560 次浏览

How about

resource.valid_password?(password.to_s)

I hope it help You.

Devise DatabaseAuthenticatable#valid_password? is using a method called Encryptor::compare it take 2 objects, the current stored password and the new password you want to compare, I believe there is a side effect for this method that modify the second parameter in the middle so it'll modify the object instead of once it'll be modified twice which leads to a false result, so it may work if you passed a duplicated object of password. can you try to use valid_password? password.dup

It could be a problem with the encoding between the original source and your console. If you run password.codepoints, you should be able to see the actual encoding. Running .codepoints on the raw 'password' string should return [112, 97, 115, 115, 119, 111, 114, 100].

This issue is due to a known string-corruption bug in Ruby 2.2.0 that was fixed in 2.2.2.

As described in the bug report, the corruption occured when BCrypt called a specific string-creation API from its C extension, which Devise v3.3.0 triggered by calling ::BCrypt::Engine.hash_secret from the Devise::Models::DatabaseAuthenticatable#valid_password? method. A Devise-specific workaround for this bug was published in v3.5.0.

The solution is to either:

  • Downgrade Ruby to < 2.2.0, or upgrade to >= 2.2.2;
  • Upgrade Devise to >= 3.5.0.