2

I am using passport-local for my strategy and also using bluebird in order to make this a promise. I am not sure if this is a bad thing to do, but it is what I would like to do. My current problem is I do not know how to get the resolve and or rejectvalues from my route.

I will post the local-strategy. Everything works and I am getting the correct information. I just need to get this information to the route and be able to use req.user

I am getting the authUser and also getting any errors such as a custom wrong password error. But if seeing the other code helps then let me know.

passport.use(
  new LocalStrat((username, password) => {
    return new Promise((resolve, reject) => {
      controllers.user
        .getUserByUsername(username)
        .then(user => {
          user = user;
          return controllers.user.comparePassword(password, user);
        })
        .then(authUser => {
          resolve(authUser);
        })
        .catch(err => {
          reject(err);
        });
    });
  })
);

/* User Login */
router.post('/login', passport.authenticate('local'), (req, res) => {
  // Need to access promise values here 
  console.log(req.user);
});
Taylor Austin
  • 5,407
  • 15
  • 58
  • 103
  • Avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! – Bergi Sep 28 '17 at 20:59
  • @Bergi how do I correct this here then? I am pretty new to this. – Taylor Austin Sep 28 '17 at 21:44
  • 1
    Drop the "`new Promise((resolve, reject) => {`" and "`.then(authUser => { resolve(authUser); }) .catch(err => { reject(err); }); })`" parts – Bergi Sep 28 '17 at 22:25
  • 1
    Oh, and `user = user` is superfluous as well – Bergi Sep 28 '17 at 22:25

1 Answers1

4

The main thing you need to note is that Strategy's API doesn't deal in Promises. You'll have to deal with the callback argument that it wants. You can see the function signature here: Configure Strategy. In my implementation, my User deals with Promises and just calls the callback from within the then() of the Promise.

Since you have to hand the Strategy that you want to use to passport, and passport expects something with the callback convention, you'll have to follow its API. As of right now, passport does not really support Promises within its API. I'd say take a look at the passport issue Add support promises flow and add support for integrating with promises. I don't think it'll happen until express migrates as well though.

This is the way that I use Strategys to deal with async login:

const express = require("express"),
    passport = require("passport"),
    Strategy = require("passport-local").Strategy,
    User = require("../models/user"),
    router = express.Router();

// Strategy to authenticate a user
const localStrategy = new Strategy((username, password, cb) => {
    User.authenticate(username, password).then((result) => {
        if (result.success) {
            cb(null, result.user);
        } else {
            cb(null, false);
        }
    }, cb);
});

function ensureLoggedIn(req, res, next) {
    if (req.isAuthenticated()) {
        return next();
    }
    res.redirect("/login");
}

// Utilize the strategy
passport.use(localStrategy);

router.use(require("./passify"));
router.use("/profile", ensureLoggedIn, require("./profile"));
zero298
  • 25,467
  • 10
  • 75
  • 100
  • Yes, this is using `callbacks` which I know how to do already, I was wondering how to do it when making it a promise. Or if it is possible? – Taylor Austin Sep 28 '17 at 20:26
  • 1
    @TaylorAustin See my edit. Passport doesn't have support for promises yet. Maybe it will migrate as express does. – zero298 Sep 28 '17 at 20:41
  • So I can't actually use resolve or reject inside of the local strategy correct? – Taylor Austin Sep 28 '17 at 21:29
  • @TaylorAustin no, I don't believe so according to what I'm reading in the documentation and source. – zero298 Sep 29 '17 at 18:00