[英]Rails Google Client API - unable to exchange a refresh token for access token
在我的機器上遇到一些SSL問題之后,我仍然試圖通過Google Ruby Client API訪問用戶的Blogger帳戶。 我正在使用以下內容:
我可以在身份驗證時通過Google API成功驗證用戶身份並訪問他們的博客。 當用戶登錄時,我存儲了我從Google收到的access_token
和refresh_token
。 並且在access_token
到期之前一切正常。 我正在嘗試構建為新的access_token
交換refresh_token
的功能,但不斷遇到問題。 以客戶端文檔為例,這是我正在使用的代碼:
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
- 除了使用數據庫中的值之外,還有不同的方法可以檢查令牌的過期嗎? client.authorization.fetch_access_token!
我收到invalid_request
錯誤。 有人可以告訴我如何使用客戶端API為新的access_token
交換refresh_token
嗎? 即使你知道如何用另一種語言來做,這將是一個很大的幫助,因為我可以嘗試Rubyfy它。 謝謝!!
您可能已經發現了這一點,但您可以在google上閱讀整個過程: 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
由於您使用的是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
而根據這個問題 ,建議不要使用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
我用下面的簡單代碼修復了它。
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.