16
votes

Working with Node, Express, and Passport.

Okay, so my team and I are building a REST API for a dual-sided marketplace type application. We have already set up a basic LocalStrategy for email and password login.

We want to make the API user-agent agnostic, so we can use the API via web, Android, or iOS.

But where we are getting confused is with the FB login flow. The question is, what exactly goes on behind the scenes in Passportjs. We have looked into the 'passport-facebook' and 'passport-facebook-token' strategies, and can't really decide which one to go with.

This is my current understanding of the flow:

Passport-token

Passport-facebook

If this is correct, am I better off having the client get the access_token from FB then sending it to me, or just letting FB handle it via redirects and the callback URL?

Passport-token:

passport.use('facebook-token', new FacebookTokenStrategy( {
    clientID: 'xxx',
    clientSecret: 'xxx'
}, function(accessToken, refreshToken, profile, done) {
    // asynchronous
    //console.log("into passport auth");
    process.nextTick(function() {
        User.findOne({'facebook.id': profile.id}, function(error, user) {
            console.log("user is " + JSON.stringify(user));
            console.log("profile is " + JSON.stringify(profile));

            //do user creation stuff etc.

            return done(error, user);
        });
    });
}));

authRouter.post('/facebook', passport.authenticate('facebook-token'), function (req, res) {
    console.log("into controller");
    if (req.user){
        //log the user in since they successfully authenticated with facebook.
        req.login(user);
        res.status(200).end();
    } else {
        res.status(401).end();
    }
});

Passport-facebook:

passport.use('facebook', new FacebookStrategy( {
    callbackURL: "http://75.128.65.176:8080/auth/facebook/callback",
    clientID: 'xxx',
    clientSecret: 'xxx'
}, function(accessToken, refreshToken, profile, done) {
    // asynchronous
    //console.log("into passport auth");
    process.nextTick(function() {
        User.findOne({'facebook.id': profile.id}, function(error, user) {
            console.log("user is " + JSON.stringify(user));
            console.log("profile is " + JSON.stringify(profile));

            //do user creation stuff etc.

            return done(error, user);
        });
    });
}));

// Redirect the user to Facebook for authentication.  When complete,
// Facebook will redirect the user back to the application at
//     /auth/facebook/callback
authRouter.get('/facebook', passport.authenticate('facebook'));

// Facebook will redirect the user to this URL after approval.  Finish the
// authentication process by attempting to obtain an access token.  If
// access was granted, the user will be logged in.  Otherwise,
// authentication has failed.
authRouter.get('/facebook/callback',
    passport.authenticate('facebook', { successRedirect: '/',
                                  failureRedirect: '/login' }));

Any details/elaboration on how this flow actually works would be GREATLY appreciated!

2
I found these examples very useful github.com/philipbrack/express-passport-facebook-token-example (server) and github.com/philipbrack/… (client)srghma

2 Answers

5
votes

Verify if the 2 flows shown are correct.

Yes, they are correct.


Q: I have a list of APIs. How can I protect them with passport-facebook strategy

You have serveral options:

1. Validate the Facebook token

  • Server returns the Facebook token along with the user information
  • Client sends Facebook token each time it calls an API
  • Server validates the Facebook token

More information about how to validate Facebook token here.

2. Using JSON Web Token (JWT)

  • Server returns a JWT after retreiving the Facebook user information
  • Client sends JWT each time it calls an API
  • Server validates the JWT

This way, the server does not have to send the request to Facebook to validate the Facebook token. More information here.


Q: If I'm using passport-facebook-token, how do I tell user to go and login on facebook

Your /api/auth/facebook only accepts Facebook token and returns corresponding HTTP code. Thus, asking the user to go and login in Facebook is the job of the client.

More information about how to create a Facebook login manually here.

4
votes

The client side Facebook redirects are inconvenient when using native iOS and Android Facebook SDKs - as they sometimes redirect to the user installed Facebook app instead. Hence if you would like a really generic API then you should go with passport-facebook-token.