Passport : Twitter Authentication

This post is a continuation of the previous post, … . We will be using twitter as our third-party authentication.

Lets start by visiting https://apps.twitter.com/ . Create an account and sign in. We want to click the ‘Create new App’ button on this page.

Here you will fill out the name, description, website URL, and callback URL. Name and description are up to you, but for the website URL fill out your local servers address. For example, mine is : http://127.0.0.1:3000/ ( for some reason localhost:3000 wont be accepted, so try this instead ). For the callback URL ( we will make this route later ) fill it out as http://127.0.0.1:3000/auth/twitter/callback.

If all goes well, your app should be created. You should be able to go to a tab called keys and access tokens. We are going to copy and paste the consumer key and consumer secret into a file yet to be created:

config/auth.js

module.exports = {
  'twitterAuth': {
    'consumerKey': 'YOUR-TWITTER-CONSUMER-KEY-HERE',
    'consumerSecret': 'YOUR-TWITTER-CONSUMER-SECRET-HERE',
    'callbackURL': 'http://127.0.0.1:3000/auth/twitter/callback'
  }
}

Now lets modify our user model to contain schema for the twitter authentication

app/models/users.js

var userSchema = new mongoose.Schema({
  local: {
    email: String,
    password: String
  },
  twitter: {
    id: String,
    token: String,
    email: String,
    username: String,
    displayName: String
  }
});

// methods...

So, now lets first start by adding our twitter strategy into our config/passport.js. First lets install the passport-twitter module, $ npm i --save passport-twitter

config/passport.js


var User = require('../app/models/users');
var LocalStrategy = require('passport-local').Strategy;
var TwitterStrategy = require('passport-twitter').Strategy;

var authConfig = require('./auth.js');

module.exports = function(passport) {

  // serialize/deserialze user

  // local login/signup

  // twitter strategy

  passport.use('twitter', new TwitterStrategy({
    consumerKey: authConfig.twitterAuth.consumerKey,
    consumerSecret: authConfig.twitterAuth.consumerSecret,
    callbackURL: authConfig.twitterAuth.callbackURL
  }, function(token, tokenSecret, profile, done) {

    User.findOne({ 'twitter.id': profile.id }, function(err, user) {
      if (err) { return done(err); }
      if (user) { return done(null, user) }
      else {
        var newUser = new User();
        newUser.twitter.profileId = profile.id
        newUser.twitter.token = token;
        newUser.twitter.username = profile.username;
        newUser.twitter.displayName = profile.displayName;
        newUser.save(function(err) {
          if (err) { throw err; }
          done(null, newUser);
        });
      }
    });

  }));

}

notice here we are requiring our twitter auth strategy, and our new authConfig module that contains our twitter token/secret.

Next lets add the routes for our twitter auth

app/routes.js

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

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

Lets add a link onto our index page that links to /auth/twitter so we can try out our new addition!

views/index.hbs

<h3>welcome home...</h3>
<a href="/login">Login</a>
<a href="/signup">Signup</a>
<a href="/auth/twitter">Twitter</a>

reset the server and visit the page, it should be working.

lets add an object to pass into our /profile route that will contain the user info, req.user, which is provided by passport

app/routes.js

app.get('/profile', function(req, res) {
  res.render('profile', {
    user: req.user
  });
});

now in our /profile template:

views/profile.hbs

Now when you sign in, either through local or with twitter, you will see info pertaining to the user.