2012-04-20 29 views
22

我正在寫一個Rails應用程序,它使用omniauth-facebook來驗證FB用戶(並獲得用戶的FB OAuth訪問令牌)。該應用程序然後使用Koala使用保存的OAuth令牌對FB Graph API進行各種調用。Facebook令牌到期和更新,與考拉和omniauth-facebook

每次用戶重新進行身份驗證時(通常是他們登錄到我的應用程序時),我都會更新保存的令牌。即便如此,該保存的令牌將不時(或以其他方式無效)過期。

圍繞使用考拉防止認證失敗和更新令牌的最佳做法是什麼?

是否應該將所有調用都封裝在開始/救援塊中,並使用異常處理程序對FB重新驗證用戶?

是否有某種方法(使用考拉)利用描述爲here的「擴展訪問令牌」過程?如果沒有,是否有最佳做法來編寫我自己的代碼,以便從考拉呼叫中提取新的令牌?

回答

16

我所擁有的是在需要活躍的Facebook會話的每個頁面上觸發的before_filter。像這樣的東西應該工作:

before_filter :reconnect_with_facebook 
    def reconnect_with_facebook 
    if current_account && current_account.token_expired?(session[:fb]["expires"]) 

    # re-request a token from facebook. Assume that we got a new token so 
    # update it anyhow... 
    session[:return_to] = request.env["REQUEST_URI"] unless request.env["REQUEST_URI"] == facebook_request_path 
    redirect_to(with_canvas(facebook_request_path)) and return false 
    end 
end 

token_expired?方法是這樣的:

def token_expired?(new_time = nil) 
    expiry = (new_time.nil? ? token_expires_at : Time.at(new_time)) 
    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 
+0

感謝您的回答。 session [:fb] [「expires」]在哪裏/如何設置?您可以在上面的reconnect_with_facebook方法中使用它。 – 2012-05-07 15:55:13

+0

我設置了第一次有人成功登錄創建會話。所有其他連接被視爲「重新連接」 – heavysixer 2012-05-07 18:54:32

+0

謝謝。我的實施方式有所不同,但這有助於我走上正確的道路。 – 2012-05-16 18:30:17

16

我碰到this postRailscast on Facebook適應代碼向您展示如何爲60天的一個交換短期令牌:

user.rb

def self.from_omniauth(auth) 

    # immediately get 60 day auth token 
    oauth = Koala::Facebook::OAuth.new(ENV["FACEBOOK_APP_ID"], ENV["FACEBOOK_SECRET"]) 
    new_access_info = oauth.exchange_access_token_info auth.credentials.token 

    new_access_token = new_access_info["access_token"] 
    # Facebook updated expired attribute 
    new_access_expires_at = DateTime.now + new_access_info["expires_in"].to_i.seconds 

    where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user| 
     user.provider = auth.provider 
     user.uid = auth.uid 
     user.name = auth.info.name 
     user.image = auth.info.image 
     user.email = auth.info.email 
     user.oauth_token = new_access_token #originally auth.credentials.token 
     user.oauth_expires_at = new_access_expires_at #originally Time.at(auth.credentials.expires_at) 
     user.save! 
    end 
    end 
+0

感謝您的代碼片段! – okysabeni 2014-05-18 20:36:19

+0

謝謝,這是一個不錯的方法。花了我一段時間來弄清楚爲什麼我的測試抱怨 '考拉:: Facebook :: OAuthTokenRequestError: 類型:OAuthException,代碼:101,消息:缺少client_id參數。 [HTTP 400]'。最終,我意識到我沒有在'secrets.yml'中爲我的測試環境定義ENV [「FACEBOOK_APP_ID」]或ENV [「FACEBOOK_SECRET」]。 – DazBaldwin 2015-02-05 00:41:59

0

你可以做這樣的事情,你檢查access_token是否過期並生成另一個。

%w[facebook].each do |provider| 
    scope provider, -> { where(provider: provider) } 
end 

def client 
    send("#{provider}_client") 
end 

def expired? 
    expires_at? && expires_at <= Time.zone.now 
end 

def access_token 
    send("#{provider}_refresh_token!", super) if expired? 
    super 
end 

def facebook_refresh_token!(token) 
    new_token_info = 
    Koala::Facebook::OAuth.new.exchange_access_token_info(token) 
    update(access_token: new_token_info["access_token"], expires_at: Time.zone.now + new_token_info["expires_in"]) 
end 

你可以檢查gorails screencast,這個深度解釋這個。