2011-10-02 61 views
3

我使用OmniAuth在我的應用程序中訪問Facebook。我正在使用fb_graph gem:https://github.com/nov/fb_graph發佈到Facebook。我在Heroku上爲這個應用程序運行omniauth-0.3.0。當用戶創建時保存的令牌在用戶稍後登錄時更改。OmniAuth Facebook過期令牌錯誤

代碼創建用戶

class SessionsController < ApplicationController 
    def create 
    auth = request.env["omniauth.auth"] 
    user = User.find_by_provider_and_uid(auth["provider"], auth["uid"])||   
    User.create_with_omniauth(auth) 
     session[:user_id] = user.id 
     redirect_to root_url, :notice => "Signed in!" 
     end 

用戶模型是:

def self.create_with_omniauth(auth) 
    create! do |user| 
    user.provider = auth["provider"] 
    user.uid = auth["uid"] 
    user.name = auth["user_info"]["name"] 
    user.token = auth["credentials"]["token"] 
    end 
    end 

我現在看到的30%左右這個錯誤用戶 -

FbGraph::InvalidToken (OAuthException :: Error validating access token: Session does not match current stored session. This may be because the user changed the password since the time the session was created or Facebook has changed the session for security reasons.) 

我看到過期令牌問題最近已在OmniAuth中修復:

https://github.com/soopa/omniauth/commit/67bdea962e3b601b8ee70e21aedf5e6ce1c2b780

我用這個代碼試圖刷新訪問令牌。但是,我仍然遇到同樣的錯誤。有人能指出我缺少的東西嗎? 每當用戶登錄時,是否有其他方式可以更新令牌?

已經工作的唯一解決方案是創建一個新的用戶每次在用戶登錄(我不喜歡這個解決方案在所有):

def create 
    auth = request.env["omniauth.auth"] 
    user = User.create_with_omniauth(auth) 
    session[:user_id] = user.id 
    redirect_to root_url, :notice => "Signed in!" 
    end 

謝謝!

回答

7

您可以在創建會話時簡單更新令牌。

class SessionsController < ApplicationController 
def create 
    auth = request.env["omniauth.auth"] 
    user = User.find_by_provider_and_uid(auth["provider"], auth["uid"]).tap do |u| 
      u.update_attributes(:token => auth["credentials"]["token"]) if u 
     end || User.create_with_omniauth(auth) 
    session[:user_id] = user.id 
    redirect_to root_url, :notice => "Signed in!" 
end 
+0

感謝您的回覆。我有一個問題 - 我使用omniauth使用FB登錄。 FB令牌會隨着時間的變化而變化,所以當用戶在登錄後很長時間使用應用程序時,令牌可能會發生變化。遇到這種情況,現在我正在使用「offline_access」權限,以便FB生成長壽命令牌。有沒有辦法可以解決這個問題,而不需要「offline_access」。這可能需要我的應用程序在發佈到Facebook之前通過omniauth詢問更新的令牌(登錄後的任何時間)。有沒有其他方法可以解決這個問題? –

+0

根據我的經驗,令牌更改爲'offline_access'設置的唯一時間是用戶在Facebook上更改其密碼時。除此之外,令牌在一年內保持不變。當密碼改變時,他們必須再次登錄以獲得新的令牌,如上所述。 – Brad

+0

我同意你的意見。使用「offline_access」設置令牌沒有改變。但是,我想知道如何在不設置「offline_access」的情況下處理它?(「offline_access」是來自用戶的附加許可,因此很可能會引入一些用戶的摩擦,這些用戶可能不希望應用程序「隨時訪問他們的數據」) –

2

我用類似的解決方案,你回答了這個question-

class SessionsController < ApplicationController 
    def create 
auth = request.env["omniauth.auth"] 
user = User.find_by_provider_and_uid(auth["provider"], auth["uid"]) || User.create_with_omniauth(auth) 

user.update_attributes(:token => auth["credentials"]["token"]) 

session[:user_id] = user.id 
redirect_to root_url, :notice => "Signed in!" 

    end 
1

我們不能刷新使用FBGraph寶石,在這種情況下follwing方法令牌之前?

auth = FbGraph::Auth.new(CLIENT_ID, CLIENT_SECRET) 
auth.exchange_token! access_token # Needs fb_graph 2.3.1+ 
auth.access_token # => new token 

但是,這不會延長令牌的到期日期,但會用新的標誌替換令牌。到期時間將保持不變。用FB檢查它們,它們可能不允許延長超過60天的FB令牌期限。 最大令牌有效期爲60天。

參考:https://github.com/nov/fb_graph/wiki/Authentication#wiki-extend-token-expiry