Google :: Apis :: AuthorizationError (Несанкционированный) - PullRequest
0 голосов
/ 25 мая 2018

Мы создаем приложение с Ionic Framework в качестве внешнего интерфейса и Ruby on Rails в качестве внутреннего.Мы можем связать учетную запись Gmail в нашем приложении.Связывание аккаунта работает нормально, мы получаем serverAuthCode из внешнего интерфейса, а затем, используя его, получаем токен обновления, и мы можем получать электронные письма с этим маркером обновления с первой попытки.Но через несколько секунд он истекает или отменяется.Получение следующей проблемы:

Signet::AuthorizationError (Authorization failed.  Server message:
{
  "error" : "invalid_grant",
  "error_description" : "Token has been expired or revoked."
})

Похоже, сам токен обновления истекает в считанные секунды.Кто-нибудь имеет какие-либо идеи о том, как это исправить?

Обновление:

Существующий код выглядит следующим образом:

class User   
  def authentication(linked_account)
    client = Signet::OAuth2::Client.new(
    authorization_uri: 'https://accounts.google.com/o/oauth2/auth',
    token_credential_uri: Rails.application.secrets.token_credential_uri,
    client_id: Rails.application.secrets.google_client_id,
    client_secret: Rails.application.secrets.google_client_secret,
    scope: 'https://www.googleapis.com/auth/gmail.readonly, https://www.googleapis.com/auth/userinfo.email, https://www.googleapis.com/auth/userinfo.profile',
    redirect_uri: Rails.application.secrets.redirect_uri,
    refresh_token: linked_account[:refresh_token]
  )

  client.update!(access_token: linked_account.token, expires_at: linked_account.expires_at)
  return  AccessToken.new(linked_account.token) unless client.expired?
  auth.fetch_access_token! 
 end

 def get_email(linked_account)
   auth = authentication(linked_account)
   gmail = Google::Apis::GmailV1::GmailService.new
   gmail.client_options.application_name = User::APPLICATION_NAME
   gmail.authorization = AccessToken.new(linked_account.token)
   query = "(is:inbox OR is:sent)"
   gmail.list_user_messages(linked_account[:uid], q: "#{query}")
   ## Getting error over here ^^
  end
end // class end 

class AccessToken
  attr_reader :token
  def initialize(token)
    @token = token
  end

  def apply!(headers)
    headers['Authorization'] = "Bearer #{@token}"
  end
end

Ссылка: https://github.com/google/google-api-ruby-client/issues/296

Ответы [ 6 ]

0 голосов
/ 11 августа 2019

В моем случае только YouTube загрузка повышение API

Unauthorized (Google::Apis::AuthorizationError)

и другие API, как список видео API работают хорошо

это потому, что я использую новый аккаунт Googleи не иметь видео

я вручную видео в сети YouTube, YouTube требует от меня создать "канал"

, и я пытаюсь снова YouTube API, это работает

Я думаю,это потому, что у YouTube есть канал до

0 голосов
/ 08 июня 2018

Отправлено недостаточно кода, но опубликованное выглядит неправильно.

  • linked_account не определено
  • Нигде не показано, что linked_account.token когда-либо обновляется (илиустановить, в этом отношении).Он должен быть обновлен, когда refresh_token используется для получения нового токена доступа.
  • auth представляется неопределенным в строке auth.fetch_access_token!
  • GmailService#authorization= занимает Signet::OAuth2::Client, а не AccessToken.

Вероятно, чтопроисходит то, что у вас есть действительный токен доступа в linked_account.token до тех пор, пока вы не вызовете client.update!, который выбирает новый токен доступа и делает недействительным старый.Но поскольку вы никогда не обновляете linked_account, будущие вызовы не будут выполняться до тех пор, пока вы не пройдете путь к коду, который сбрасывает его.

Вам нужно вызывать client.update! только в том случае, если срок действия маркера доступа истек, и если он истек иВы получаете новый, вам нужно сохранить этот новый в linked_account.token.

0 голосов
/ 07 июня 2018

Вы пытались обновить токен доступа токеном обновления?Вы можете перехватить ошибку и повторить попытку.

Примерно так:

begin
  gmail.list_user_messages(linked_account[:uid], q: "#{query}")
rescue Google::Apis::AuthorizationError => exception
  client.refresh!
  retry
end
0 голосов
/ 07 июня 2018

Существует несколько причин, по которым токен обновления перестает работать.

  1. Срок действия старых токенов обновления истекает через шесть месяцев, если они не используются.
  2. Пользователь может повторно проверить приложение.и получите новый токен обновления; оба токена обновления будут работать, вы можете иметь до пятидесяти выдающихся токенов обновления, после чего первый перестанет работать.
  3. пользователь может отозвать ваш доступ.
  4. Wakey перехода на летнее времяошибка времени 2015 года. (мы не будем об этом говорить)

Gmail и сброс пароля.

Это в основном похоже на сброс пароля.Гранты OAuth с областями gmail аннулируются, когда пользователь меняет свой пароль.

См. Автоматический отзыв токена OAuth 2.0 при смене пароля

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

Вы провели большое тестирование, и я полагаю, что вы сохраняете новейшую версию.обновить токен?Если нет, то вы можете использовать старые токены обновления, и они перестанут работать.(номер 2)

0 голосов
/ 06 июня 2018

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

return  AccessToken.new(linked_account.token) unless client.expired?
auth.fetch_access_token! 

Вот как я получаю свой токен доступа:

  def self.access_token(refresh_token)
    Cache.fetch(refresh_token, expires_in: 60.minutes) do
      url = GoogleService::TOKEN_CREDENTIAL_URI
      # p.s. TOKEN_CREDENTIAL_URI = 'https://www.googleapis.com/oauth2/v4/token'
      _, response = Request.post(
        url,
        payload: {
          "client_id": GoogleService::CLIENT_ID,
          "client_secret": GoogleService::CLIENT_SECRET,
          "refresh_token": refresh_token,
          "grant_type": "refresh_token"
        }
      )
      response['access_token']
    end
  end

И затем использую этот токен доступа для любых целей.Дайте мне знать, как это происходит, а также, если вы в состоянии создать воспроизводимую версию API.Это будет здорово.

0 голосов
/ 06 июня 2018

Мысль о том, что refresh token никогда не истечет, на самом деле является недоразумением.Фактическая сцена состоит в том, что сервер выдает токен недолговечного доступа и токен обновления долгоживущего.Таким образом, в действительности происходит то, что токен доступа может быть восстановлен с использованием долгоживущих токенов обновления, но да, вам придется запросить новый токен обновления (так как срок его действия также истекает!).Например;Вы можете обращаться с токенами обновления так, как будто они никогда не истекают.Однако при проверке входа для нового, в случае, если пользователь отзывает токен обновления, в этом случае Google предоставит новый токен обновления при входе в систему, поэтому просто обновите токен обновления.

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

Для лучшего понимания этого вы можете обратиться к этому документу идаже документация OAuth 2.0 .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...