6

我正在尝试为我的第一个面向公众的节点应用程序设置基本身份验证。我有两种护照策略:1)Facebook 和 2)Twitter。在我了解安全隐患之前,我至少暂时不打算包含电子邮件/密码系统。我已经能够让他们以开箱即用的方式工作,并与 Mongoose 一起创建新用户。

我现在想对社交帐户用户进行重复数据删除。因此,每当有新用户通过 twitter auth 进入时,我想将他们重定向到收集电子邮件的页面。我将返回的令牌和配置文件对象保存为会话变量,并在将表单提交为隐藏字段时在该页面上重用它们。

但是我无法理解如何使用 Passport 来实现这个方面。这是到目前为止我所拥有的代码,其中包含对我尝试对每个部分执行的操作的评论。本质上,我正在检查 twitter 用户是否是老用户,如果不是,我正在设置我将在 /addemail 页面上重用的会话变量,初始化用户对象(以便序列化、反序列化函数可以执行某些操作(不确定我是否理解序列化/反序列化实际上做了什么)。现在,如果用户是新用户,则会话变量 NewTwitterUser 为真,我在 auth/callback url 中检查它以将用户重定向到适当的页面。但这不起作用。

//basic modules and setup
var express = require('express')
    , passport = require('passport')
    , mongoose = require('mongoose')
    , http = require('http')
    , util = require('util')
    , TwitterStrategy = require('passport-twitter').Strategy
    , FacebookStrategy = require('passport-facebook').Strategy
    , path = require('path');

var app = express();


//Mongodb setup
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;

var UserSchema = new Schema({
  provider: String,
  uid: String,
  fb_uid: String,
  twitter_uid: String,
  name: String,
  first_name: String,
  gender: String,
  fb_username: String,
  twitter_username: String,
  profile_pic: String,
  email: String,
  location: String,
  birthday: String,
  created: {type: Date, default: Date.now}
});


var User = mongoose.model('User', UserSchema);
mongoose.connect('MongoHQ db connection here')'


//User Authentication - Twitter
passport.use(new TwitterStrategy({
    consumerKey: 'KEY',
    consumerSecret : 'SECRET',
    callbackURL: "CALLBACKURL",
    passReqToCallback: true
},
    function(req, token, tokenSecret, profile, done){
        User.findOne({twitter_uid: profile.id}, function(err, user){
            if (err) {
            console.log('this is an error 1' + err);
            return done(err);}
            if(user){
                console.log('this user' + user);
                done(null, user);
            } else {
                console.log('this is a new user');
                req.session.token = token;
                req.session.tokenSecret = tokenSecret;
                req.session.profile = profile;
                req.session.newtwitteruser = true;
                var user = new User();
                user.uid = profile.id;
                done(null, user);

                /* This part is commented and is the default code I had if I needed to simply create a Twitter User right here.
                var user = new User();
                user.provider = profile.provider;
                user.uid = profile.id;
                user.twitter_uid = profile.id;
                user.name = profile.displayName;
                user.first_name = profile.displayName[0];
                user.twitter_username = profile._json.screen_name;
                user.profile_pic = profile._json.profile_image_url;
                user.location = profile._json.location;
                user.save(function(err){
                    if(err) {throw err;}
                    else {done(null, user);}
                });*/
            }
        }); 
    }   
));


//User Authentication - Facebook
passport.use(new FacebookStrategy({
    clientID: 'ID',
    clientSecret: 'SECRET',
    callbackURL: "URL"
},
    function(accessToken, refreshToken, profile, done){
        User.findOne({fb_uid: profile.id}, function(err, user){
            if (err) {return done(err);}
            if(user){
                done(null, user);
            } else {
                var user = new User();
                user.provider = profile.provider;
                user.uid = profile.id;
                user.fb_uid = profile.id;
                user.name = profile.displayName;
                user.first_name = profile._json.first_name;
                user.gender = profile._json.gender;
                user.fb_username = profile._json.username;
                user.profile_pic = 'https://graph.facebook.com/' + profile.id + '/picture';
                user.email = profile._json.email;
                user.location = profile._json.location.name;
                user.birthday = profile._json.birthday;
                user.save(function(err){
                    if(err) {throw err;}
                    else {done(null, user);}
                });
            }
        })  
    }   
));


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

passport.deserializeUser(function(uid, done) {
  User.findOne({uid: uid}, function (err, user) {
    done(err, user);
  });
});  


//app configurations
app.configure(function(){
  app.set('port', process.env.PORT || 3000);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.cookieParser("freecookie"));
  app.use(express.session({secret:"freecookie"}));
  app.use(express.static(path.join(__dirname, 'public')));
  app.use(express.errorHandler());
  app.use(passport.initialize());
  app.use(passport.session());
  app.use(app.router);
});


//Basic Routing
app.get('/', function(req, res){
    res.render('home', {title: 'App Title', user: req.user});
});


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

app.get('/auth/twitter/callback', 
    passport.authenticate('twitter', {failureRedirect: '/login' }), 
    function(req, res) {
        if (req.session.newtwitteruser){
        res.redirect('/addemail');}
        else {res.redirect('/');}
    });

app.get('/addemail', function(req, res){
    if (req.session.newtwitteruser){
    res.render('email', {title: 'Add your Email'});}
    else {res.redirect('/');}
});


app.get('/auth/facebook', passport.authenticate('facebook', {scope: ['email', 'user_location', 'user_birthday'] }));

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


app.get('/logout', function(req, res){
  req.logout();
  res.redirect('/');
});



//create the server
var server = http.createServer(app);
server.listen(app.get('port'));


//Checks if a request is authenticated
function ensureAuthenticated(req, res, next) {
  if (req.isAuthenticated()) { return next(); }
  res.redirect('/login')
}
4

1 回答 1

6

我会首先将成功的登录重定向到你的 twitter 路由中的 addemail 函数:

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

然后,在您的 addemail 功能中,我会检查他们是否已经有电子邮件,之后您可以将他们重定向到适当的位置。

  app.get('/addemail', function(req, res){
      if (req.user.email){
           res.render('email', {title: 'Add your Email'});}
      else {res.redirect('/');}
  });
于 2012-11-13T18:38:29.523 回答