How to use Passport-Facebook login without redirec

2019-04-05 08:30发布

问题:

I'm building a phonegap application which will have nodejs at the server side. I wanted to implement login using passport-facebook strategy but their callbacks specify two routes, /successcallback and /failurecallback. Having a single page application, this makes it very confusing to have users redirected to so and so page.

I don't want to serve static files (index.html, login.html) from the server but rather have them on the client and ask the client to make ajax calls. So far, I'm able to make /auth/facebook call as an AJAX request but I can't receive any response on the same request because the login strategy requires the user to be redirected. I'd rather want to send a user_id or name back to the user on successful login or show him the login form (which is also on the www directory in phonegap) on failure. But the redirection and CORS errors are preventing me from doing this. Is there any way I can implement this? I've looked for this since a few weeks now, but no success. I'd really appreciate your help!

PS: I'd rather avoid having to send all html and static content from the node server.

EDIT: Adding login code for better understanding:

app.get('/userpage', utility.isLoggedIn, function(req, res)
{
    res.send('User:'+req.user);
});

app.get('/', utility.isLoggedIn, function(req, res)
{
    res.redirect('/userpage');
});

app.get('/auth/facebook', passport.authenticate('facebook'));

app.get('/auth/facebook/callback',passport.authenticate('facebook',
{
    successRedirect : '/',
    failureRedirect : '/login'
}));

app.get('/logout', function(req, res)
{
    req.logout();
    res.redirect('/login');
});


utility.isLoggedIn:
function isLoggedIn(req, res, next)
{
    if (req.isAuthenticated())
    return next();

    res.redirect('/login');
}

回答1:

Instead of using the standard redirections offered by passport, you can define your own function which will be executed instead of the redirection. Here's an example of what that code would look like

 passport.authenticate('login', function(err, user, info) {
      if (err) { return next(err); }
      if (!user) { return res.json({ status:"failed", "error": "Invalid credentials" }); }

// req / res held in closure
      req.logIn(user, function(err) {
          if (err) { return next(err); }

          return res.json({ "status":"success"});
      })
 })(req, res, next);


回答2:

You can't do that with facebook oAuth, but Facebook provides another login solution where you can code your client app to request a token, that you can later validate on the server with passport-facebook-token.

This way you can use the advantages of passport for persistent sessions, without that annoying redirection.