skip to Main Content

Currently I am working in dev env on my local machine where I am storing passwords in plain text using MongoDB. I am using express-jwt along with jsonwebtoken for passing user data and authentication. I’ve researched bcryptjs and bcrypt and I would like to implement whichever is best for React, and Express, for passing hashed passwords to the database from the client. I have found resources for server side, but nothing for client side.

My question is then, what is the methodology for properly saving encrypted passwords on my server when they are passed from a client? How do I encrypt passwords client side then authenticate server side?

I have read some articles saying there is no need to encrypt client side due to ssl, but others say there is an absolute need to encrypt client side. What is the correct way, and how can I implement it on my React application?

2

Answers


  1. You don’t decrypt passwords. You ask the user for the password, then you hash it and compare it to the stored hash one you saved. If they’re the same, then (assuming you have a secure hashing algorithm) the unencrypted versions must be the same also.

    Login or Signup to reply.
  2. Using Bcryptjs, Express and MongoDB:

    1. There is no need to encrpyt client side, you can pass the password as plain text to the server using a post request (through a form usually).

    2. Assuming you have a ‘user’ schema which looks similar to this:

         const userSchema = new mongoose.Schema({
          email:{type:String,required:true,unique:true},
          password:{type:String,required:true}
         },{collection:'users'}
         const User= mongoose.model("User",userSchema);
         )
      
    3. On register/sign up in the server, where you handle the request you would hash the user’s password like so:

    app.post('/signup',async (req,res)=>{
        // geting our data from frontend
        const {email,password:plainTextPassword}=req.body;
        // encrypting our password to store in database
        const password = await bcrypt.hash(plainTextPassword,salt);
        try {
            // storing our user data into database
            const response = await User.create({
                email,
                password
            })
            return res.redirect('/');
        } catch (error) {
            console.log(JSON.stringify(error));
            if(error.code === 11000){
                return res.send({status:'error',error:'email already exists'})
            }
            throw error
        }
    })

    4.Upon login request (which will also be a post through a form o the client), you will compare the passwords using bcrpyt.compare() function, and if successful, assign a JWT to the user like so, this method assumes the token will be stored in the Cookies.

    const verifyUserLogin = async (email,password)=>{
        try {
            const user = await User.findOne({email}).lean()
            if(!user){
                return {status:'error',error:'user not found'}
            }
            if(await bcrypt.compare(password,user.password)){
                // creating a JWT token
                token = jwt.sign({id:user._id,username:user.email,type:'user'},JWT_SECRET,{ expiresIn: '2h'})
                return {status:'ok',data:token}
            }
            return {status:'error',error:'invalid password'}
        } catch (error) {
            console.log(error);
            return {status:'error',error:'timed out'}
        }
    }
    
    // login 
    app.post('/login',async(req,res)=>{
        const {email,password}=req.body;
        // we made a function to verify our user login
        const response = await verifyUserLogin(email,password);
        if(response.status==='ok'){
            // storing our JWT web token as a cookie in our browser
            res.cookie('token',token,{ maxAge: 2 * 60 * 60 * 1000, httpOnly: true });  // maxAge: 2 hours
            res.redirect('/');
        }else{
            res.json(response);
        }
    })
    1. I didn’t address the front end, because it only includes basic POST request forms in react, there is no need for any special methods or processing on the client-side.
      hope it helps.

    edit, hashing client-side:
    There is a debate about this, and in some protocols, it’s even required to hash passwords on the client-side, in short, because SSL already encrypts everything that moves from client to server hashing on the client-side is pretty pointless and is not widely accepted today, even @ big companies. Bottom line, the added security is neglectable, and is not worth the trouble and exposing hashing logic to the client side

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search