4

Currently I can access messages set in done(null, user, {message: 'ok'}) inside post request via req.authInfolike this:

app.post('/reg', passport.authenticate('local-reg', { session: false }), function (req, res) {        
        console.log(req.authInfo.message); --> 'ok'         
});

Which is very useful.
But how can i access message like this done(null, false, {message: 'username taken'}) in the same fashion, as it seems that passing done(null, false) in passport.authenticate makes it throw 401 unathorised, therefore not forwarding to the route handler itself.
Maybe i misunderstood something?

P.S.: I'm posting through jQuery.post.

Vaibhav Mule
  • 5,016
  • 4
  • 35
  • 52
Max Yari
  • 3,617
  • 5
  • 32
  • 56

2 Answers2

6

You should use custom callback where you have info accessible:

app.post('/req', function(req, res, next) {
  passport.authenticate('local-reg', {session: false}, function(err, user, info) {
    if (err) {
      return next(err);
    }
    if (!user) {
      return res.json(info);
    }
    req.logIn(user, function(err) {
      if (err) {
        return next(err);
      }
      return res.json(info);
    });
  })(req, res, next);
});

req.authInfo gets set only after successful login. If you were using sessions you could use flash messages with redirects, eg:

app.post('/reg', passport.authenticate('local-reg', {
  successRedirect: '/',
  failureRedirect: '/',
  failureFlash: true,
  successFlash: true
}));

app.get('/', function(req, res) {
  res.json(req.flash());
});
vesse
  • 4,871
  • 26
  • 35
  • I am using sessions, but it feels like overkill to connect whole flash messages module just to achieve such a simple task. I'll try a custom callback, it feels less workaround-ish and less code lines to change for me. I will check it out and then accept an answer (just want to hold it open for a bit in case if something goes wrong or if any other interesting answers will occure.). Thank You for reply – Max Yari Apr 16 '15 at 19:53
  • So, this approach seems to work just fine. As a side note, i understant that this is not the point in the answer, but isn't `req.logIn` is used to deserialize user into session, therefore using it in example with `session:false` have no sense? Thank You again) – Max Yari Apr 17 '15 at 22:11
  • I believe `req.logIn` also [sets `req.user`](https://github.com/jaredhanson/passport/blob/298d2452430dd0d1841d417e9c0d0b23e4b06239/lib/http/request.js#L29-L56). Deserializing is not done if `options.session` is `false`. – vesse Apr 20 '15 at 05:10
1

Everyone has their own way of implementing it. In my implementation if there are no errors and login is successful then :

return done(null, {type : true, data: {email: <some email>, role : <some role>, name: <some name>}, token : <some token>});

Whereas if any error or unsuccessful login then i do either

return done(null, {type : false, data: 'Email is already taken.'});

or

return done(null,{type:false, data: err}) 

So this makes my job simpler, i only check the type value and i can use it to pass values as well as error messages.

NarendraSoni
  • 2,210
  • 18
  • 26
  • Yes, i thought about this way, but in fact it's a workaround i.e using succesfull done for both success and fail cases. It will work in my case. But i'm curious, why there is a possibility to pass message in third argument if it's ain't gonna be passed anywhere in case of fail. And the fail case is pretty much a case where this messages required most of all. – Max Yari Apr 16 '15 at 14:01
  • Thanks for suggestion, yet i decided to go with custom callback idea below, as it simply means less code rewrite for me, but it was intresting to see that someone implements it this way also. – Max Yari Apr 17 '15 at 22:12
  • thanks man, that it helped you, let me know if you find better way in implementing same. – NarendraSoni Apr 18 '15 at 14:12