在Node中使用Passport中间件进行Twitter身份验证

时间:2012-10-14 17:46:15

标签: node.js twitter oauth express passport-twitter

我正在使用Node.js开发一个网站(使用Express框架)。为了使用Twitter身份验证,我使用的是passport模块(http://passportjs.org),而他的Twitter包装器名为passport-twitter

我的服务器端脚本是:

/**
 * 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'));
});

与登录相关联的URI为http://local.host:3000/auth/twitter;当我访问它时,Twitter向我显示了将我的帐户与我自己的网站链接的身份验证表单,但在此步骤之后,会出现以下错误:

Express
500 ReferenceError: User is not defined

我该如何解决这个问题? 最好的问候,Vi。

5 个答案:

答案 0 :(得分:7)

您必须在某处定义用户类型。看起来你希望这个东西User存在并且具有函数findOrCreatefindById,但你从未在任何地方定义过它。你在哪里“找到”这些用户?那些没有找到的,他们在哪里“被创造”?你在使用数据库吗?你如何连接到数据库?我想你忘了“模特”一步。您可能需要查看Mongoose Auth,它类似于Passport,但它会直接插入Mongoose,它连接到Mongo数据库

答案 1 :(得分:3)

这是我在遇到同样的错误时所做的,即User未定义:

passport.use(new TwitterStrategy({
    consumerKey: keys.twitterConsumerKey,
    consumerSecret: keys.twitterConsumerSecret,
    callbackURL: "http://local.host:3000/auth/twitter/callback"
  },
  function(token, tokenSecret, profile, done) {
    done(null, profile);
  }
));

答案 2 :(得分:0)

在Kraken中为Passport集成BeatsMusic OAuth2策略时遇到了同样的问题。看起来各种Kraken Passport集成策略的示例使用相同的简单示例文档,该文档未明确讨论User对象(可理解)。

我发现(通过挖掘护照策略示例@ https://github.com/krakenjs/kraken-examples/tree/master/with.passport),用户打算成为基于Mongoose模型架构的模型,并且还配置了https://github.com/drudge/mongoose-findorcreate插件。

在我加入User = require('../PATH_TO/user')并将此插件添加到用户模型后,瞧!没有更多的错误:)

听起来你不需要数据库功能,所以你可能不喜欢删除身份验证。

希望这有助于其他有类似问题的人。

答案 3 :(得分:0)

我认为api还没有为不需要用户数据库集成的情况做好准备。我的解决方案是忽略done()函数并重定向到成功页面。

passport.use(new TwitterStrategy({
    consumerKey: keys.twitterConsumerKey,
    consumerSecret: keys.twitterConsumerSecret,
    callbackURL: "http://local.host:3000/auth/twitter/callback"
  },
  function(token, tokenSecret, profile, done) {
    //done(null, profile);
    this.redirect('/auth/success');
  }
));

答案 4 :(得分:0)

要进一步解释Max的答案:“你需要自己创建User

Read Here

TL:DR - 基本上你必须有一个用于设置用户和验证用户的用户密码,它需要一个mongoose db后端,这实际上很容易配置。

基本上创建这个中间件:

var mongoose = require('mongoose');
var bcrypt   = require('bcrypt-nodejs');

// define the schema for our user model
var userSchema = mongoose.Schema({

    local            : {
        email        : String,
        password     : String,
        group        : String,
    },
    facebook         : {
        id           : String,
        token        : String,
        email        : String,
        name         : String
    },
    twitter          : {
        id           : String,
        token        : String,
        displayName  : String,
        username     : String
    },
    google           : {
        id           : String,
        token        : String,
        email        : String,
        name         : String
    }

});

// methods ======================
// generating a hash
userSchema.methods.generateHash = function(password) {
    return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
};

// checking if password is valid
userSchema.methods.validPassword = function(password) {
    return bcrypt.compareSync(password, this.local.password);
};

// create the model for users and expose it to our app
module.exports = mongoose.model('User', userSchema);