Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

OAuth Authentication with Passport.js and Integration with Jade

DZone's Guide to

OAuth Authentication with Passport.js and Integration with Jade

· Web Dev Zone
Free Resource

Learn how to build modern digital experience apps with Crafter CMS. Download this eBook now. Brought to you in partnership with Crafter Software

Again, we’re talking about a technology used on www.parkuik.com (aren’t you registered yet? ;P)

Although simple registration via username and password is really important (which I’ll do in the near future), nowadays it’s more important to give users website access through OAuth providers such as Facebook or Twitter. There are tons of them, but of course, these two are the best known.

First of all, I must say that there are two major options on node.js world to include OAuth log in: Passport.js and Everyauth. These two are valid options, but I must say that I started with everyauth months ago and it was very buggy. I don’t know how it is right now, but if I have to tell you one of them to use, I’ll go with passport.js (which includes OAuth and simple registration).

So, first of all, you need to register your application to all of OAuth providers you want to use. This is different for each provider, so just go to its website and try it. It’s pretty simple =).

Once you’ve done that, you’ll have two keys. Depending on the OAuth provider they’ll be called different. Facebook uses appId and appSecret, Twitter uses consumerKey and consumerSecret, Github uses appId and appSecret, etc.

Now, install passport on your project:

     
npm install passport

This is not the only thing you have to install. For every oauth provider you want to work with, you must install its module. For Facebook, passport-Facebook, for Twitter, passport-Twitter, etc.

npm instal passport-twitter
npm instal passport-facebook

First of all, I’m used to include these oauth token keys or however-you-want-to-call-them, in a separate file avoiding mixing it with all the app:

var ids = {
  fb: {
    appId: '...',
    appSecret: '...'
  },
  twit: {
    consumerKey: '...',
    consumerSecret: '...'
  },
  github: {
    appId: '...',
    appSecret: '...'
  },
  instagram: {
    clientId: '...',
    clientSecret: '...'
  }
}

You must configure your app and routes to use OAuth. This must be done on the main file, which I usually call app.js. This could be done this way (I’m posting only the Twitter solution because other providers are done the same way):

var conf = require('./config/oauth_providers.js')
app.configure(function(){
  ...
  app.use(express.session({secret: "ihauyd6tqwueuhet7dwqyqwhiwqhuyiod"}));
  app.use(passport.initialize());
  app.use(passport.session());
});
passport.use(new TwitterStrategy({
    consumerKey: conf.twit.consumerKey,
    consumerSecret: conf.twit.consumerSecret,
    callbackURL: callbackURL('twitter')
  },
  function(token, tokenSecret, profile, done) {
    var User = mongoose.model('User');
    User.findOne({providerId: profile.id},
      function(err, user) {
        if (!err && user != null) {
          var ObjectId = mongoose.Types.ObjectId;
          User.update({"_id": user["_id"]}, { $set: {lastConnected: new Date()} } ).exec();
        } else {
          var userData = new User({
            provider: profile.provider,
            providerUsername: profile.username,
            providerId: profile.username + ":" + profile.id,
            created: Date.now(),
            oauthToken: token,
            username: profile.displayName,
            profilePicture: 'https://api.twitter.com/1/users/profile_image?screen_name=' + profile.username +'&size=bigger'
          });
          userData.save(function(err) {
            if (err) console.log(err);
            else console.log('Saving user...');
          });
        }
      }
      );
      var user = { id: profile.id, name: profile.username });
      done(null, user);
  }
));

And now we have to define our callbacks and routes. This includes all the work to insert users and get them from database.

app.get('/auth/twitter', passport.authenticate('twitter'), {scope: 'email'});
app.get('/auth/facebook', passport.authenticate('facebook', {scope: 'email'}));
app.get('/auth/twitter/callback',
  passport.authenticate('twitter', { successRedirect: '/main',
                                    failureRedirect: '/auth/twitter'})
);
app.get('/auth/facebook/callback',
  passport.authenticate('facebook', { successRedirect: '/main',
                                    failureRedirect: '/auth/facebook'})
);
app.get('/logout', isAuthenticated, function(req, res) {
  req.logOut();
  res.redirect('/');
});

Here I’m using Mongoose to work with MongoDB database, but of course, you could use whatever you want.

As you can see in routes defined by express, /logout is used to log the user out. So, just put a link to logout, and it’ll be done.

Other things you can do? define a “isAuthenticated” function (you must come up with a solution that works for you) and use it this way to access protected resources:

     
app.put('/parkings/:id', isAuthenticated, routes.parkings.putParking);

Or you may want to define herlpers to use variables on your jade templates:

var helpers = {};
helpers.auth = function(req, res) {
    var map = {};
    map.isAuthenticated = req.isAuthenticated();
    map.user = req.user;
    return map;
}
app.dynamicHelpers(helpers);

If you want to use it on a Jade template, just call it this way:

     
#{auth.isAuthenticated}

Pretty simple!

Do you know any other solutions? more efficient?

Thanks!

Crafter is a modern CMS platform for building modern websites and content-rich digital experiences. Download this eBook now. Brought to you in partnership with Crafter Software.

Topics:

Published at DZone with permission of Javier Manzano, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}