如何在TwitterStrategy,PassportJS中传递数据?

时间:2013-08-22 07:09:24

标签: node.js authentication express passport.js

我有三种用户:

  1. 查看器(登录链接:auth / v / twitter)
  2. 创作者(登录链接:auth / c / twitter)
  3. 管理员(登录链接:auth / a / twitter)
  4. 我还有3个不同的db / collection

    1. c_viewer
    2. c_creator
    3. c_admin
    4. 每种类型的用户都有不同的登录链接。

      现在让我们来看看代码

      var passport = require('passport')
         ,TwitterStrategy = require('passport-twitter').Strategy;
      
      passport.use(new TwitterStrategy({
        consumerKey: config.development.tw.consumerKey,
        consumerSecret: config.development.tw.consumerSecret,
        callbackURL: config.development.tw.callbackURL
      },
      
      function(token, tokenSecret, profile, done) {
        process.nextTick(function(req, res) {
          var query = User.findOne({ 'twId': profile.id});
          query.exec(function(err, oldUser){
            if(oldUser) {
              done(null, oldUser);
            } else {
              var newUser = new User();
              newUser.twId = profile.id;
              newUser.twUsername = profile.username;
              newUser.name = profile.displayName;
              newUser.avatar = profile.photos[0].value;
           -> newUser.age = req.body.creator.age; ???
              newUser.save(function(err) {
                if(err) throw err;
                done(null, newUser);
              });
            };
          });
        });
      }));
      
      app.get('/auth/c/twitter', passport.authenticate('twitter'),
      function(req, res) {
        var userUrl = req.url;
        // codes to pass the userUrl to TwitterStrategy
      });
      app.get('/auth/twitter/callback', 
      passportForCreator.authenticate('twitter', { successRedirect: '/dashboard', failureRedirect: '/' }));
      

      这是我的表格

      <input type="text" name="creator[age]" placeholder="How old are you?">
      <a id="si" class="btn" href="/auth/c/twitter">Sign in</a>
      

      我的问题:

      1。我们可以将<input>数据传递给登录流程吗?所以我们可以在TwitterStrategy中读取输入数据,并保存到数据库中    2. 我们可以从登录网址(auth / c / twitter)获取“c”并将其传递给TwitterStrategy吗?所以我们可以简单地检查不同的db / collection并更改查询。

1 个答案:

答案 0 :(得分:2)

我们的想法是在将用户重定向到Twitter以进行身份​​验证之前存储您的值,并在用户回来后重新使用这些值。

OAuth2包含scope参数,完全适合这种情况。不幸的是,TwitterStrategy基于OAuth1。但我们可以解决它!

下一个技巧是在创建用户时。 在声明策略时不应该这样做(因为你无法访问输入数据),但是稍后,在最后一次身份验证回调中 see here the callback arguments

宣布您的策略:

passport.use(new TwitterStrategy({
  consumerKey: config.development.tw.consumerKey,
  consumerSecret: config.development.tw.consumerSecret,
  callbackURL: config.development.tw.callbackURL
}, function(token, tokenSecret, profile, done) {
  // send profile for further db access
  done(null, profile);
}));

声明您的身份验证网址时(重复/ twitter和v / twitter):

// declare states where it's accessible inside the clusre functions
var states={};

app.get("/auth/c/twitter", function (req, res, next) {
  // save here your values: database and input
  var reqId = "req"+_.uniqueId();
  states[reqId] = {
    database: 'c',
    age: $('input[name="creator[age]"]').val()
  };
  // creates an unic id for this authentication and stores it.
  req.session.state = reqId;
  // in Oauth2, its more like : args.scope = reqId, and args as authenticate() second params
  passport.authenticate('twitter')(req, res, next)
}, function() {});

然后在声明回调时:

app.get("/auth/twitter/callback", function (req, res, next) {
  var reqId = req.session.state;
  // reuse your previously saved state
  var state = states[reqId]

  passport.authenticate('twitter', function(err, token) {
    var end = function(err) {
      // remove session created during authentication
      req.session.destroy()
      // authentication failed: you should redirect to the proper error page
      if (err) {
        return res.redirect("/");
      }
      // and eventually redirect to success url
      res.redirect("/dashboard");
    }

    if (err) {
      return end(err);
    }

    // now you can write into database:
    var query = User.findOne({ 'twId': profile.id});
    query.exec(function(err, oldUser){
      if(oldUser) {
        return end()
      } 
      // here, choose the right database depending on state
      var newUser = new User();
      newUser.twId = profile.id;
      newUser.twUsername = profile.username;
      newUser.name = profile.displayName;
      newUser.avatar = profile.photos[0].value;
      // reuse the state variable
      newUser.age = state.age
      newUser.save(end);
    });
  })(req, res, next)
});