Easy Node Authentication: Twitter

Chris Sevilleja
💬 comments

Welcome to Part 3 of our Easy Node Authentication series. We will be using the foundation of that tutorial to use Twitter authentication with our application. We already have a good application structure for our application packages, user model, application setup and views.

node-auth-twitter Since we set up our application to be as clean and efficient as possible, we will only have to create our Twitter application and add to 4 different files:

Creating the Twitter App and App ID and Secret config/auth.js
Configuring the Passport Twitter Strategy config/passport.js
Generating Routes app/routes.js
Updating Views views/

Since we are already familiar with code organization (the first tutorial) and where we need to add code to authenticate with a social network (the second tutorial), we'll jump right into configuring our Passport Twitter Strategy.

Table of Contents

    Authenticating with Twitter using Passport

    Creating Our Twitter Application

    Let's get the easiest part out of the way and create our Twitter application over at Twitter Developers. We will need the consumer key, consumer secret, and callback URL. twitter-auth-secrets Callback URL: Using http://localhost:8080/auth/twitter/callback wasn't working for me. Twitter liked however so that's what I used.

    Let's add our consumer key and our consumer secret to our auth.js file so that our application knows the secrets it needs to authenticate with Twitter.

    // config/auth.js
    // expose our config directly to our application using module.exports
    module.exports = {
        'facebookAuth' : {
            'clientID'      : 'your-secret-clientID-here', // your App ID
            'clientSecret'  : 'your-client-secret-here', // your App Secret
            'callbackURL'   : 'http://localhost:8080/auth/facebook/callback'
        'twitterAuth' : {
            'consumerKey'       : 'your-consumer-key-here',
            'consumerSecret'    : 'your-client-secret-here',
            'callbackURL'       : 'http://localhost:8080/auth/twitter/callback'
        'googleAuth' : {
            'clientID'      : 'your-secret-clientID-here',
            'clientSecret'  : 'your-client-secret-here',
            'callbackURL'   : 'http://localhost:8080/auth/google/callback'

    Fill in your Twitter key and secret and let's move on.

    Configuring Passport's Twitter Strategy config/passport.js

    We'll make this short and sweet. I'll add comments for where our old code went for local and Facebook authentication.

    // config/passport.js
    // load all the things we need
    var LocalStrategy    = require('passport-local').Strategy;
    var FacebookStrategy = require('passport-facebook').Strategy;
    var TwitterStrategy  = require('passport-twitter').Strategy;
    // load up the user model
    var User       = require('../app/models/user');
    // load the auth variables
    var configAuth = require('./auth');
    module.exports = function(passport) {
        // used to serialize the user for the session
        passport.serializeUser(function(user, done) {
            done(null, user.id);
        // used to deserialize the user
        passport.deserializeUser(function(id, done) {
            User.findById(id, function(err, user) {
                done(err, user);
        // code for login (use('local-login', new LocalStategy))
        // code for signup (use('local-signup', new LocalStategy))
        // code for facebook (use('facebook', new FacebookStrategy))
        // =========================================================================
        // TWITTER =================================================================
        // =========================================================================
        passport.use(new TwitterStrategy({
            consumerKey     : configAuth.twitterAuth.consumerKey,
            consumerSecret  : configAuth.twitterAuth.consumerSecret,
            callbackURL     : configAuth.twitterAuth.callbackURL
        function(token, tokenSecret, profile, done) {
            // make the code asynchronous
        // User.findOne won't fire until we have all our data back from Twitter
            process.nextTick(function() {
                User.findOne({ 'twitter.id' : profile.id }, function(err, user) {
                    // if there is an error, stop everything and return that
                    // ie an error connecting to the database
                    if (err)
                        return done(err);
                    // if the user is found then log them in
                    if (user) {
                        return done(null, user); // user found, return that user
                    } else {
                        // if there is no user, create them
                        var newUser                 = new User();
                        // set all of the user data that we need
                        newUser.twitter.id          = profile.id;
                        newUser.twitter.token       = token;
                        newUser.twitter.username    = profile.username;
                        newUser.twitter.displayName = profile.displayName;
                        // save our user into the database
                        newUser.save(function(err) {
                            if (err)
                                throw err;
                            return done(null, newUser);

    Twitter Passport Profile

    This is where the Twitter Strategy differs from the Facebook and Google Strategies for Passport.

    Passport standardizes the information that is sent back in profile. To see exactly how they lay out their information, see their User Profile docs. As you can see, you can retrieve information like displayName, name, and emails (in an array).

    In my experience, using Passport with Twitter returns some different information. The Twitter information that gets passed back looks like:

            id: '130668248',
            username: 'sevilayha',
            displayName: 'Chris Sevilleja',
            photos: [{ value: 'https://pbs.twimg.com/profile_images/805686037/IMG_0075_normal.JPG' }]

    Getting Email from Twitter: You might ask why we don't get a user's email back from Twitter. In Twitter's eyes, accounts are not really tied to a real email like Facebook or Google are and is less firmly attached to a real-world identity. Email is seen more as a formality to Twitter and accounts are more directly tied to their username.

    Now that we have our application and our Twitter Passport Strategy, we just need to add in our Twitter auth routes and show our user on the profile page.

    Generating Our Routes app/routes.js

    Just like our Facebook authentication, we will need just two routes.

    • /auth/twitter: Send our user to Twitter to authenticate
    • /auth/twitter/callback: Twitter sends our user back to our application here with token and profile information
    // app/routes.js
    module.exports = function(app, passport) {
        // route for home page
        app.get('/', function(req, res) {
            res.render('index.ejs'); // load the index.ejs file
        // route for login form
        // route for processing the login form
        // route for signup form
        // route for processing the signup form
        // route for showing the profile page
        app.get('/profile', isLoggedIn, function(req, res) {
            res.render('profile.ejs', {
                user : req.user // get the user out of session and pass to template
            // route for logging out
        app.get('/logout', function(req, res) {
        // facebook routes
        // =====================================
        // TWITTER ROUTES ======================
        // =====================================
        // route for twitter authentication and login
        app.get('/auth/twitter', passport.authenticate('twitter'));
        // handle the callback after twitter has authenticated the user
            passport.authenticate('twitter', {
                successRedirect : '/profile',
                failureRedirect : '/'
    // route middleware to make sure a user is logged in
    function isLoggedIn(req, res, next) {
        // if user is authenticated in the session, carry on
        if (req.isAuthenticated())
            return next();
        // if they aren't redirect them to the home page

    Our routes are very simple. Just authenticate and handle the callback.

    Showing Our User index.ejs, profile.ejs

    Now that our user is authenticated and saved to the database, they will be redirected to our profile page. The last thing to do is show that user's Twitter information.

    Showing the Login Button

    We'll add this button to our index.ejs file.

    <!-- views/index.ejs -->
    <!doctype html>
        <title>Node Authentication</title>
        <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css"> <!-- load bootstrap css -->
        <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css"> <!-- load fontawesome -->
            body        { padding-top:80px; }
    <div class="container">
        <div class="jumbotron text-center">
            <h1><span class="fa fa-lock"></span> Node Authentication</h1>
            <p>Login or Register with:</p>
            <a href="/auth/twitter" class="btn btn-info"><span class="fa fa-twitter"></span> Twitter</a>

    node-auth-twitter Now we have our login button for Twitter. It will point to our /auth/twitter route and then once a user successfully authenticates, they'll be pushed to the profile page.

    The Profile Page views/profile.ejs

    After a user registers with Twitter, here they are in our database.

    node-auth-twitter-database Let's show their profile page.

    <!-- views/profile.ejs -->
    <!doctype html>
        <title>Node Authentication</title>
        <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css">
        <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css">
            body        { padding-top:80px; word-wrap:break-word; }
    <div class="container">
        <div class="page-header text-center">
            <h1><span class="fa fa-anchor"></span> Profile Page</h1>
            <a href="/logout" class="btn btn-default btn-sm">Logout</a>
        <div class="row">
            <!-- TWITTER INFORMATION -->
            <div class="col-sm-6">
                <div class="well">
                    <h3 class="text-info"><span class="fa fa-twitter"></span> Twitter</h3>
                            <strong>id</strong>: <%= user.twitter.id %><br>
                            <strong>token</strong>: <%= user.twitter.token %><br>
                            <strong>username</strong>: <%= user.twitter.username %><br>
                            <strong>displayName</strong>: <%= user.twitter.displayName %>

    Here is their profile page.



    We're all done. We have configured Passport for Twitter, added our routes, authenticated with Twitter, and shown our user's profile.

    In the next article, we'll deal with Google authentication. Then we move on to the big one. Linking all these social accounts and local account together into one gigantic user profile.

    Chris Sevilleja

    173 posts

    Founder of Scotch.io. Google Developer Expert in Web Technologies. Slapping the keyboard until something good happens.