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" - это своего рода ошибка для всех ошибок, связанных с недействительными/истекшими/отмененными токенами (токен предоставления или обновления).

Для нас проблема была двукратной:

Кроме того, существует множество других потенциальных причин, которые могут вызвать ошибку:

  1. Серверные часы/время не синхронизированы
  2. Не разрешено для автономного доступа
  3. Дросселировано Google
  4. Использование истекших токенов обновления
  5. Пользователь неактивен в течение 6 месяцев
  6. Использовать электронную почту рабочего лица вместо идентификатора клиента
  7. Слишком много токенов доступа за короткое время
  8. Клиентский SDK может быть устаревшим
  9. Неверный/неполный токен обновления

Я написал короткую статью, в которой кратко излагается каждый элемент с некоторыми инструкциями по отладке, чтобы помочь найти виновника. Надеюсь, что это поможет.

Ответ 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 Поддержка форума) Я не могу найти эту ссылку для справки