nodejs passport BasicStrategy getting unauthorized

Viewed 436

I am trying to test a simple passport authentication by using BasicStrategy. I am able to create a user with email and password (password is hashed). However, when I signin I am getting unauthorized

app.js

const express = require('express');
const app = express();
var bodyParser = require('body-parser');
var passport = require('passport');
var BasicStrategy = require('passport-http').BasicStrategy;

const index = require('./routes/index.js');
const userRouter = require('./routes/user');
const User = require('./models/User');

// connect to mongodb
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/test', {useNewUrlParser: true})
  .then(() => {
    console.log('connected to mongodb');
  }).catch(err => {
    console.log("Connection failed with an error " + err);
  });

passport.use(new BasicStrategy(
  function (email, password, done) {
    User.findUserByEmail(email, function(err, user) {
      if (err) {
        return done(err);
      }

      if (!user) {
        return done(null, false, {message: 'User not found'});
      }

      User.comparePassword(password, user.password, function(err, isMatch) {
        if (err) {
          return done(err);
        }
        if (isMatch) {
          return done(null, user);
        } else {
          return done(null, {message: 'Invalid password'});
        }
      });
    });
  }
));

// Middleware
app.use(passport.initialize());
app.use(bodyParser.urlencoded({ extended: true }));
app.use("/users", userRouter);


app.get('/', index);

app.listen(3000, () => console.log(`Open http://localhost:3000 to see a response.`));

routes/user.js

var express = require('express');
var router = express.Router();
var passport = require('passport');
var User = require('../models/User');

router.post('/create', function(req, res) {
  var newUser = new User({
    name: req.body.name,
    email: req.body.email,
    password: req.body.password,
    role: 'student',
  });

  User.createUser(newUser, function(err, user) {
    if (err) throw err;

    res.send(user).end();
  });
});

router.post('/signin',
  passport.authenticate('basic', {session: false}),
  function(req, res) {
    res.send({
      status: 'success',
    });
});

module.exports = router;

models/User.js

var mongoose  = require('mongoose');
var bcrypt = require('bcryptjs');

var UserSchema = mongoose.Schema({
    name: String,
    email: {
      type: String,
      index: true,
      unique: true
    },
    password: String,
});

var User = module.exports = mongoose.model('User', UserSchema);

module.exports.createUser = function(newUser, callback){
  bcrypt.genSalt(10, function(err, salt) {
    bcrypt.hash(newUser.password, salt, function(err, hash) {
        newUser.password = hash;
        newUser.save(callback);
    });
  });
}

module.exports.findUserByEmail = function(email, callback) {
  User.findOne({email: email}, callback);
}

module.exports.comparePassword = function(password, passwordHash ,callback) {
  bcrypt.compare(password, passwordHash, function(err, isMatch) {
    if (err) throw err;

    callback(null, isMatch);
  });
}

To create a user via curl

curl -X POST -d 'name=John' -d 'email=test@gmail.com' -d 'password=123456' http://localhost:3000/users/create

{"_id":"5d0790633c0a7857b6154654","name":"John","email":"test@gmail.com","password":"$2a$10$GqFoxNhEOw2sCLNS8QfWx.xiAsZ8Y6/cQyeM1qseSeX7dhPA6D0dW","__v":0}

However, signin fails;

curl -X POST -d 'email=test@gmail.com' -d 'password=123456' http://localhost:3000/users/signin

Unauthorized

Really appreaciate for the help. Thanks!

2 Answers

Your request should be

curl -X POST --user username:password <<loginURL>> or 
curl -X POST -u username:password <<loginURL>>

The issue is basically that you are using the HTTP basic auth Passport strategy. If you change your login request to the following, it will work:

curl -X POST --user test@gmail.com:123456 http://localhost:3000/users/signin

See here for more details on using curl with basic auth.

If you do want to use email and password body parameters, you can check out the Passport local strategy.

Related