我在rails中使用omniauth-oauth2對支持oauth2的站點進行身份驗證。做OAuth技巧後,該網站給了我;下面,我再堅持到數據庫:在Rails應用程序中使用Omniauth-oauth2刷新令牌
- 訪問令牌
- Expires_AT(蜱)
- 刷新令牌
是否有omniauth方法在過期後自動刷新令牌,還是應該編寫自定義代碼來執行相同的操作?
如果要編寫自定義代碼,是否是幫助程序編寫邏輯的正確位置?
我在rails中使用omniauth-oauth2對支持oauth2的站點進行身份驗證。做OAuth技巧後,該網站給了我;下面,我再堅持到數據庫:在Rails應用程序中使用Omniauth-oauth2刷新令牌
是否有omniauth方法在過期後自動刷新令牌,還是應該編寫自定義代碼來執行相同的操作?
如果要編寫自定義代碼,是否是幫助程序編寫邏輯的正確位置?
Omniauth不提供此功能,所以我使用以前的答案和另一個SO答案在我的模型中編寫代碼User.rb
def refresh_token_if_expired
if token_expired?
response = RestClient.post "#{ENV['DOMAIN']}oauth2/token", :grant_type => 'refresh_token', :refresh_token => self.refresh_token, :client_id => ENV['APP_ID'], :client_secret => ENV['APP_SECRET']
refreshhash = JSON.parse(response.body)
token_will_change!
expiresat_will_change!
self.token = refreshhash['access_token']
self.expiresat = DateTime.now + refreshhash["expires_in"].to_i.seconds
self.save
puts 'Saved'
end
end
def token_expired?
expiry = Time.at(self.expiresat)
return true if expiry < Time.now # expired token, so we should quickly return
token_expires_at = expiry
save if changed?
false # token not expired. :D
end
在使用訪問令牌進行API調用之前,您可以調用此方法,其中current_user是登錄用戶。
current_user.refresh_token_if_expired
確保安裝rest-client寶石,並在模型文件中添加需要的指令require 'rest-client'
。該ENV['DOMAIN']
,ENV['APP_ID']
和ENV['APP_SECRET']
是可以在config/environments/production.rb
(或開發)
這裏有一些信息,太多列出here。它可能取決於您使用的提供商以及它們允許的使用情況以及它們允許的使用情況refresh-token
事實上,omniauth-oauth2 gem與它的依賴性,oauth2來設置環境變量,都內置了一些刷新邏輯。
見https://github.com/intridea/oauth2/blob/master/lib/oauth2/access_token.rb#L80
# Refreshes the current Access Token
#
# @return [AccessToken] a new AccessToken
# @note options should be carried over to the new AccessToken
def refresh!(params = {})
fail('A refresh_token is not available') unless refresh_token
params.merge!(:client_id => @client.id,
:client_secret => @client.secret,
:grant_type => 'refresh_token',
:refresh_token => refresh_token)
new_token = @client.get_token(params)
new_token.options = options
new_token.refresh_token = refresh_token unless new_token.refresh_token
new_token
end
而且在https://github.com/intridea/omniauth-oauth2/blob/master/lib/omniauth/strategies/oauth2.rb#L74:
self.access_token = access_token.refresh! if access_token.expired?
所以,你可能無法直接與omniauth-的oauth2做到這一點,但你肯定能做到沿此線的東西用的oauth2:
client = strategy.client # from your omniauth oauth2 strategy
token = OAuth2::AccessToken.from_hash client, record.to_hash
# or
token = OAuth2::AccessToken.new client, token, {expires_at: 123456789, refresh_token: "123"}
token.refresh!
有沒有簡單的方法從Rails應用中的現有策略加載客戶端?就像Oauth2策略那樣,我最終宣佈了一個新客戶端:https://github.com/intridea/omniauth-oauth2/blob/master/lib/omniauth/strategies/oauth2。rb#L34 – bgentry
我想你的問題是,我如何找到對現有OmniAuth策略的參考?一旦你有策略對象,它就有一個「客戶端」方法。這裏有其他人詢問有關尋找策略:http://stackoverflow.com/questions/13112430/find-loaded-providers-for-omniauth – Eero
謝謝@Eero - 這導致我到我的修復下面:http://stackoverflow.com/a/38276378/224707 – Nick
艾羅的回答解鎖的路徑爲我解決這個問題。我有一個關於我的課程的幫助問題,它使我獲得了一個Gmail服務。作爲這個過程的一部分,用戶對象(包含谷歌身份驗證信息)會被檢查是否已過期。如果有,它會在返回服務之前刷新。
def gmail_service(user)
mail = Google::Apis::GmailV1::GmailService.new
# Is the users token expired?
if user.google_token_expire.to_datetime.past?
oauth = OmniAuth::Strategies::GoogleOauth2.new(
nil, # App - nil seems to be ok?!
"XXXXXXXXXX.apps.googleusercontent.com", # Client ID
"ABC123456" # Client Secret
)
token = OAuth2::AccessToken.new(
oauth.client,
user.google_access_token,
{ refresh_token: user.google_refresh_token }
)
new_token = token.refresh!
if new_token.present?
user.update(
google_access_token: new_token.token,
google_token_expire: Time.at(new_token.expires_at),
google_refresh_token: new_token.refresh_token
)
else
puts("DAMN - DIDN'T WORK!")
end
end
mail.authorization = user.google_access_token
mail
end
OmniAuth :: Strategies :: YOUR_PROVIDER(nil,client_id,secret)...這是訪問策略,然後訪問其客戶端的唯一方法嗎? – kukrt
ENV ['DOMAIN']應該如何看起來像? – TiSer
你應該正常化到UTC嗎?或者沒有關係... – ckarbass
域名應該是:「https://accounts.google.com/o/oauth2/token」 –