Как я могу получить доступ к параметру состояния OAuth, используя 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);
});

Однако я не могу получить доступ к этой переменной позднее:

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 - undefined. request.param( "state" ) тоже не работает.

Как я могу получить эту переменную после обратного вызова аутентификации?

Ответы

Ответ 1

Причина, по которой это не работает, заключается в том, что вы передаете состояние как объект вместо строки. Кажется, что паспорт не подчеркивает это значение для вас. Если вы хотите передать объект через параметр состояния, вы можете сделать что-то вроде этого:

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, вы можете получить доступ к параметру state в объекте обратного вызова req.query.

Я не уверен, что состояние приложения кодирования и передача его в параметре state - отличная идея. OAuth 2.0 RFC Раздел 4.1.1 определяет состояние как "непрозрачное значение". Он предназначен для использования в защите CSRF. Лучший способ сохранить состояние приложения между запросом авторизации и обратным вызовом может состоять в следующем:

  • генерирует некоторое значение параметра state (хэш файла cookie, например)
  • сохраняйте состояние приложения с state как идентификатор перед началом запроса авторизации
  • получить состояние приложения в обработчике запроса обратного вызова, используя параметр state, переданный обратно из Google

Ответ 2

Тестирование этого кратко, используя 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);
}

(Выше скопировано из https://github.com/ciaranj/node-oauth/blob/efbce5bd682424a3cb22fd89ab9d82c6e8d68caa/lib/oauth2.js#L123).

Тестирование в консоли с использованием указанного вами параметра состояния:

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

В качестве обходного пути вы можете попробовать JSON-кодирование своего объекта или использовать одну строку, которая должна решить вашу проблему. Затем вы можете получить доступ к state в обработчике запроса обратного вызова через req.query.state. Не забывайте JSON.parse(req.query.state) при доступе к нему.