我们正在创建一个使用Ionic框架作为前端和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
发布于 2018-06-06 15:00:48
根据我的猜测,问题似乎在这两条线上。检查令牌过期并生成新令牌的方式。如果只有最少的可重现代码,那就太好了。
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版本。那就太好了。
发布于 2018-06-08 03:29:06
您是否尝试过使用刷新令牌刷新访问令牌?您可以捕获错误并重试。
如下所示:
begin
gmail.list_user_messages(linked_account[:uid], q: "#{query}")
rescue Google::Apis::AuthorizationError => exception
client.refresh!
retry
end
发布于 2018-06-08 09:55:03
没有发布足够的代码,但发布的内容看起来是错误的。
linked_account
不是definedlinked_account.token
会被更新(或设置,就此而言)。当使用refresh_token
获取新的访问令牌时,需要对其进行更新。auth
似乎未在GmailService#authorization=
takes a AccessToken
. auth.fetch_access_token!
a Signet::OAuth2::Client
这一行中定义
可能发生的情况是,在调用client.update!
之前,您在linked_account.token
中拥有一个有效的访问令牌,这将获取一个新的访问令牌并使旧的访问令牌无效。但是,由于您从不更新linked_account
,因此在您通过重置它的代码路径之前,将来的调用都会失败。
仅当访问令牌过期时才需要调用client.update!
,如果访问令牌已过期并且您获得了一个新令牌,则需要将该新令牌存储在linked_account.token
中。
https://stackoverflow.com/questions/50523052
复制相似问题