The has_secure_password helper method makes it easy for developers to encrypt and compare passwords for authentication, while also following best practices to provide a high-level of security. Learn how to use has_secure_password and discover the code which it adds and the processes that it handles for you.
- [Instructor] To create secure passwords, we need to encrypt them. Encryption is the process of taking a string of data, and then applying a mathematical function to it to produce a unique string of output. It's a process that requires knowledge you may not have yet, and it's easy to make mistakes. But in this movie, we'll learn how Rails makes it very easy for all developers to follow best practices and avoid careless mistakes. Most important rule about passwords is to never, ever, store passwords in the database as plain text. Always encrypt them.
If they're in plain text, then anyone who gains access to your database will have every user's password. Not just hackers, any site administrator, employee, or person with database access has the potential to read or accidentally leak all user passwords. And it's not just your site security that's at risk. Many users reuse the same username and passwords on multiple sites. So if a user uses the same password on your site that's for their bank account, you don't want to be the one providing a hole in the bank's site security.
So please, do it for all of us other website developers. Not only will we be encrypting the passwords, but we'll be using a one way encryption algorithm. It won't be possible for anyone to get the original password from the encrypted string. Including us. It works because of the principle that the same inputs to the hashing algorithm will always return the same output. So we'll take the password, we'll encrypt it, and then we'll store the result. Then when a user tries to log in, we'll take their attempted password, we'll pass it to the same hashing algorithm, and we'll get another encrypted string, which we can compare against the original to see if they match.
If the output is the same, we'll know that the input had to be correct. If the output is different, then we know that the input must be different. The one way encryption algorithm that Ruby on Rails uses is Blowfish, and that's a good strong encryption algorithm that's become a best practice and an industry standard. Rails makes it easy to create and work with secure passwords by providing us with the has secure password method that we can put into any active record model. That will enable a lot of best practices functionality.
You don't need to learn how to compare a plain text password with the stored encrypted password. Has secure password makes it easy. There are just two prerequisites to being able to use has secure password on a model. The first is that the application must have the bcrypt gem installed. Bcrypt is another name for Blowfish. You want to make sure that bcrypt is there, and available to us to use. And second, we must have a table on the model which has a string column for password digest.
So the first requirement is that we have that bcrypt gem. So if we look in our gem file, and we scroll down, we'll see that it is there, but it's probably commented out. And it says right here if we're using ActiveModel has secure password, then we're gonna need it. So you want to uncomment that line, so that bcrypt is now available. Let's save that file, and whenever we make changes to our gem file, we need to come back over to our application, we need to run bundle install. And that will install any missing gems that are there.
Once that process is complete, we have bcrypt available to us. The second requirement is that we have to have a column called password digest on our users model. And if we go take a look in our db directory, we have our schema dot rb, we can look at that at admin users, we'll see that we have one called hashed password. That's not going to work. This used to be what a lot of people used for the name of their hashed password field, but has secure password is going to require that we use password digest, and it's not configurable.
So let's write ourselves a migration so that we can change that. Let's come to our command line. We know how to create a migration, generate, migration, call it add password digest to admin users. Okay, so it created our new migration, let's go ahead and edit it, and I'm gonna change this to be an up method, and I'm first just gonna remove the column that we don't want anymore which is admin users and hashed password.
Then I'm gonna add a new column instead. I'm not gonna try changing the name of the column. I could, but I'm just gonna go ahead and throw away anything that was there before, and let's start fresh. I don't want any contents that might have been lingering around. And it's just gonna be a string. And of course if we have that as the up method, then we also need to have the down method which does the opposite. So I'm just gonna copy these two lines, and I'll reverse them, and instead of add column it's going to remove this column, and it's gonna add this column, and password digest doesn't need a definition after it, but we will need this definition here for hashed password.
If I recall correctly, it had a length on it which was 40. So let's just put that in there as well. Limit 40. Okay, so now I have my migration, let's go and run the migration. Rails db migrate, make sure that that works successfully. Okay, let's go take a look at our schema again. And it should be changed now, and we can say sure enough it is. It's now a string called password digest. Okay, so now we can use it, we've fulfilled the two prerequisites.
So the next step is to go into our model, and go into admin user, and inside admin user we just have to write has underscore secure underscore password. That's it, that's all we have to do. We just drop that one line, into our model. Adding has secure password to our model does a lot of work behind the scenes for us though. Let's get an idea of what it does for us. It adds an attribute reader, for password that allows us to assign a value to the password, and whenever we do it's going to automatically take that password and encrypt it using Blowfish and set it equal to the password digest.
It won't save it, it's just gonna set it equal to it. The next thing it's gonna do, is it's gonna do validates presence of password on create, so that we can't create this user without having a password, and it's gonna validate the confirmation of the password. Remember that only validates the confirmation, if confirmation is something we require on the form. Then last of all it gives us this authenticate method, and that's what we really need to call. We call authenticate, we provided a plain text string, the unencrypted password that someone is attempting, and it will return to us true or false.
True if the password matches what's stored, false if it doesn't. Let's try it out on the console. So we're gonna launch our Rails console. Okay so now that we have our console open, let's take an existing user. Let's say user equals admin user and let's just find the first one in the database. So there's the first one, and I'm gonna set user dot password equal to test password. Okay, now I've got that.
Now let's take a look at user dot password digest. See what it created? As soon as we set this password, password digest got populated with the encrypted string for us. It's ready to go. Let's try user dot save. It says false, let's check and see what our messages were, user dot errors, our errors were that the email is blank, so let's just fill that in real quick. User dot email is going to be equal to someone at somewhere dot com.
Okay, now let's try again, user dot save. And now it's saved it successfully. Now that we have the user saved, we have the ability at any point to find out if someone gave us the correct password. All we have to do is go find the user again, I'll do u this time, admin user dot first. All right, so we found that same user. U dot authenticate, that's the magic method name that we want to use, authenticate, and then let's try not the password and it gives us back false.
But if we instead do test password, which is what I used, then it returns back the actual user. It returns the user to us so that we can then continue to work with it. So while there's a lot of complicated things going on in the background, Rails makes the process extremely easy for us. We just need the bcrypt gem, we need to have the right column on our table, and then we drop in has secure password. After that, everything else is handled for us.
- Creating and configuring a new Ruby on Rails project
- Generating controllers and views
- Handling server requests
- Using different types of routes
- Rendering and viewing templates
- Generating migrations and models
- Creating, updating, and deleting records
- Finding records with queries
- Understanding relationship types
- Writing controllers for CRUD
- Working with layouts and helpers
- Managing application assets
- Building forms
- Validating data
- Authenticating users