在我的机器上使用了一些SSL issues之后,我仍然在尝试通过Google Ruby Client API访问用户的博客帐户。我使用的是以下内容:
我可以成功地对用户进行身份验证,并在身份验证时通过Google API访问其博客。当用户登录时,我存储从谷歌收到的access_token
和refresh_token
。在access_token
到期之前,一切都运行得很好。我正在尝试构建将refresh_token
转换为新access_token
的功能,但一直遇到障碍。以client documentation为例,下面是我使用的代码:
client = Google::APIClient.new
token_pair = auth.oauth_token # access_token and refresh_token received during authentication
# Load the access token if it's available
if token_pair
client.authorization.update_token!(token_pair.to_hash)
end
# Update access token if expired
if client.authorization.refresh_token && client.authorization.expired?
client.authorization.fetch_access_token!
end
blogger = client.discovered_api('blogger', 'v3')
result = client.execute(
api_method: blogger.blogs.list_by_user,
parameters: {'userId' => "self", 'fields' => 'items(description,id,name,url)'},
headers: {'Content-Type' => 'application/json'})
当access_token
有效时,这段代码可以很好地工作。但一旦到期,我就会看到两个问题:
expires_at
值),client.authorization.expired?
仍返回false
--除了使用database?client.authorization.fetch_access_token!
时出现invalid_request
错误。有没有人可以告诉我如何使用客户端接口将refresh_token
换成新的access_token
?即使你知道如何在另一种语言中做到这一点,这也是一个很大的帮助,因为我可以尝试Ruby化它。谢谢!!
发布于 2012-09-25 07:37:57
你可能已经找到了这个,但你可以在谷歌上阅读整个过程:https://developers.google.com/accounts/docs/OAuth2WebServer
omniauth-google-oauth2策略已经负责设置access_type和approval_prompt,因此获得刷新令牌只需使用grant_type=request_token发送到https://accounts.google.com/o/oauth2/token
下面是我使用的大致代码:
def refresh_token
data = {
:client_id => GOOGLE_KEY,
:client_secret => GOOGLE_SECRET,
:refresh_token => REFRESH_TOKEN,
:grant_type => "refresh_token"
}
@response = ActiveSupport::JSON.decode(RestClient.post "https://accounts.google.com/o/oauth2/token", data)
if @response["access_token"].present?
# Save your token
else
# No Token
end
rescue RestClient::BadRequest => e
# Bad request
rescue
# Something else bad happened
end
发布于 2013-11-19 16:08:05
既然您正在使用Ruby Google API客户端,为什么不使用它来交换刷新令牌呢?Ruby API在内部做了几乎相同的事情,@brimil01在他的回答中说过。
这就是我如何使用Ruby API将我的刷新令牌交换为新的访问令牌。
def self.exchange_refresh_token( refresh_token )
client = Google::APIClient.new
client.authorization.client_id = CLIENT_ID
client.authorization.client_secret = CLIENT_SECRET
client.authorization.grant_type = 'refresh_token'
client.authorization.refresh_token = refresh_token
client.authorization.fetch_access_token!
client.authorization
end
根据this issue here的说法,建议不要使用expired?
方法检查访问令牌是否已过期。
基本上,不调用expired?方法。基本上没有任何情况下这是个好主意。它不会给你提供可靠的过期信息。它更像是一个提示,而不是真正的过期时间戳,令牌服务器可能会在某些理论上但很重要的情况下决定接受过期的令牌。如果确实收到无效授权错误,请始终刷新访问令牌并重试一次。如果您仍然收到错误,请引发该错误。
这就是我要做的。
# Retrieved stored credentials for the provided user email address.
#
# @param [String] email_address
# User's email address.
# @return [Signet::OAuth2::Client]
# Stored OAuth 2.0 credentials if found, nil otherwise.
def self.get_stored_credentials(email_address)
hash = Thread.current['google_access_token']
return nil if hash.blank?
hash[email_address]
end
##
# Store OAuth 2.0 credentials in the application's database.
#
# @param [String] user_id
# User's ID.
# @param [Signet::OAuth2::Client] credentials
# OAuth 2.0 credentials to store.
def self.store_credentials(email_address, credentials)
Thread.current['google_access_token'] ||= {}
Thread.current['google_access_token'][email_address] = credentials
end
def self.credentials_expired?( credentials )
client = Google::APIClient.new
client.authorization = credentials
oauth2 = client.discovered_api('oauth2', 'v2')
result = client.execute!(:api_method => oauth2.userinfo.get)
(result.status != 200)
end
# @return [Signet::OAuth2::Client]
# OAuth 2.0 credentials containing an access and refresh token.
def self.get_credentials
email_address = ''
# Check if a valid access_token is already available.
credentials = get_stored_credentials( email_address )
# If not available, exchange the refresh_token to obtain a new access_token.
if credentials.blank?
credentials = exchange_refresh_token(REFRESH_TOKEN)
store_credentials(email_address, credentials)
else
are_credentials_expired = credentials_expired?(credentials)
if are_credentials_expired
credentials = exchange_refresh_token(REFRESH_TOKEN)
store_credentials(email_address, credentials)
end
end
credentials
end
发布于 2013-12-12 16:50:46
我用下面的简单代码修复了它。
def refesh_auth_tooken(refresh_token)
client = Google::APIClient.new
puts "REFESH TOOKEN"
client.authorization = client_secrets
client.authorization.refresh_token = refresh_token
#puts YAML::dump(client.authorization)
client.authorization.fetch_access_token!
return client.authorization
end
https://stackoverflow.com/questions/12572723
复制相似问题