2011-10-02 37 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