Invalid_grant пытается получить токен oAuth из google
Я продолжаю получать ошибку invalid_grant
при попытке получить токен oAuth от Google для подключения к своим контактам api. Вся информация верна, и я трипл проверил это так, как будто это было в тупике.
Кто-нибудь знает, что может вызвать эту проблему? Я попытался настроить для него другой идентификатор клиента, но я получаю тот же результат, я попытался подключить много разных способов, включая проверку подлинности силы, но все тот же результат.
Ответы
Ответ 1
Я столкнулся с этой проблемой, когда я явно не запрашивал "автономный" доступ при отправке пользователя в OAuth "Вы хотите дать этому приложению разрешение касаться ваших вещей?" стр.
Убедитесь, что в запросе указывается access_type = offline.
Подробности здесь: https://developers.google.com/accounts/docs/OAuth2WebServer#offline
(Также: я думаю, что Google добавила это ограничение в конце 2011 года. Если у вас есть старые токены до этого времени, вам нужно будет отправить своих пользователей на страницу разрешений для авторизации автономного использования.)
Ответ 2
Я столкнулся с этой же проблемой, несмотря на указание "offline" access_type
в моем запросе в соответствии с ответом bonkydog. Короче говоря, я нашел, что описанное здесь решение сработало для меня:
https://groups.google.com/forum/#!topic/google-analytics-data-export-api/4uNaJtquxCs
По сути, когда вы добавляете клиента OAuth2 в свою консоль Google API, Google предоставит вам "Идентификатор клиента" и "Адрес электронной почты" (при условии, что вы выбрали "webapp" в качестве вашего типа клиента). И, несмотря на то, что Google вводит в заблуждение соглашения об именах, они ожидают, что вы отправите "Адрес электронной почты" в качестве значения параметра client_id
при обращении к их API OAuth2.
Это применимо при вызове обоих этих URL:
Обратите внимание, что вызов первого URL-адреса будет успешным, если вы вызываете его с помощью своего "Идентификатора клиента" вместо вашего "Адрес электронной почты" . Однако использование кода, возвращенного с этого запроса, не будет работать при попытке получить токен-носитель со второго URL-адреса. Вместо этого вы получите сообщение об ошибке "Ошибка 400" и "invalid_grant".
Ответ 3
Хотя это старый вопрос, кажется, что многие все еще сталкиваются с этим - мы провели дни напролет, отслеживая это сами.
В спецификаторе OAuth2 "invalid_grant" - это своего рода ошибка для всех ошибок, связанных с недействительными/истекшими/отмененными токенами (токен предоставления или обновления).
Для нас проблема была двукратной:
-
Пользователь активно отменил доступ к нашему приложению
Имеет смысл, но получите следующее: через 12 часов после отзыва Google перестает отправлять сообщение об ошибке в свой ответ:
"error_description" : "Token has been revoked."
Это скорее вводит в заблуждение, потому что вы будете считать, что сообщение об ошибке всегда есть, что не так. Вы можете проверить, есть ли у вашего приложения доступ на странице .
-
Пользователь имеет reset/восстановил свой пароль Google
В декабре 2015 года Google изменил свое поведение по умолчанию, чтобы сбрасывать пароль для пользователей, не относящихся к Google Apps, автоматически отменяет все токены пользователей, обновляющие токены. При отзыве сообщение об ошибке следует тому же правилу, что и раньше, поэтому вы получите только "error_description" в течение первых 12 часов. Кажется, нет никакого способа узнать, был ли пользователь вручную отменен доступ (намеренный), или это произошло из-за пароля reset (побочный эффект).
Кроме того, существует множество других потенциальных причин, которые могут вызвать ошибку:
- Серверные часы/время не синхронизированы
- Не разрешено для автономного доступа
- Дросселировано Google
- Использование истекших токенов обновления
- Пользователь неактивен в течение 6 месяцев
- Использовать электронную почту рабочего лица вместо идентификатора клиента
- Слишком много токенов доступа за короткое время
- Клиентский SDK может быть устаревшим
- Неверный/неполный токен обновления
Я написал короткую статью, в которой кратко излагается каждый элемент с некоторыми инструкциями по отладке, чтобы помочь найти виновника. Надеюсь, что это поможет.
Ответ 4
Я столкнулся с той же проблемой. Для меня я исправил это, используя адрес электронной почты (строка, которая заканчивается на... @developer.gserviceaccount.com) вместо идентификатора клиента для значения параметра client_id. Именование, установленное Google, путается здесь.
Ответ 5
У меня было такое же сообщение об ошибке 'invalid_grant', и это произошло потому, что
authResult [ 'код']
отправить с клиентской стороны javascript не получил корректно на сервере.
Попробуйте вернуть его с сервера, чтобы убедиться, что он правильный, а не пустая строка.
Ответ 6
Моя проблема заключалась в том, что я использовал этот URL:
https://accounts.google.com/o/oauth2/token
Когда я должен был использовать этот URL-адрес:
https://www.googleapis.com/oauth2/v4/token
Это была проверка учетной записи службы, которая хотела автономный доступ к механизму хранения.
Ответ 7
Если вы используете библиотеку scribe, просто настройте автономный режим, например, bonkydog
вот код:
OAuthService service = new ServiceBuilder().provider(Google2Api.class).apiKey(clientId).apiSecret(apiSecret)
.callback(callbackUrl).scope(SCOPE).offline(true)
.build();
https://github.com/codolutions/scribe-java/
Ответ 8
Используя клиент clientId для Android (без client_secret), я получал следующий ответ об ошибке:
{
"error": "invalid_grant",
"error_description": "Missing code verifier."
}
Я не могу найти документацию для поля "code_verifier", но я обнаружил, что если вы установите равные значения в запросах авторизации и токена, это приведет к удалению этой ошибки. Я не уверен, какой должна быть предполагаемая стоимость, или если она должна быть безопасной. Он имеет минимальную длину (16 символов), но я обнаружил, что установка null
также работает.
Я использую AppAuth для запроса авторизации в своем Android-клиенте, который имеет функцию setCodeVerifier()
.
AuthorizationRequest authRequest = new AuthorizationRequest.Builder(
serviceConfiguration,
provider.getClientId(),
ResponseTypeValues.CODE,
provider.getRedirectUri()
)
.setScope(provider.getScope())
.setCodeVerifier(null)
.build();
Вот пример запроса токена в node:
request.post(
'https://www.googleapis.com/oauth2/v4/token',
{ form: {
'code': '4/xxxxxxxxxxxxxxxxxxxx',
'code_verifier': null,
'client_id': 'xxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com',
'client_secret': null,
'redirect_uri': 'com.domain.app:/oauth2redirect',
'grant_type': 'authorization_code'
} },
function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log('Success!');
} else {
console.log(response.statusCode + ' ' + error);
}
console.log(body);
}
);
Я тестировал, и это работает как с https://www.googleapis.com/oauth2/v4/token
, так и https://accounts.google.com/o/oauth2/token
.
Если вместо этого вы используете GoogleAuthorizationCodeTokenRequest
:
final GoogleAuthorizationCodeTokenRequest req = new GoogleAuthorizationCodeTokenRequest(
TRANSPORT,
JSON_FACTORY,
getClientId(),
getClientSecret(),
code,
redirectUrl
);
req.set("code_verifier", null);
GoogleTokenResponse response = req.execute();
Ответ 9
Это глупый ответ, но проблема для меня в том, что я не понял, что мне уже был выпущен активный токен OAuth для моего пользователя Google, который я не смог сохранить. Решение в этом случае - перейти на консоль api и reset секрет клиента.
Есть много других ответов на SO для этого эффекта, например
Reset Client Secret OAuth2 - Нужно ли клиентам повторно предоставлять доступ?
Ответ 10
Возможно, вам придется удалить устаревший/недействительный ответ OAuth.
Кредит: node.js ошибка google oauth2 перестала работать с invalid_grant
Примечание. Ответ на OAuth также станет недействительным, если пароль, используемый в первоначальной авторизации, был изменен.
Если в среде bash вы можете использовать следующее, чтобы удалить устаревший ответ:
rm /Users/<username>/.credentials/<authorization.json>
Ответ 11
Существуют две основные причины ошибки invalid_grant, которую вы должны заботиться до запроса POST для Обновить токен и токен доступа.
- Заголовок запроса должен содержать "content-type: application/x-www-form-urlencoded"
- Ваша полезная нагрузка для запроса должна быть закодирована в форме данных формы, не отправлять как объект json.
RFC 6749 OAuth 2.0 определил invalid_grant как:
Предоставленный авторизационный грант (например, код авторизации, учетные записи владельца ресурса) или токен обновления недействителен, истек, отменен, не соответствует URI перенаправления, используемому в запросе авторизации, или был выдан другому клиенту.
Я нашел еще одну хорошую статью, здесь вы найдете много других причин этой ошибки.
https://blog.timekit.io/google-oauth-invalid-grant-nightmare-and-how-to-fix-it-9f4efaf1da35
Ответ 12
на этом сайте
console.developers.google.com
эта консольная плата выбирает ваш проект, вводя клятву присяги.
oauth callback url будет перенаправляться, когда успех oauth
Ответ 13
Рассмотрев и попробовав все другие способы здесь, вот как я решил проблему в nodejs с модулем googleapis
в сочетании с модулем request
, который я использовал для извлечения токенов вместо предоставленного getToken()
метод:
const request = require('request');
//SETUP GOOGLE AUTH
var google = require('googleapis');
const oAuthConfigs = rootRequire('config/oAuthConfig')
const googleOAuthConfigs = oAuthConfigs.google
//for google OAuth: https://github.com/google/google-api-nodejs-client
var OAuth2 = google.auth.OAuth2;
var googleOAuth2Client = new OAuth2(
process.env.GOOGLE_OAUTH_CLIENT_ID || googleOAuthConfigs.clientId,
process.env.GOOGLE_OAUTH_CLIENT_SECRET || googleOAuthConfigs.clientSecret,
process.env.GOOGLE_OAUTH_CLIENT_REDIRECT_URL || googleOAuthConfigs.callbackUrl);
/* generate a url that asks permissions for Google+ and Google Calendar scopes
https://developers.google.com/identity/protocols/googlescopes#monitoringv3*/
var googleOAuth2ClientScopes = [
'https://www.googleapis.com/auth/plus.me',
'https://www.googleapis.com/auth/userinfo.email'
];
var googleOAuth2ClientRedirectURL = process.env.GOOGLE_OAUTH_CLIENT_REDIRECT_URL || googleOAuthConfigs.callbackUrl;
var googleOAuth2ClientAuthUrl = googleOAuth2Client.generateAuthUrl({
access_type: 'offline', // 'online' (default) or 'offline' (gets refresh_token)
scope: googleOAuth2ClientScopes // If you only need one scope you can pass it as string
});
//AFTER SETUP, THE FOLLOWING IS FOR OBTAINING TOKENS FROM THE AUTHCODE
const ci = process.env.GOOGLE_OAUTH_CLIENT_ID || googleOAuthConfigs.clientId
const cs = process.env.GOOGLE_OAUTH_CLIENT_SECRET || googleOAuthConfigs.clientSecret
const ru = process.env.GOOGLE_OAUTH_CLIENT_REDIRECT_URL || googleOAuthConfigs.callbackUrl
var oauth2Client = new OAuth2(ci, cs, ru);
var hostUrl = "https://www.googleapis.com";
hostUrl += '/oauth2/v4/token?code=' + authCode + '&client_id=' + ci + '&client_secret=' + cs + '&redirect_uri=' + ru + '&grant_type=authorization_code',
request.post({url: hostUrl}, function optionalCallback(err, httpResponse, data) {
// Now tokens contains an access_token and an optional refresh_token. Save them.
if(!err) {
//SUCCESS! We got the tokens
const tokens = JSON.parse(data)
oauth2Client.setCredentials(tokens);
//AUTHENTICATED PROCEED AS DESIRED.
googlePlus.people.get({ userId: 'me', auth: oauth2Client }, function(err, response) {
// handle err and response
if(!err) {
res.status(200).json(response);
} else {
console.error("/google/exchange 1", err.message);
handleError(res, err.message, "Failed to retrieve google person");
}
});
} else {
console.log("/google/exchange 2", err.message);
handleError(res, err.message, "Failed to get access tokens", err.code);
}
});
Я просто использую request
, чтобы сделать запрос api через HTTP, как описано здесь:
https://developers.google.com/identity/protocols/OAuth2WebServer#offline
POST /oauth2/v4/token HTTP/1.1
Host: www.googleapis.com
Content-Type: application/x-www-form-urlencoded
code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=8819981768.apps.googleusercontent.com&
client_secret={client_secret}&
redirect_uri=https://oauth2.example.com/code&
grant_type=authorization_code
Ответ 14
Попробуйте изменить URL-адрес для запроса
https://www.googleapis.com/oauth2/v4/token
Ответ 15
Для будущих людей... Я прочитал много статей и блогов, но мне повезло с решением ниже...
GoogleTokenResponse tokenResponse =
new GoogleAuthorizationCodeTokenRequest(
new NetHttpTransport(),
JacksonFactory.getDefaultInstance(),
"https://www.googleapis.com/oauth2/v4/token",
clientId,
clientSecret,
authCode,
"") //Redirect Url
.setScopes(scopes)
.setGrantType("authorization_code")
.execute();
Этот блог описывает различные случаи, когда возникает ошибка "invalid_grant".
Наслаждаться!!!
Ответ 16
для меня проблема была на странице учетных данных Google... я создал еще один... и решил проблему....
Ответ 17
для меня я должен был убедиться, что redirect_uri
является точным соответствием тому, что в консоли разработчика. Authorised redirect URIs
, которые исправили это для меня, я смог отладить и знать, что именно было проблемой после переключения с https://accounts.google.com/o/oauth2/token
to https://www.googleapis.com/oauth2/v4/token
Я получил правильную ошибку:
{"error": "redirect_uri_mismatch", "error_description": "Bad Request"}
Ответ 18
У меня возникла эта проблема после включения нового API службы в консоли Google и попытки использовать ранее сделанные учетные данные.
Чтобы решить эту проблему, мне пришлось вернуться на страницу с учетными данными, щелкнув по имени учетной записи и снова нажав "Сохранить" again. После этого я мог просто аутентифицироваться.
Ответ 19
В моем случае проблема была в моем коде. По ошибке я пытался инициировать клиента 2 раза с одинаковыми токенами. Если ни один из приведенных выше ответов не помог, убедитесь, что вы не сгенерировали 2 экземпляра клиента.
Мой код до исправления:
def gc_service
oauth_client = Signet::OAuth2::Client.new(client_options)
oauth_client.code = params[:code]
response = oauth_client.fetch_access_token!
session[:authorization] = response
oauth_client.update!(session[:authorization])
gc_service = Google::Apis::CalendarV3::CalendarService.new
gc_service.authorization = oauth_client
gc_service
end
primary_calendar_id = gc_service.list_calendar_lists.items.select(&:primary).first.id
gc_service.insert_acl(primary_calendar_id, acl_rule_object, send_notifications: false)
как только я изменю его на (используйте только один экземпляр):
@gc_service = gc_service
primary_calendar_id = @gc_service.list_calendar_lists.items.select(&:primary).first.id
@gc_service.insert_acl(primary_calendar_id, acl_rule_object, send_notifications: false)
это исправило мои проблемы с типом гранта.
Ответ 20
Для меня проблема заключалась в том, что у меня было несколько клиентов в моем проекте, и я почти уверен, что это совершенно нормально, но я удалил всех клиентов для этого проекта и создал новый, и все начали работать на меня (Понял эту идею из справки плагина WP_SMTP Поддержка форума) Я не могу найти эту ссылку для справки