Authentication with Node Passport

Does anyone have any good examples of utilizing Node Passport for authentication with my Ionic App?

All of the examples I see for Node Passport have server side views. Are there any good tutorials out there for HTTP or front-end angular app methods of doing it?

I want to use Facebook, Linkedin, and just username/pw with Node passport. Any help is appreciated, thanks!

You could use any of those tutorials.
But do not implement the template stuff.

Use expressjs to handle requests.
For an request you get the request object (req) and the response object (res).

Passport is something like a middleware -> something that is executed after the server receives the request, but before you will handle it.
So in your handling of the requests you need no rendering engine and so on -> make res.send(status, repsonseContent); and the server will send the response.

like this example:

start server:

var express = require('express'),
app = express();

app.listen(8000, function () {
    console.log('NodeJS Server hört auf Port 8000');
});

Handle a simple post request:

app.post('/api/login', function (req, res) {
    // req -> req object
    // res -> res to finish request
    // do something 
    res.send(200, {
       message: 'loggedIn'
    });    
});

You should install additional packages for expressjs:
body-parser -> access request body simple over req.body.KEY
method-override -> now you can also send put and delete requests

Then you little server would looks like this:

var express = require('express'),
     bodyParser = require('body-parser'),
     methodOverride = require('method-override'),
     app = express();

app.use(bodyParser.json()); // handle json request data
app.use(bodyParser.urlencoded({
    extended: true
})); // possibility to handle also form-param requests
app.use(methodOverride()); // HTTP PUT and DELETE support

app.listen(8000, function () {
    console.log('NodeJS Server hört auf Port 8000');
});

For express there are 3 types of parameter:

  1. url parameters from a url-scheme
    like app.use(’/login/:type’, …) params.type = the url parameter of the type

  2. ordinary query parameters like 'http://…/test?param1=xxxxx&value1=yyyyy’
    you can do req.query.param1 to get the values.

  3. request-data like sending ajax request or json request
    do req.body.KEY to get the value

I have a Sails.js app running up on my local machine. I understand that it’s a middleware, but for example with Facebook:

I call the auth/facebook route with $http

and I get a 500 error. I (think) passport is supposed to make a call to facebook using the Facebook Strategy and open up a popup window, but instead I’m having issues.

I suppose I could completely ignore Passport for Facebook, and only use it for user / pw, but then that wouldn’t be using it to it’s full potential. How do I have passport open facebook in a popup window for me, when the strategy is coming from the server, and my app is a front-end app hosted elsewhere?

Hopefully that makes sense.

I had the same problem last week. But i implemented my authentication without passport. because i have a generic url-scheme and passport are making bigger nodeJS APIs a mess.

But to clearify, there are three steps for authentication:

1 define an api endpoint for facebook login

  • e.g. /authentication/facebook
  • on this url you add the facebook strategy where you pass appid, app secret and redirect url

2 redirect url

  • e.g. http://yourapisite/authentication/facebookCallback
  • on this url you handle the response from facebook -> after facebook has finished with user-login, set permissions, or aborting the process it redirects to this url
  • add an endpoint for that url.
  • in success case facebook adds an query-parameter to your url like “?code=xxxxxxxxx”
  • in error case you do not get the code query -> authorization failed
  • now you can get accesstoken with the “code”
  • and with the accessToken you can make othe API requests like, getting the users profile, image,…
  • if you successfully get the accesstoken -> you know that the user is correctly logged in with facebook
    -> you can set him as “loggedIn” in your db or create the user if it is the first login

3 Redirects for success or error case

  • if something failed or everything works fine-> redirect to another url or put a parameter at the current url like '?success"

In you app you should use the inappbrowser plugin to open your initial facebook login url of your API.
Do not forget to include that plugin!

use $window.open to open a new childbrowser window with /authentication/facebook
if everything is working -> you api should redirect automatically to facebook and if the user canceld or is finished jumps back to your callback url.

Now you have to look how the url in the external browser window is changing, because you should close the window if everything is fine.

-> Check if the url is your success or error callback or facebook error page -> close the window

  • if success handle login

You can see here:

passport makes it a little bit easier to get tokens and the profile.
you only need the 2 endpoints, and the authentication handling for create a user or make login.

Yes it seems like - at least for Ionic - Passport might be more of a headache than it is worth. I just wanted it for all of the platforms it supports ( 140+ or something like that ), but it looks like I may just have to pick the ones I want and implement individual $http implementations of each of those

yeah passport and all other stuff is not optimized for rest APIs or hybrid mobile apps.

I am searching for a more native solution. Native apps are opening the facebook app or a new browser window and get informed if authorization was successfully. But i do not know how they make it.

Because you could implement such thing, but how you API could be sure that the user is loggedin and not faking a request.

I think native apps have something like that:
On the app side -> handle social login
-> get informed if social login worked -> inform backend (i do not know how they secure this part)

Hybrid apps:
App side -> open child browser -> backend handles login -> inform frontend (app)

In many cases the passport login possibilities are not that good. Look at the github repositories from goolge, facebook strategy… many of the open issues are very annoying.

The easiest social login is google.
They have a nodejs sdk (in beta state).

It is very easy to use. For facebook it took me half a day to find out anything i need :slight_smile: .

Geetz, bengtler

1 Like

I am doing exactly the same server side, it work perfect on angular with a simple GET form route ej:"/users/facebook",
It logs in and I get the user and token perfect.

With ionic I decided to use InAppBrowser to open a browser and facilitate logging

When the callbackURL ej:"/users/facebook/callback"returns the response in the browser window. To capture the data of the user, I veriry if the URL have indexOf (‘facebook/callback’) and then make $http get to this address to get the user info.

Route in server

router.get('/facebook/callback', function (req, res, next) {
      passport.authenticate('facebook', function (err, user, info) {
        if (err) {
          return next(err);
        }
        if (!user) {
          return res.status(401).json({
            err: info
          });
        }
        req.logIn(user, function (err) {
          if (err) {
            return res.status(500).json({
              err: 'Could not log in user'
            });
          }
          var token = jwt.sign(user, config.secretKey, {
            expiresIn: "35d"
          });
          res.status(200).json({
            status: 'Login successful!',
            success: true,
            token: token
          });
        });
      })(req, res, next);
    });

Controller in Ionic

$ionicPlatform.ready(function () {
        $scope.OpenBrowser = function () {
            $cordovaInAppBrowser.open('http://10.21.0.78:3443/users/facebook/', '_blank', options)
                .then(function (event) {
                    $scope.error = '';
                    $scope.event = event;
                })
                .catch(function (event) {
                    $scope.error = event;
                    $scope.event = '';
                });
        };
    });

$rootScope.$on('$cordovaInAppBrowser:loadstop', function (e, event) {
      
        var OnLoad = JSON.stringify(event);
        $scope.EventOnLoad = "load_start";
        if (OnLoad.indexOf("facebook/callback") != -1) {
            $scope.ShowFacebook = false;
            $scope.load( 'http://10.21.0.78:3443/users/facebook/callback');
            // Do request again but to callback route to get the user info.
            $http({
                method: 'GET',
                url: users/facebook/callback
            }).then(function successCallback(response) {
                var res = response.data;
                $scope.result = res;
                //here your code confirmation in my case 'Login successful!'
                if (res.status === 'Login successful!') {
                    
                    $localStorage.storeObject('userinfo', res);
                    //now the user has confirm and go to use the app
                    $state.go('homePage');
                    
                }


        }, function errorCallback(response) {
            
        });

            $cordovaInAppBrowser.close();
        }
    });
1 Like