JavaScript's Math.random() does not provide an option to provide a seed, but there are libraries out there that implement a PRNG in JavaScript. Two of the most popular ones are seedrandom and random-seed. Out of the two, the random-seed package provides a string(count) method that'll generate a random string instead of a random number; because of this convenience, we will use the random-seed package to generate our fake salt.
First, let's install it:
$ yarn add random-seed
Now, create a new file at utils/generate-fake-salt.js and define a new generateFakeSalt function that will output a fake salt based on the email of the user:
import randomseed from 'random-seed';
function generateFakeSalt(seed) {
const salt = randomseed
// Seed the pseudo-random number generator with a seed so the
// output is deterministic
.create(seed)
// Instead of a number, generate a string of sufficient length,
// so that even when invalid characters are stripped out,
// there will be enough characters to compose the salt
.string(110)
// Replace all characters outside the character range of a valid
//bcrypt salt
.replace(/[^a-zA-Z0-9./]/g, '')
// Extract only the first 22 characters for the salt
.slice(0, 22);
// Prepend the bcrypt algorithm version and cost parameters
return `$2a$10$${salt}`;
}
export default generateFakeSalt;
Next, inside the retrieveSalt engine, add a catch block at the end that will use the generateFakeSalt function if the user cannot be found:
function retrieveSalt(req, db, getSalt, generateFakeSalt) {
...
.then(bcrypt.getSalt)
.catch((err) => {
if (err.message === NO_RESULTS_ERROR_MESSAGE) {
return generateFakeSalt(req.query.email);
}
return Promise.reject(new Error('Internal Server Error'));
});
}
Again, import the generateFakeSalt utility function in src/index.js, and pass it down to the engine through the handler.
Now, run the E2E test suite again and the tests should pass. Add some unit and integration tests to cover these new blocks of code. When you finish, commit the changes and move on to the next step.