Password Hashing
Introduction
It is not uncommon to read a story about a company's database being "hacked" and 100,000 user accounts being stolen. Often time, the usernames and passwords of those stolen accounts end up being published on the Internet. What is very embarrassing is when the passwords that were stolen were "plain text". Just as the ones in our "account" table are right now.
The solution to our embarrassment is to alter the password from "plain text" to a "hash". Without getting too geeky, a hash is a one-way transformation (it cannot be reversed - we hope) of a plain text password into a jumble of characters that don't mean anything if read by a human.
Video Demonstration
The video provides a general overview of the activity, but does not contain the detail needed to complete each process. Watch the video to obtain a general idea, but follow the written steps to complete the activity. This is the Transcript of the video.
Bcryptjs
In the old days, people would devise all kinds of methods of creating hashes, but today things are much simpler as packages exist to do it for us. We will use the bcryptjs package to hash the submitted password, prior to storing it into the database.
Install Bcryptjs
As with installing any package, the following process should be followed:
- Open a VSC terminal.
- Type "
pnpm add bcryptjs
", press "Enter". - When the installation is done, close the terminal.
Implement Bcryptjs
- Open the accountController file.
- At the top of the file, require the "bcryptjs" package:
const bcrypt = require("bcryptjs")
- Scroll down and find the function to register a new client.
- In the register function, directly beneath where the incoming data is collected from the req.body, create several empty lines. Add the following code to the new lines:
// Hash the password before storing let hashedPassword try { // regular password and cost (salt is generated automatically) hashedPassword = await bcrypt.hashSync(account_password, 10) } catch (error) { req.flash("notice", 'Sorry, there was an error processing the registration.') res.status(500).render("account/register", { title: "Registration", nav, errors: null, }) }
An Explanation
- Line 1 - a comment to indicate what is happening in the code.
- Line 2 - declares a new variable.
- Line 3 - opens a try-catch block.
- Line 4 - another comment explaining line 5.
- Line 5 - calls the "
bcrypt.hashSync()
function, using "await" and stores the resulting hash into the variable created on line 2. The function accepts the plain text password and a "saltRounds" value as parameters. [A saltRound is an integer indicating how many times a hash will be resent through the hashing algorithim. In our code, the 10 means that the password will be hashed, then that hash will be rehashed and so on until 10 such processes have been carried out.] - Line 6 - ends the "try" and opens the "catch". The catch will store any errors into the "error" variable.
- Line 7 - creates a flash message indicating the registration failed.
- Lines 8-12 - will return the registration view.
- Line 13 - closes the "catch" block.
- Ensure that no warnings or errors are present. Save the file.
- Finally, scroll down a bit further and replace the plain text "account_password" variable in the accountRegister function, with the new "hashedPassword"" variable.
- When done the accountRegister function should look similar to this:
const regResult = await accountModel.accountRegister( account_firstname, account_lastname, account_email, hashedPassword )
- Again, ensure that no warnings or errors are present. Save the file.
Test it Out
- Open a VSC terminal and start the local server: "
pnpm run dev
", press "Enter". - In the browser, navigate to the registration view in the project site.
- Register a new account.
- The login view should be delivered with a success message.
- Use pgAdmin to check your account data in the database.
- If things worked correctly the password for the new account should now be a long string of characters and symbols and no longer be a plain text password.
- If it didn't work, review the code for errors. Check variable names to make sure they match. Ask a classmate. Ask the TA, lab assistant or professor for help.
- Delete old records. Delete the records in the account table that contain plain text passwords. If desired, register the same accounts again, but with the hashed password.
- Be sure to shut down the server when done with "
Control + C
" in the terminal.
Summary
As has been stated before, "This is not a security class, but we want to use secure methods with our code". By hashing passwords, we increase the security of the passwords that are stored in the database. This makes it much more difficult to know the original password - thus, they are more secure.