Open In App

How to Sign In with raw password when password store in the database are hashed form in Node.js ?

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

The password stored in the database is always in (hashed+salt) form because of security reasons. When users sign up on any website, a password is given in the raw form. But storing the raw passwords in the database directly is not a good practice. Using some server-side logic we first convert raw passwords in the (hashed+salt) form then store it in the database. This arises a new challenge, how to compare the raw password given by the user at Sign In time and give access to the user on the basis of the password is correct or not.
 

Password stored in the database in the following form: 

Hashed(password, salt) 

Example: 
 

22cbca6aa74d3546971ca355a7641649b222a7858f97952f50d68ea65b3c5067a008ea4cdc8974461090a36d7815215 
ab4659d2333a94b15d43c758f4d08ab60.7fb85e87188dd649

Steps to set up logic to Sign In with raw password: 

  • Search the database with the help of unique username or email given by the user to sign in.
  • Find the unique record and if not found return ‘User not exist’.
  • Split the encrypted password at ‘ . ‘ to find the hashed password and salt individually.
  • Hashed the raw password given by the user to sign in with Node.js ‘scrypt’ method using salt.
  • Compare the obtained hashed with the hashed  got from splitting the database password.
  • If both hashed are equal signed in the user and give the access.
  • If both hashed not equal denied the access with message Invalid password.

 

Note: To illustrates the logic, here we take a local or custom database.  same logic can also be implemented with the regular database like MongoDB, MySql etc.

Example: This example illustrates how to sign in with a raw password when stored password in the database is in (hashed + salt) form.

javascript




const util = require('util')
const crypto = require('crypto')
const express = require('express')
const bodyParser = require('body-parser')
const repo = require('./repository')
 
const app = express()
const scrypt = util.promisify(crypto.scrypt)
const port = process.env.PORT || 3000
 
// The body-parser middleware to parse form data
app.use(bodyParser.urlencoded({ extended: true }))
 
// Get route to display HTML form to sign in
app.get('/signin', (req, res) => {
    res.send(`
    <div>
      <form method='POST'>
        <div>
          <div>
            <label id='email'>Username</label>
          </div>
          <input type='text' name='email'
            placeholder='Email' for='email'>
        </div>
        <div>
          <div>
            <label id='password'>Password</label>
          </div>
          <input type='password' name='password'
          placeholder='Password' for='password'>
        </div>
        <div>
          <button>Sign In</button>
        </div>
      </form>
    </div>
  `)
})
 
// Post route to handle form submission logic and
app.post('/signin', async (req, res) => {
 
    // Email and password submitted by the user
    const { email, password } = req.body
 
    // Find record by given unique username or email
    const user = await repo.findBy({ email })
    console.log(user)
 
    // If record not found by given username
    if (!user) {
        return res.send('User Not Exist')
    }
 
    // Hashed and salt of database password
    const [hashed, salt] = user.password.split('.')
 
    // Hashing raw password submitted by the user
    // to sign in third argument is the key length
    // that must be same when hashing the password
    // to store it into the database when user sign up
    const hashedBuff = await scrypt(password, salt, 64)
    console.log(hashed)
    console.log(hashedBuff.toString('hex'))
 
    // Compare saved hashed of database and
    // obtained hashed
    const isValid = hashed === hashedBuff.toString('hex')
 
    if (isValid) {
        return res.send('Sign In successfully')
    }
    return res.send('Invalid Password')
})
 
// Server setup
app.listen(port, () => {
    console.log(`Server start on port ${port}`)
})


Filename: repository.js This file contains all the logic related to create a local database and how to interact with it.

javascript




// Importing node.js file system, util,
// crypto module
const fs = require('fs')
const util = require('util')
const crypto = require('crypto')
 
// Convert callback based scrypt method
// to promise based method
const scrypt = util.promisify(crypto.scrypt)
 
class Repository {
 
    constructor(filename) {
 
        // The filename where datas are
        // going to store
        if (!filename) {
            throw new Error(
'Filename is required to create a datastore!')
        }
 
        this.filename = filename
 
        try {
            fs.accessSync(this.filename)
        } catch (err) {
 
            // If file not exist it is created
            // with empty array
            fs.writeFileSync(this.filename, '[]')
        }
    }
 
    async findBy(attrs) {
 
        // Read all file contents of the datastore
        const jsonRecords = await
            fs.promises.readFile(this.filename, {
            encoding: 'utf8'
        })
 
        // Parsing json records in javascript
        // object type records
        const records = JSON.parse(jsonRecords)
 
        // Iterating through each record
        for (let record of records) {
            let found = true
 
            // Iterate through each given
            // propert for each record
            for (let key in attrs) {
 
                // If any given property not matches
                // with record record is discarded
                if (record[key] !== attrs[key]) {
                    found = false
                }
            }
            // If 'found' remains true after iterating
            // through each given property that
            // means record found
            if (found) {
                return record
            }
        }
    }
}
 
// The 'datastore.json' file created at runtime
// if it not exist, here we try to fetch
// information from database using some properties
// that means database(datastore.json) already
// exist and there are also records in it.
module.exports = new Repository('datastore.json')


Run index.js file using the following command: 
 

node index.js

Filename: package.json
 

package.json file

Database: 

Database

Output: 

Here we submit three forms individually with a different combinations of username and password and get the output as shown in the image respectively.

 

Sign In with invalid username

 

Sign In with valid username but invalid password

 

Sign In with valid username and password

Redirected Pages:
 

Response when Sign In with invalid username

 

Response when sign in with valid username but invalid password

 

Response when sign in with valid username and password

 



Last Updated : 02 Feb, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads