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 возвращает следующую ошибку после страницы начального согласия.
- Это ошибка.
Ошибка: 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, и процесс вернулся к моему коду.