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

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 indivisually.
  • 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.

filter_none

edit
close

play_arrow

link
brightness_4
code

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 uniqe 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}`)
})

chevron_right


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

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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')

chevron_right


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




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.


Article Tags :

Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.