DEV Community

Cover image for Where to impliment Password Encryption in node.js
Jane49-cloud
Jane49-cloud

Posted on

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

Top comments (0)