Where to impliment Password Encryption in node.js

jane49cloud

Jane49-cloud

Posted on November 14, 2022

Where to impliment Password Encryption in node.js

Security is one of the most essential features of any application.
We mainly impliment this through hashing password. Today I will focus on implimenting this in a MERN app.
The basic structure of a neat node application has the following basic folders and files

connection(database)
models (defines properties of models.)
conrollers (handlers of Crud operations)
routes(defines paths || Url mapping)

Encryption in controllers

Assuming you are already connected to the database and have created a users model, install bcrypt
npm i bcryptjs

# backend/controllers/users.js
const User = require('../models/user') //path to your user model
const bcrypt = require("bcryptjs")

const registerUser = async(req,res)=>{
const {name, email, password} = req.body

//first check if the user exists
 const userExists = await User.findOne({ email });
    if (userExists) {
      response.status(400);
      console.log("Email address already exists")
    }

  //Encrpt password before you save
    const salt = await bcrypt.genSalt(10);
    const hashedPassword = await bcrypt.hash(password, salt);
}

//create user 

try {
const user = await User.create({
        name,
        password: hashedPassword,
        email
    });
  res.json(user);
    console.log(user, "User created successfully...")

} catch (error) {
    console.log(error, `User not created...`)
};

module.exports = {
  registerUser,
};

Enter fullscreen mode Exit fullscreen mode

import the registerUser controller and route your user register path and test your application. I used postman to register a user and got the following json response:

{
    "name": "Luke Graham",
    "email": "graham@gmail.com",
    "password": "$2a$10$rQrhLmwoEGaCMq9qR9cLaOvVBtA/FvoSSmt1tGj0gq7tFyscDS5jK",
    "photo": "https://i.ibb.co/4pDNDk1/avatar.png",
    "phone": "+245",
    "bio": "bio should be at most 250 characters",
    "_id": "6371eb2668c624ddb1bd72d9",
    "createdAt": "2022-11-14T07:15:50.078Z",
    "updatedAt": "2022-11-14T07:15:50.078Z",
    "__v": 0
}

Enter fullscreen mode Exit fullscreen mode

The password was hashed successfully.
Do not give a maxLength to the password in the model because the hashed password gives a long string. Validate in the frontend.
The above method is valid. However, there are moreother controllers that require password.

*registerUser
loginUser
updatePassword
forgotPassword
*

for each of the above handlers you need to configure encryption.
Therefore it is easier to perfom the encription in the model file.
Use a schema.pre() function that changes the password before saving.
This is how it is implimented:

#backend/models/users.js
const mongoose = require("mongoose");
const bcrypt = require("bcryptjs");

const userSchema = new mongoose.Schema({
  name: { type: String, required: true },
  email: {
    type: String,
    required: true,
    unique: true,
    trim: true,
    match: [
      /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
      "Please enter a valid email address",
    ],
  },
  password: {
    type: String,
    required: true,
    minLength: [6, "password must be at least 6 characters"],
  },
  photo: { type: String, required: true ,
    default: "https://i.ibb.co/4pDNDk1/avatar.png"}, // person avatar
    phone:{type:String, default: "+245"},
    bio:{
        type:String, 
        maxLength:[250, "bio must be at most 250 characters"],
        default: "bio should be at most 250 characters"
    }
},
{
    timestamps:true
}

);

//Encrypt password before saving to database

userSchema.pre("save", async function(next){
  if(!this.isModified("password")){
      return next()
  }
  const salt = await bcrypt.genSalt(10);
  const hashedPassword = await bcrypt.hash(this.password, salt);//this.passord (points to the password in this file)
  this.password = hashedPassword
next()
})


module.exports = mongoose.model("User", userSchema);

Enter fullscreen mode Exit fullscreen mode

Just a few adjustments in the model and password is pashed before the schema is saved.
There are a few changes in the controller file

#backend/controller/user
const User = require('../models/user') //path to your user model

const registerUser = async(req,res)=>{
const {name, email, password} = req.body

//first check if the user exists
 const userExists = await User.findOne({ email });
    if (userExists) {
      response.status(400);
      console.log("Email address already exists")
    }
 //create user 
try {
const user = await User.create({
        name,
        password,
        email
    });
  res.json(user);
    console.log(user, "User created successfully...")

} catch (error) {
    console.log(error, `User not created...`)
};
module.exports = {
  registerUser,
};

Enter fullscreen mode Exit fullscreen mode

route your application and test. My response:

{
    "name": "Mercy",
    "email": "mercy@gmail.com",
    "password": "$2a$10$iqzkaO1wTco.3z1KK8Ij9u9sy2DtLViRwL5lvgeHDcQ31wPfCo9jK",
    "photo": "https://i.ibb.co/4pDNDk1/avatar.png",
    "phone": "+245",
    "bio": "bio should be at most 250 characters",
    "_id": "6371fe23225d25b4e3e8220c",
    "createdAt": "2022-11-14T08:36:51.311Z",
    "updatedAt": "2022-11-14T08:36:51.311Z",
    "__v": 0
}

Enter fullscreen mode Exit fullscreen mode

The password was successfully hashed. Hoping this helps understund encryption better and how to use it better.

Was this article helpful?
Need clarification?
Leave a comment

💖 💪 🙅 🚩
jane49cloud
Jane49-cloud

Posted on November 14, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related