【问题标题】:Saving multiple passportjs providers into same user document in mongodb将多个passportjs提供程序保存到mongodb中的同一个用户文档中
【发布时间】:2015-07-18 17:38:00
【问题描述】:

我遇到了无法解决的问题。我正在使用nodejs开发一个应用程序,使用mongodb、expressjs和passportjs作为我的身份验证中间件。

我目前有 3 种策略:facebook、twitter 和 instagram。我想要实现的是,当用户第一次登录时,如果用户使用一种策略登录并使用另一种策略登录,则将配置文件保存到同一个 mongodb 用户文档中。

这是我的 auth/index.js:

require('./local/passport').setup(User, config);
require('./facebook/passport').setup(User, config);
require('./twitter/passport').setup(User, config);
require('./instagram/passport').setup(User, config);

var router = express.Router();

router.use('/local', require('./local'));
router.use('/facebook', require('./facebook'));
router.use('/twitter', require('./twitter'));
router.use('/instagram', require('./instagram'));

这是,例如,我的 auth/twitter/index.js

var router = express.Router();

router
  .get('/', passport.authenticate('twitter', {
    failureRedirect: '/',
    session: false
  }))
  .get('/callback', passport.authenticate('twitter', {
    failureRedirect: '/',
    session: false
  }), auth.setTokenCookie);

  module.exports = router;

但是我如何将 mongodb _id 传递给这个 auth/twitter/passport.js 以便将其传递给 mongoose 查询并更新用户?像向 auth/twitter 发送 POST 并访问 req.user._id 之类的东西?我不知道该怎么做。

exports.setup = function (User, config) {
  var passport = require('passport');
  var TwitterStrategy = require('passport-twitter').Strategy;
  var TwitterApi = require('twitter');

  passport.use(new TwitterStrategy({
    consumerKey: process.env.TWITTER_CONSUMER_KEY,
    consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
    callbackURL: config.twitter.callbackURL
  },
  function(token, tokenSecret, profile, done) {
    User.findOne({
      'twitter.id_str': profile.id
    }, function(err, user) {
      if (err) {
        return done(err);
      }
      if (!user) {
        user = new User({
          role: 'user',
[...]

非常感谢。

编辑: 这就是我设置 cookie 的方式:

function setTokenCookie(req, res) {
  if (!req.user) return res.json(404, { message: 'Something went wrong,       please try again.'});
  var token = signToken(req.user._id, req.user.role);
  res.cookie('token', JSON.stringify(token));
  res.redirect('/');
}

还有signToken函数:

function signToken(id) {
  return jwt.sign({ _id: id }, config.secrets.session, {     expiresInMinutes: 60*24*30 });
}

为什么 req.user 和 req.session 在我的策略中总是空的?

EDIT2:

我想我可以在调用策略之前使用 auth.isAuthenticated() 函数将用户附加到请求。我所做的是这样的:

router
  .get('/', auth.isAuthenticated(), passport.authenticate('twitter',  auth.isAuthenticated, {
    failureRedirect: '/',
    session: false
  }))
  .get('/callback', auth.isAuthenticated(),  passport.authenticate('twitter', {
    failureRedirect: '/',
    session: false
  }), auth.setTokenCookie);

但现在我遇到了这个问题:

UnauthorizedError: No Authorization header was found

我对 auth/twitter 的请求来自 $window.location。这似乎没有将用户对象附加到请求中,因为当我使用 isAuthenticated() 进行 GET 或 POST 时,用户对象被正确传递。这是我的 isAuthenticated() 函数:

function isAuthenticated() {
  return compose()
    // Validate jwt
    .use(function(req, res, next) {
      // allow access_token to be passed through query parameter as well
      if(req.query && req.query.hasOwnProperty('access_token')) {
        req.headers.authorization = 'Bearer ' + req.query.access_token;
      }
      validateJwt(req, res, next);
    })
    // Attach user to request
    .use(function(req, res, next) {
       User.findById(req.user._id, function (err, user) {
        if (err) return next(err);
        if (!user) return res.send(401);

        req.user = user;
        next();
      });
});

}

【问题讨论】:

    标签: node.js mongodb passport.js


    【解决方案1】:

    您可以在定义护照策略时将passReqToCallback 设置为true。它将发出当前请求,因此当前登录的用户可用于您的回调函数。

    exports.setup = function (User, config) {
      var passport = require('passport');
      var TwitterStrategy = require('passport-twitter').Strategy;
      var TwitterApi = require('twitter');
    
      passport.use(new TwitterStrategy({
        consumerKey: process.env.TWITTER_CONSUMER_KEY,
        consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
        callbackURL: config.twitter.callbackURL,
        passReqToCallback: true
      },
      function(req, token, tokenSecret, profile, done) {
        User.findOne({
          'twitter.id_str': profile.id
        }, function(err, user) {
    
          if (err) return done(err);
    
          if (!user) {
    
            if (req.user) {
    [...]
    

    【讨论】:

    • 我试过了,但是req.user总是空的,req.session也是。在我的浏览器中,我可以检查 cookie 是否设置正确...
    【解决方案2】:

    仅供参考,我刚刚在我的策略中处理了解码 JWT 令牌的问题。我不知道这是否是一个好习惯,但问题是如果请求是使用 $window.location.href 发出的,我没有将我的用户附加到请求中 因此,在我的策略中,我读取 cookie 并即时对其进行解码,以便在数据库中搜索用户。

    谢谢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-26
      • 2018-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-09
      相关资源
      最近更新 更多