invalid_request с пропущенным: область действия с использованием Google Passportjs в Google Oauth2

Возникла проблема в коде аутентификации, который прекрасно работал до начала года, а затем, казалось бы, сломался с небольшими изменениями с моей стороны, я попытался вернуться к предыдущей версии и найти причину безуспешно. Поэтому я ищу помощь в исправлении кода, как он существует сегодня.

Я использую nodejs v0.10.25 Passportjs для обеспечения аутентификации через Google и Facebook. Мои пакеты:

"config-multipaas": "^0.1.0",
"restify": "^2.8.3",
"googleapis": "~2.1.5",
"mocha": "~2.3.3",
"restify-redirect": "~1.0.0",
"sequelize": "~3.12.2",
"mysql": "~2.9.0",
"passport": "~0.3.2",
"passport-facebook": "~2.0.0",
"passport-local": "~1.0.0",
"passport-google-oauth": "~0.2.0",
"sendgrid-webhook": "0.0.4",
"sendgrid": "~2.0.0",
"restify-cookies": "~0.2.0"

Две недели назад, работая над другой частью приложения, я заметил, что функция регистрации пользователей больше не работает ни для одной из этих служб. В частности, код Google Oauth2 возвращает следующую ошибку после страницы начального согласия.

  1. Это ошибка.

Ошибка: invalid_request

Отсутствует обязательный параметр: область

Вот соответствующие части моего определения стратегии:

passport.use(new FacebookStrategy({
    clientID:     siteConfigs.facebook.clientId,
        clientSecret: siteConfigs.facebook.clientSecret,
        callbackURL:  authRoot + 'facebook/callback',
    profileFields: ['id','name','emails', 'picture', 'location', 'birthday', 'gender']
  },
  function(accessToken, refreshToken, profile, done){...}

passport.use(new GooglePlusStrategy({
    clientID:     siteConfigs.google.clientId,
        clientSecret: siteConfigs.google.clientSecret,
        callbackURL:  authRoot + 'google/callback',
    profileFields: ['id','name','emails', 'gender', 'placesLived']
  },
  function(accessToken, refreshToken, profile, done){...}

Механизм функций обратного вызова токена не имеет значения, поскольку процесс никогда не заходит так далеко (проверяется отладчиком узла и инструкциями журнала консоли).

И вот мои конечные точки отдыха:

app.get('/auth/facebook', passport.authenticate('facebook', { session: false, scope: ['email']}));

app.get('/auth/google', passport.authenticate('google', 
        {
        scope: ['profile', 'email'],
        accessType: 'online',
        session: false
        })
);

app.get('/auth/:service/callback', function(req, res, next){
    console.log('Request:', req.path(), req.getQuery());

    passport.authenticate(req.params.service,
    function(err, user, info){
        var returnPath = '/html/authcallback.html';

        if(err)
            return res.redirect({
                pathname: returnPath,
                query: {
                    error: err
                }
            }, next);
        else
            return res.redirect({
                pathname: returnPath,
                query: {
                    id: user.id,
                    created: info
                }
            }, next);
    })(req, res, next);
});

После некоторого первоначального устранения неполадок я использовал подход Google Oauth 2.0 Playground с настраиваемыми конечными точками авторизации и токена (те, которые использовались в моей версии passportjs), а также мой собственный идентификатор клиента и секрет, чтобы сравнить каждое взаимодействие с тем, что делал мой код. Первоначальный запрос на приглашение согласия работает правильно и соответствует Playground, а обратный вызов возвращает соответствующий код, такой как code=4/EUnaIvWpLIiHnKUR9WctOJKQ-_iWZ3_H9YeUYx7bJSo, Но запрос на обмен кода на токен не выполняется. используя отладчик узла, чтобы оценить запрос на перенаправление, который passport-google-oauth отправляет обратно для токена, URL-адрес, который он создает:

https://accounts.google.com/o/oauth2/auth?response_type=code&redirect_uri=http://localhost:8080/auth/google/callback&client_id=<ID>

Сравните это с сопоставимыми запросами от Google Oauth 2.0 Playground, которые выглядят так:

http://www.googleapis.com?code=4/9uaUYjeExmPftgRLsRZ8MCc2e_7YGHow7kvew6Fkypo&redirect_uri=https://developers.google.com/oauthplayground&client_id=<ID>&client_secret=<SECRET>&scope=&grant_type=authorization_code

В моей строке запроса отсутствуют несколько параметров, наиболее важными из которых являются мой код и секрет. Я бы подумал, что сервис Google вернул бы ошибку для тех. Вместо этого он возвращает ошибку для отсутствующего параметра области действия, который на самом деле не нужен для этого шага в процессе (я понятия не имею, почему приложение для детской площадки включает его).

Наконец, я вполне уверен, что это где-то на моей стороне, так как стратегия Facebook также начала давать сбои. После получения согласия происходит странный возврат к моему обратному вызову с несколькими кодами, а затем, наконец, возвращается ошибка TOO_MANY_REDIRECTS.

Итак, у кого-нибудь есть идеи? Еще раз, этот же код работал до начала года, а затем через некоторое время начал давать сбои.

1 ответ

Я задал этот же вопрос пару недель назад и сам наткнулся на ответ. Я рад поделиться этим:

Кажется, я пропустил следующий код после инициализации сервера:

api.use(restify.plugins.queryParser({ mapParams: false }));

Как только я добавил эту строку, я больше не видел ошибку Google, и процесс вернулся к моему коду.

Другие вопросы по тегам