Search code examples
node.jstwitteroauthexpresspassport-twitter

Twitter authentication with Passport middleware in Node


I'm developing a website with Node.js (using Express framework). In order to use Twitter authentication, I'm using passport module (http://passportjs.org), and his wrapper for Twitter called passport-twitter.

My server-side script is:

/**
 * Module dependencies.
 */

var express = require('express')
  , routes = require('./routes')
  , user = require('./routes/user')
  , http = require('http')
  , path = require('path')
  , passport = require('passport')
  , keys = require('./oauth/keys')
  , TwitterStrategy = require("passport-twitter").Strategy;

var app = express();

app.configure(function(){
  app.set('port', process.env.PORT || 3000);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.favicon());
  app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.cookieParser('foo'));
  app.use(express.session());
  // Initialize Passport!  Also use passport.session() middleware, to support
  // persistent login sessions (recommended).
  app.use(passport.initialize());
  app.use(passport.session());
  app.use(app.router);
  app.use(require('less-middleware')({ src: __dirname + '/public' }));
  app.use(express.static(path.join(__dirname, 'public')));
});

app.configure('development', function(){
  app.use(express.errorHandler());
});

passport.serializeUser(function(user, done) {
  done(null, user.id);
});

passport.deserializeUser(function(id, done) {
  User.findById(id, function (err, user) {
    done(err, user);
  });
});

passport.use(new TwitterStrategy({
    consumerKey: keys.twitterConsumerKey,
    consumerSecret: keys.twitterConsumerSecret,
    callbackURL: "http://local.host:3000/auth/twitter/callback"
  },
  function(token, tokenSecret, profile, done) {
    User.findOrCreate({ twitterId: profile.id }, function (err, user) {
      if (err) { return done(err); }
      else { return done(null, user); }
    });
  }
));

app.get('/', routes.index);
app.get('/contacts', routes.contacts);
app.get('/cv', routes.cv);
app.get('/projects', routes.projects);
app.get('/users', user.list);

// Redirect the user to Twitter for authentication.
// When complete, Twitter will redirect the user back to the
// application at /auth/twitter/callback
app.get('/auth/twitter', passport.authenticate('twitter'));

// Twitter will redirect the user to this URL after approval.  Finish the
// authentication process by attempting to obtain an access token.  If
// access was granted, the user will be logged in.  Otherwise,
// authentication has failed.
app.get('/auth/twitter/callback', 
  passport.authenticate('twitter',
    {
      successRedirect: '/',
      failureRedirect: '/login'
    }
  )
);

http.createServer(app).listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));
});

The URI associated to login is http://local.host:3000/auth/twitter; when I visit it, Twitter shows me the authentication form for linking my account with my own website but, after this step, the following error occurs:

Express
500 ReferenceError: User is not defined

How can I solve this problem? Best regards, Vi.


Solution

  • You have to define your User type somewhere. It looks like you expect this thing User to exist and to have the functions findOrCreate and findById, but you never defined that anywhere. Where are you 'finding' these users? The ones that aren't found, where are they being 'created'? Are you using a database? How do you connect to the database? I think you forgot the "Model" step. You might want to take a look at Mongoose Auth which is like Passport but it plugs directly into Mongoose, which connnects to a Mongo Database