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,
};
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
}
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);
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,
};
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
}
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)