Authenticating a User
The problem with the way we have created the User
information in the database is that we are saving the password in plain text. That is a big no no!
What we need to do is to encrypt the password before we save it. Then, when the user tries to log in, we need to compare the password he provides with the encrypted password in the database, and if it matches, allow the user in to the system.
There is a gem we can use to encrypt the password before we store it in the database - it is called BCrypt
and you can find more info about that gem here.
Add that gem to your Gemfile:
As usual, you run bundle install
once you add a new dependency.
Edit your spec/spec_helper.rb
file to require the new gem. The next step is to add some specs for the password encryption. In our user_spec.rb
we add the following tests within our main describe block:
The next step is to add some specs for the password encryption. In our user_spec.rb
we add the following tests within our main describe block:
In the first of the two specs we are a) creating a user with some credentials, b) asserting that the saved password (password_digest
) is NOT the one we passed in while creating the user and c) that the saved password is of a BCrypt::Password
class. We can not test for a specific encryption since BCrypt returns a different hash every time it is called on a word.
When this spec passes we can be sure that the right password have been saved in our database.
The second test is testing what happens if we try to create a user but pass in the wrong password confirmation. Password confirmation is mainly used to ensure that the user remembers what password he provides during the registration process and that he has not made a spelling mistake while typing it. First we save a command in a variable and then, on the next line, we assert that when that command is executed it throws an error. If that passes, we can be sure that password confirmation works and the user will not be created if password and password_confirmation does not match.
Save your spec file and run rspec
to see these tests fail.
On the first spec we get an failure about attribute password
not being accessible on User. Let's fix that. Open your user.rb
and add:
Also, on top of that file add:
Once you've added those lines and run rspec
again, you should get the following error on that particular spec:
An the second spec we've added, the error message should be:
Let's move over to the user.rb
file and fix that.
This code validates the confirmation of password and encrypts the password using BCrypt
if the confirmation passes the validation.
Now, we need to update the method we use to create the user in the applications controller:
Now, real quickly head over to the user_maintenance.feature
and add the following scenario:
Run cucumber
and watch it pass. The scenario we just added is called the sad path and is used to test not only what happens when everything is okay but also what happens when stuff go wrong.
Alright, now we have the users password safely encrypted and saved in our database. The next step is to add a method to authenticate the user when he tries to log in to the application.
Last updated