与Passport.js和Restify的会话问题

时间:2015-02-19 02:09:30

标签: node.js session authentication passport.js restify

我正在尝试开发一个简单的概念证明,它使用Passport的Google身份验证策略与Restify和Bookshelf.js。我希望这个简单的应用程序能够解析/ sessions / google路由(调用Google身份验证)并在成功验证后重定向到/ sessions / googleReturn。对于这个简单的概念证明,请假设与User模型对应的表包含正在进行身份验证的用户的记录。

以下是我正在尝试的代码。目前,此代码在验证后导致无限重定向循环。如果我删除/ sessions / googleReturn路线中的'passport.authenticate('google',{failureRedirect:'/'})'行,/ sessions / googleReturn会解析,但req.user会返回一个空对象。我猜我没有初始化会话或正确地将会话绑定到护照。护照方法中的console.log输出似乎被抑制,这使得调试变得困难。如果我用快速/快速会话替换Restify /客户端会话,我的概念证明是有效的。我究竟做错了什么?提前谢谢。

var restify = require('restify');
var sessions = require('client-sessions');
var passport = require('passport');
var GoogleStrategy = require('passport-google').Strategy;
var User = require('./models/user'); // Bookshelf model

var server = restify.createServer({ name: 'test-server' });

server
  .use(sessions({
    cookieName: 'user',
    secret: 'topsecret',
    duration: 365 * 24 * 60 * 60 * 1000}))
  .use(passport.initialize())
  .use(passport.session());

passport.serializeUser(function(user, done) {
  console.log('serialize user:', user);
  done(null, user.id);
});

passport.deserializeUser(function(id, done) {
  console.log('deserialize user:', id);
  new User({ id: id }).fetch({require: true}).then(function(user) {
    done(null, user);
  }).catch(function(err) {
    done(err, null);
  });
});

passport.use(
  new GoogleStrategy({
    returnURL: 'http://localhost:3000/sessions/googleReturn',
    realm: 'http://localhost:3000'
  },
  function(identifier, profile, done) {
    console.log('Hello from the verify callback', identifier, profile);
    new User({ email: profile.emails[0].value }).fetch({require: true}).then(function(user) {
      done(null, user);
    }).catch(function(err) {
      done(err, null);
    });
  }
));

server.listen(3000, function () {
  console.log('%s listening at %s', server.name, server.url);
});

server.get('/', function(req, res, next) {
  res.send(200, 'Hello from root route.');
  return next();
});

server.get(
  '/sessions/google',
  passport.authenticate('google')
);

server.get(
  '/sessions/googleReturn',
  passport.authenticate('google', { failureRedirect: '/' }),
  function(req, res, next) {
    console.log('Session user data?', req.user);
    res.send(200, 'Hello from Google auth return route.');
    return next();
  }
);

4 个答案:

答案 0 :(得分:0)

如果您看到来自google auth的回复,则说302暂时移动了。 谷歌openid也被弃用,取而代之的是google-plus登录。

Google OpenID:https://developers.google.com/accounts/docs/OpenID

如果您想使用,可以使用google-plus登录的npm模块。

npm install passport-google-plus https://www.npmjs.com/package/passport-google-plus

答案 1 :(得分:0)

当我遇到这个问题时,我发现我需要确保restify准备解析查询参数。我的重定向循环消失了。

server = restify.createServer({ name: 'test-server' });
server.use(restify.queryParser());

答案 2 :(得分:0)

如果你正在使用restify,它的重定向功能会略有不同。您可以简单地添加覆盖,例如:

function patchRedir(){
    return function( req, res, next ){
        res.redirect = function( url ){
            res.header( 'Location', url )
            res.send( 302 )
        }
        return next()
    }
}
server.get('/auth/facebook/callback', patchRedir(), passport.authenticate('facebook', { failureRedirect: '/login' }), ( req, res, next ) => {
    // Successful
    res.send( 200 )
})

答案 3 :(得分:0)

client-sessions包在req中设置会话对象,其名称与会话cookie名称相同。它默认为session,这意味着req.session对象可用。我发现passport.js需要这样的对象(实际上是passport-oauth2),以便将用户保存到会话中。因此,通过更改cookieName配置中的client-sessions,您可以在req中为会话对象使用不同的密钥!

GoogleStrategy使用passport-oauth2作为基础,您可以查看确实需要req.session的来源: https://github.com/jaredhanson/passport-oauth2/blob/master/lib/state/session.js

我发现了两种解决方案:

  1. 使用session Cookie名称
  2. 制作一个小型的通用处理程序"为了你解决服务器并在之后设置会话但之前设置护照:

    server.use((req, res, next) => {
        req.session = req.your_cookie_name;
        return next();
    });