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

问题描述:

我正在使用Passport.js进行身份验证,并且每个 Google的OAuth2文档,我要传递一个状态变量:

I'm using Passport.js to do authentication, and per Google's OAuth2 documentation, I'm passing in a state variable:

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);
});

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

However, I can't seem to access that variable at a later date:

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

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

request.query.state is undefined. request.param("state") doesn't work, either.

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

How can I get at that variable after the authentication callback?

之所以不起作用,是因为您将状态作为对象而不是字符串进行传递.好像护照不能为您确定该值.如果要通过状态参数传递对象,则可以执行以下操作:

The reason this doesn't work is because you're passing state as an object instead of a string. Seems like passport doesn't stringify that value for you. If you want to pass an object through the state param, you could do something like this:

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);

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

As Rob DiMarco noted in his answer, you can access the state param in the callback req.query object.

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

I'm not sure encoding application state and passing it in the state param is a great idea though. The OAuth 2.0 RFC Section 4.1.1 defines state as "an opaque value". It's intended to be used for CSRF protection. A better way to preserve application state in between the authorization request and the callback might be to:

  1. 生成一些state参数值(例如,cookie的哈希)
  2. 在发起授权请求之前,
  3. 使用state作为标识符保留应用程序状态
  4. 使用从Google传回的state参数在回调请求处理程序中获取应用程序状态
  1. generate some state parameter value (hash of cookie, for example)
  2. persist the application state with state as an identifier before initiating the authorization request
  3. retrieve the application state in the callback request handler using the state param passed back from Google