“Fly Me to the Moon” … an experience with securing passwords as a first-time Sinatra user.
I recently finished Phase 2 of my Flatiron program and the final project was to build out an app using everything we had learned about Sinatra. Sinatra is fun because there are a lot of things it writes for you by utilizing the database ActiveRecord. One of the requirements was to make sure that the passwords for all users were secure and couldn’t be hacked. Although this seemed like an easy task, because I had just finished some labs practicing how to do it, I was surprisingly wrong. I had got a little confused about the difference between when to call password_digest and/or password.
The important detail to remember here is what exactly password_digest is doing and when it does it. I had remembered that it was supposed to be placed in your CreateUser table which looks something like this:
So naturally, I was calling password_digest in my code line since I had been used to referring back to the table to call on the information I was referring to. However, that’s not how password_digest works. Password_digest actually works in the background along with the macro has_secure_password upon the creation of a new user. When a user creates a new account has_secure_password uses built-in methods and validations to ensure the password is valid, assign the newly created password to the user model, and stores an encrypted version of the password inside the password_digest. The encryption happens by the Bcrypt gem (which is required in your Gemfile for this to function properly). Sometime in between creation and being stored into the password_digest column, Bcrypt will take the unencrypted password and “salt” it, which means it adds random strings of a fixed length to the password and hashes it. It seems like magic, but that’s the beauty of using ActiveRecord. The has_secure_password macro is writing most of the methods for you in the background. Below is an example of this in action:
Notice that the password is shown plainly when the User is called because I didn’t authenticate it properly to use has_secure_password. It clearly shows “force” even though password_digest is shown, that’s due to authenticate not being present to successfully use has_secure_password and Bcrypt gem. I fixed it and now you can see that when it is passed to digest it is encrypted and shown as: “$2a$12$Tu6b2ex8G4MJQ4OhC0gRWO4mkYpsAHF1k/JdLbo0JBJFIlBUExCPi”. This is extremely important because if this didn’t work properly one could simply run all users in Tux and see everyone’s passwords! That’s != secure. Here is an example of the correct code in full on my LoginController:
To close, it is important to always treat passwords like the “One Ring” from Lord of The Rings … “Keep it secret, keep it safe”! When not properly “wielded” we leave ourselves open to hacking attacks. We gotta properly protect our users.
Here’s a little bonus content as well, “Make it one for my readers, … and one more for the road”(that’s another play on a Frank Sinatra song feel free to give it a listen https://youtu.be/hkwdkUXQ1yo). While working on this I also used the .build function. I did this from a suggestion on a google search but didn’t really understand WHAT it was doing. Here’s an example of the code I’m referring to:
By calling current_user.party_members.build(params), .build is returning the new objects instantiated through the current user and the party members that belong to them through their associated primary and foreign keys that haven’t been saved yet. SO, when @party_member is created it will know the current user it belongs to and what party member id it will belong to. Sinatra is amazing … both the singer and software language (haha). I can’t wait to break into Rails!
Thanks for tuning in, and until next time, happy coding!