Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to protect route endpoints using Passport?

I am trying to build user authentication into my simple Node.js app using the tutorial here: http://code.tutsplus.com/tutorials/authenticating-nodejs-applications-with-passport--cms-21619

It works great in terms of protecting the application home page so that it can only be accessed after logging in, but I am having a really hard time restricting my REST endpoints to only logged in users. As in using Postman I can still call the end points without any authentication.

In my route I have the following:

var express = require('express');
var router = express.Router();

// if the user is authenticated
var isAuthenticated = function (req, res, next) {
  if (req.isAuthenticated())
    return next();
  res.json("not authenticated");
}

/*
 * GET carlist.
 */
router.get('/carlist', isAuthenticated, function(req, res) {
    var db = req.db;
    var collection = db.get('carlist');
    collection.find({},{},function(e,docs){
        res.json(docs);
    });
});

This doesn't seem to work, even if I actually enter correct credentials I am always returned "not authenticated". What I am I missing here?

EDIT:

Full code here: https://gist.github.com/tudorific/d99bc51cfbd3d9d732a3bb1b93ed7214

Thanks in advance for the help!

like image 223
user2573690 Avatar asked May 17 '16 04:05

user2573690


1 Answers

I figured it out. Since I was using a LocalStrategy the IsAuthenticated method was looking for the credentials in the session rather than at the Basic Credentials I was sending with Postman. So I needed to create the following new BasicStrategy:

var passport = require('passport');
var BasicStrategy = require('passport-http').BasicStrategy;
var Employer = require('../models/employer');
var bCrypt = require('bcrypt-nodejs');

passport.use(new BasicStrategy(
  function(username, password, done) {
    Employer.findOne({ username: username }, function (err, user) {
      if (err) { return done(err); }
      if (!user) { return done(null, false); }
      //if (!user.validPassword(password)) { return done(null, false); }

      if (!isValidPassword(user, password)){ return done(null, false); }

      return done(null, user);
    });

    var isValidPassword = function(employer, password){
        return bCrypt.compareSync(password, employer.password);
    }
}));

And then use that strategy in my route like this:

router.get('/carlist', passport.authenticate('basic',  function(req, res) {
    var db = req.db;
    var collection = db.get('cars');
    collection.find({},{},function(e,docs){
        res.json(docs);
    });
});

This would use my basic authentication credentials from Postman to connect to the website.

Thanks to Neta Meta's advice in the comments to my OP I was able to arrive to this result and a bit more reading on the Passport documentation to understand the differences between the strategies.

like image 197
user2573690 Avatar answered Sep 20 '22 12:09

user2573690