如何使用Passport.js访问OAuth的状态参数?

Mik*_*ras 21 authentication passport.js

我正在使用Passport.js进行身份验证,根据Google的OAuth2文档,我传入了一个状态变量:

app.get('/authenticate/googleOAuth', function(request, response) {
  passport.authenticate('google', {
    scope:
    [
      'https://www.googleapis.com/auth/userinfo.profile',
      'https://www.googleapis.com/auth/userinfo.email'
    ],
    state: { blah: 'test' }
  })(request, response);
});
Run Code Online (Sandbox Code Playgroud)

但是,我似乎无法在以后访问该变量:

passport.use(new googleStrategy(
{
    clientID: '...',
    clientSecret: '...',
    callbackURL: '...',
    passReqToCallback: true
},
function(request, accessToken, refreshToken, profile, done) {
  console.log('state: ' + request.query.state);
  login(profile, done);
}));
Run Code Online (Sandbox Code Playgroud)

request.query.state未定义.request.param("state")也不起作用.

如何在身份验证回调后获取该变量?

Chr*_*ith 20

这不起作用的原因是因为您将状态作为对象而不是字符串传递.似乎护照不会为您提供该值.如果要通过状态参数传递对象,可以执行以下操作:

passport.authenticate("google", {
  scope: [
    'https://www.googleapis.com/auth/userinfo.profile',
    'https://www.googleapis.com/auth/userinfo.email'
  ],
  state: base64url(JSON.stringify(blah: 'test'))
})(request, response);
Run Code Online (Sandbox Code Playgroud)

正如Rob DiMarco在回答中指出的那样,您可以访问state回调req.query对象中的参数.

我不确定编码应用程序状态并将其传递给state参数是一个好主意.OAuth 2.0 RFC 第4.1.1节将状态定义为"不透明值".它旨在用于CSRF保护.在授权请求和回调之间保留应用程序状态的更好方法可能是:

  1. 生成一些state参数值(例如,cookie的哈希)
  2. state在启动授权请求之前,将应用程序状态作为标识符保留
  3. 使用state从Google传回的param 在回调请求处理程序中检索应用程序状态


Rob*_*rco 1

使用 Node.js v0.8.9 对此进行简单测试,Google OAuth 2.0 授权请求的运行时配置参数最终通过库getAuthorizeUrl中的方法进行格式化node-auth。此方法依赖于querystring.stringify重定向 URL 的格式:

exports.OAuth2.prototype.getAuthorizeUrl= function( params ) {
  var params= params || {};
  params['client_id'] = this._clientId;
  params['type'] = 'web_server';
  return this._baseSite + this._authorizeUrl + "?" + querystring.stringify(params);
}
Run Code Online (Sandbox Code Playgroud)

(以上复制自https://github.com/ciaranj/node-oauth/blob/efbce5bd682424a3cb22fd89ab9d82c6e8d68caa/lib/oauth2.js#L123)。

使用您指定的状态参数在控制台中进行测试:

querystring.stringify({ state: { blah: 'test' }})=>'state='

作为解决方法,您可以尝试对对象进行 JSON 编码,或使用单个字符串,这应该可以解决您的问题。然后,您可以state通过 访问回调请求处理程序中的 , req.query.stateJSON.parse(req.query.state)访问时请记住。