Using bcrypt is the proper way to store passwords in your database regardless of whatever language your backend is built in – PHP, Ruby, Python, Node.js, etc. Why ? Here’s the answer.
So how do we go about employing this technique in Node.js ? Thankfully we have a neat bcrypt module from Nick Campbell to do the job for us. It’s super easy to use, lets see how.
What's the one thing every developer wants? More screens! Enhance your coding experience with an external monitor to increase screen real estate.
First of all install it via NPM.
$ npm install bcrypt
The module provides us with 2 ways to hash the password – sync and async.
Sync Usage
For generating the password hash and storing it you’d do something like this –
// Load the bcrypt module var bcrypt = require('bcrypt'); // Generate a salt var salt = bcrypt.genSaltSync(10); // Hash the password with the salt var hash = bcrypt.hashSync("my password", salt); // Finally just store the hash in your DB // .. code to store in Redis/Mongo/Mysql/Sqlite/Postgres/etc.
The salt+hash can also be auto-generated in a single line of code –
var hash = bcrypt.hashSync("my password", 10);
During authentication you need to check the incoming password string against the hash. This is what you’d do –
// Load the password hash from DB // Let's assume it's stored in a variable called `hash` bcrypt.compareSync("my password", hash); // true bcrypt.compareSync("not my password", hash); // false
"my password"
is the correct one (sent via login form or some other method by the user) hence compareSync
returns true
while in the second case, when the password is incorrect, it returns false
.
Async Usage
The module also provides us with an async flavour that can be used like this –
var bcrypt = require('bcrypt'); bcrypt.genSalt(10, function(err, salt) { bcrypt.hash("my password", salt, function(err, hash) { // Store hash in your password DB. }); }); // or bcrypt.hash('bacon', 10, function(err, hash) { // Store hash in your password DB. });
.. and this is how you’d compare the hash saved in DB with the user supplied password –
// Load password hash from DB bcrypt.compare("my password", hash, function(err, res) { // res === true }); bcrypt.compare("not my password", hash, function(err, res) { // res === false });
If you’re wondering what the 10
(that’s used for hashing) is, then that’s the work factor or the number of rounds the data is processed for. More rounds leads to more secured hash but slower/expensive process.
You can check out the full API documentation here. Good Luck!
Thanks for the nice article. In implementing a server solution I attempted to use this but it does not work. In my data model, before inserting to db I do:
bcrypt.genSalt(12, 24, function (err, salt) {
if (err) return next(err);
bcrypt.hash(password, salt, function (err, hash) {
if (err) return next(err);
model.password = hash;
});
}
);
Which works fine. However, on the comparison side, it always fails:
var hash = model.password;
var userCreds = form.password;
var validated = bcrypt.compareSync(userCreds, hash); // always false;
The logic for inserting/comparing are in two separate modules and so have their own require(‘bcrypt’) statements. Thanks in advance