Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PassportJs. How can I get facebook redirect uri without redirecting user after call passport.authenticate('facebook')

I have a NodeJs REST Service let's call it - NodeRest on my backend side and AngularJs on my frontend side.

NodeRest is suppose to be used with mobile apps as well as with web apps in my case it is AngularJs app.

The architecture of NodeRest should solve the following problem when using PassportJs:

Server shouldn't redirect user to facebook to authorize when

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

has been called.

In case if it is going to redirect it, the client will not get anything, because callback url is linked to NodeRest httpL//noderest/facebook/callback. Instead it should provide redirect uri, so I can send it back to the client(angularJs, mobile, etc...). Smth like that:

app.get('/auth/facebook', passport.authenticate('facebook', function(redirectUri){ 
//emit socket event to the client with redirect uri as a response data. })); 

I decided to use socket.io as a communication channel during authorize process.

Client:

var socket = io.connect(baseUrl);
    socket.on('auth:facebook:callback:getCalled', function (data) {
      // callback get called on server side.
      // user has been authenicated.
      // so now, user can talk with our NodeRest server to get and post data.      
      var firstName = data.firstName;
      var lastName = data.lastName;
});

$http.get(baseUrl + '/login/facebook').success(function(data, status, headers, config){
      redirectUriToAuthenticate = data;      
      $location.path(data);
});

The client will be responsible to redirect to the facebook/twitter etc, to get the user authorize. Right after that the user will be redirected to callback url.

Server:

app.get('/auth/facebook/callback', function(){
  passport.authenticate('facebook', { successRedirect: '/', failureRedirect: '/login' })
  //socket.io emit event to the client with user data.
  io.sockets.on('connection', function (socket) {
  socket.emit('auth:facebook:callback:getCalled', { data: User });
});

The general idea behind all that stuff is to get authorized from different kind of client apps (mobile, web, desktop, etc.). The client must be able only to get redirect uri to oauth2 providers(facebook, twitter etc.) and redirect to that uri by itself. The NodeRest will take care about further steps (i.e. handle callback and notify client).

I don't know if it is a good solution that I'm working on so any kind of feedback will be more than helpful. I'll be appreciated for any kind of feedback.

Thank you in advance, Julian

like image 826
julianusti Avatar asked Nov 11 '22 22:11

julianusti


1 Answers

Passport is poorly documented on this issue - I struggled with it for a long time as well. I found you can call passport.authenticate(type, fn)(req, res, next), and within fn, you can distinguish between a user who can login and a user who can't. It's up to you to call req.logIn though.

Just FYI, I'm assuming you're using sessions:

module.exports.createSession = function(req, res, next) {
  passport.authenticate('local', function(err, user, info) {
    if (err) {
      res.json(500, {ok: false});
    } else if(!user) {
      // you would probably want to do more work here
      // for example distinguishing between bad login credentials,
      // canceling, users not ready to log in (pending), etc.
      res.json(401, {ok: false});
    } else {
      req.logIn(user, function(err) {
        if (err) {
          res.json(500,{ok: false});
        } else {
          res.json(200, {
            ok:req.isAuthenticated(),
            username: req.user.username,
            email: req.user.email
          });
        }
      });
    }
  })(req, res, next);
};

This is set up for local authentication, but I believe it should work with facebook auth without any changes.

like image 73
Robert Balicki Avatar answered Nov 15 '22 05:11

Robert Balicki