This is my first time delving deeper into the inner workings of devise and the process of authentication. I had built a couple relatively simple authentication systems from scratch in PHP, but as far as Rails is concerned, I've blindly trusted Devise.
In particular, we needed to adjust the process by which an individual confirmed their account and avoid the cardinal sin of sending a plain text password to new users.
(As a side note, it never ceases to amaze me that established companies, with millions, if not billions, of dollars invested in their technical infrastructure still send out plaintext passwords. It just seems like such an avoidable security flaw...)
Anyways, I ended up overwriting the existing confirmations controller within devise and having the the users confirmation link take them to a form to create their new password. This in of itself, required digesting the confirmation token, which was new to me. Devise never allows the original token to be written other than in the user's confirmation link, sent via email. The trick though, is to have a repeatable, and comparable digestion process by which the token is encrypted to the same thing regardless of the starting point. This is where BCrypt comes in.
Devise relies on the encrpytion function that is bcrypt to take a string and systematically convert that string to a hash which is stored. But this isn't as simple as producing some random hash. One factor in good encryption is selecting the strength of encryption. In particular, BCrypt defaults to a work factor, or strength, of 10. What does that mean though?
Bcrypt is taking a string, and programatically converting that string into a hash. It then takes that hash, and does the same thing, 10 times. Now, this isn't exactly correct. The methods by which BCrypt really encrypts passwords is beyond my (current) understanding and this is a trivialization to help demonstrate a concept. BCrypt's minimum number of sequences is 4, which is relatively low cost performance-wise but even 10 doesn't show a noticable change in benchmarks. When you get up to 14 or more sequences, then you begin to go from thousandeths and hundredeths to full seconds.
Throughout this endeavor I also ended up reading a fair amount of Devise source code. The thing I found most interesting was really the magnitude of Devise all together. While, it is nice to just plug in a Gem and have it work, sometimes it can be overkill. For example, I started out by trying to copy Devise's suggested tutorial for this. It nearly worked, but as dleve123 pointed out to me, neither of us could reliably tell what was happening, so I decided to start from scratch. I ended up accomplishing the task with less flexible but a much smaller amount of code. This was primarily due to the fact that it ONLY works for the Users model whereas Devise is built to work for any model.
Security is a large concern for the entire Healthify team, and I believe this is a great example of a high value, low cost feature that allows for more secure user provisioning. I'd recommend that anyone using Devise get to know what's going on under the hood!