1ManStartup
1ManStartup

Reputation: 3816

Retrieve Salted PW using Node-bcrypt and Passport.JS

I have an issue in which I can create hashed passwords in node-bcrypt and passport.js, but am unable to use the hashed password.

Im using nodejs, express, mongodb, mongoose, passport js, bcrypt.

What Im Trying To Do

Be able to login as normal, but using the bcrypt salted paswword etc.

What I have Done I know my routes, api, and db are working. Since my current set up logs users in and out if I use a normal string for password instead of bcrypt.

I also checked my db and a bcrypt/salted password appears in the password field.

I got the idea to use bcrypt from this article (so using this code): http://devsmash.com/blog/password-authentication-with-mongoose-and-bcrypt

Here is my relevant code:

var express = require('express'),
    routes = require('./routes'),
    passport = require('passport'),
    util = require('util'),
    flash = require('connect-flash'),
    LocalStrategy = require('passport-local').Strategy,
    mongoose = require('mongoose');

mongoose.connect('mongodb://54.254.96.11/bcrypt')
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;

 bcrypt = require('bcrypt'),
    SALT_WORK_FACTOR = 10;

var user = new Schema({
username: { type: String, required: true, index: { unique: true } },
    password: { type: String, required: true },
  email: String
  });

var user = mongoose.model('user', user);

//Bcrypt Code

user.pre('save', function(next) {
    var guest = this;

    // only hash the password if it has been modified (or is new)
    if (!guest.isModified('password')) return next();

    // generate a salt
    bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
        if (err) return next(err);

        // hash the password using our new salt
        bcrypt.hash(guest.password, salt, function(err, hash) {
            if (err) return next(err);

            // override the cleartext password with the hashed one
            guest.password = hash;
            next();
        });
    });
});

user.methods.comparePassword = function(candidatePassword, cb) {
    bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
        if (err) return cb(err);
        cb(null, isMatch);
    });
};


//
passport.serializeUser(function(user, done) {
  done(null, user.id);
});

passport.deserializeUser(function(id, done) {
  user.findById(id, function (err, user) {
    done(err, user);
  });
});

passport.use(new LocalStrategy(
  function(username, password, done) {
    // asynchronous verification, for effect...
    process.nextTick(function () {

      // Find the user by username.  If there is no user with the given
      // username, or the password is not correct, set the user to `false` to
      // indicate failure and set a flash message.  Otherwise, return the
      // authenticated `user`.
      user.findOne({ username: username}, function(err, user) {
        if (err) { return done(err); }
        if (!user) { return done(null, false, { message: 'Unknown user ' + username }); }
        if (user.password != password) { return done(null, false, { message: 'Invalid password' }); }
        return done(null, user);
      })
    });
  }
));


// Relevant Express Routes

app.post('/login',
  passport.authenticate('local', { failureRedirect: '/login', failureFlash: true }),
  function(req, res) {
    res.redirect('/home');
  });


app.post('/create', function(req, res, next){
  var moot = new user({
    "username": req.body.username,
    "password" : req.body.password,
    "email" : req.body.email});


  moot.save(function (err) {
    if (!err) {
      res.redirect('/home');
    }
    else {
      res.redirect('/');
    }
  });
});

Upvotes: 4

Views: 2372

Answers (1)

mastilver
mastilver

Reputation: 677

I would do it this way:

create a new method for User model:

userSchema.statics.authenticate = function(username, password, callback)
{
    this.findOne({username: username}, function(err, user)
    {
        if(err) return callback(err);

        if(!user) return callback(null, false);


        user.comparePassword(password, function(err, correct)
        {
            if(!correct) return callback(null, false);

            callback(null, user);
        });

    });
}

then in the passport config:

passport.use(new LocalStrategy(
    function(username, password, done)
    {
        User.authenticate(username, password, function(err, user)
        {
           if(err) return done(err);
           if(!user) return done(null, false);

           done(null, user);
        }
    }
));

This should work (I didn't test it)

PS: please use 'user' for one user

for the model, use 'User'

Upvotes: 0

Related Questions