Rails - 使用 Omniauth 和 Koala 的 Facebook:如何更新过期的令牌

Posted

技术标签:

【中文标题】Rails - 使用 Omniauth 和 Koala 的 Facebook:如何更新过期的令牌【英文标题】:Rails - Facebook with Omniauth and Koala: How to renew an expired token 【发布时间】:2012-04-28 08:09:29 【问题描述】:

我有一个应用程序,用户可以在其中链接他们的 Facebook 帐户。他们可以使用电子邮件登录,但可以链接他们的 Facebook 帐户。

在我显示链接的社交网络(Facebook 和其他)的视图中,我有这样的东西:

<%= image_tag @facebook.get_facebook_picture %>

这将调用这样的实例方法:

def get_facebook_picture
    unless self.token.nil?
      facebook_graph = Koala::Facebook::GraphAPI.new(self.token)
      fb_picture = facebook_graph.get_picture("me",  :type => "small" )
    end
end

除非我存储在我的数据库中的 Facebook 令牌已过期,否则这将很好地工作。所以我在提到的控制器中添加了这个异常处理程序:

def facebook_exception_handler exception
    if exception.fb_error_type.eql? 'OAuthException'
      # Let's get a new auth token... How?
    else
      logger.debug "Damn it. We don't know what error is coming from FB"
      raise exception
    end
end

我正确捕获了异常,但我看不到如何更新我在数据库中拥有的访问令牌。请注意,我已经使用 OmniAuth 插入了访问令牌。所以我的问题是:

鉴于我有一个 OAuthException,我如何使用 Omniauth 更新特定用户 (UID) 的访问令牌?

【问题讨论】:

由于这不是您问题的答案,我将发表评论...但是您应该能够在没有活动令牌的情况下使用:profile_pic = Koala::Facebook::GraphAPI.new.get_picture(fb_uid, :type =&gt; "large") 抓取图片,对吧? 如果您想获得延长的60天令牌,this may help 【参考方案1】:

最简单的情况是您使用 FB 重新验证用户身份,就像您最初授权他们一样。首先要获得令牌,我假设您正在使用omniauth(和onmiauth-facebook)对FB进行身份验证。这意味着您有一个路由和一个控制器操作来处理身份验证回调,以及一个将令牌插入数据库的函数。

您最初通过 omniauth 获得的访问令牌可能因各种原因而失效 - 过期,或者因为用户更改了他们的 FB 密码,也可能是其他原因。在这些情况下,另一个 OAuth 调用将返回一个有效的令牌。只需再次调用(就像您第一次授权用户时所做的那样)并在您的数据库中用新的令牌替换无效令牌,您就很好了。

This gist(my own answer 到我在这里提出的相关问题)有一些代码涵盖了这一点,但听起来你已经涵盖了这一点。保存足够的状态,然后重新尝试触发异常的任何事情,你就很好了。

令牌现在也可能无效,因为用户更改了他们的 FB 应用程序设置以取消对您的应用程序的授权。在这种情况下,用户将看到 FB 权限对话框,就好像他们是第一次针对 FB 进行身份验证的新用户一样。 (FB)

这有意义吗?

【讨论】:

感谢您的回答。我的问题是:如何直接更新令牌而无需向用户显示身份验证窗口? 只要应用仍然被授权并且用户仍然登录到FB,你的oauth调用就会静默成功。如果出于某种原因需要,用户只会看到一个身份验证窗口(他们已从 FB 注销,或者他们已取消对您的应用的授权并需要重新授权)。 我根本没有说用户已登录...我正在使用 Omniauth 让用户将他们的帐户链接到应用程序(以便在他们的墙上发布),但不是作为日志记录方法。 当然——无论您是否使用该 fb 令牌登录您的应用程序都没有关系……只要您拥有它即可。我要说的要点是,无论您首先进行 OAuth 调用以获取 FB 令牌,您都可以执行相同的操作来替换过期的令牌。用户通常不会看到另一个身份验证对话框。或者我在你的场景中遗漏了一些东西。您能否发布更多详细信息(或代码)以显示您如何首先获得令牌?或者告诉我更多关于该场景的信息,以帮助我理解为什么另一个 OAuth 调用不是一个好的解决方案?【参考方案2】:

你可以用这个来改变 RailsCasts koala 教程的连接:

def facebook
  if self.facebook_expires_at < Time.now
    oauth = Koala::Facebook::OAuth.new(ENV["FACEBOOK_KEY"], ENV["FACEBOOK_SECRET"])
    new_access_info = oauth.exchange_access_token_info self.facebook_token

    new_access_token = new_access_info["access_token"]
    new_access_expires_at = DateTime.now + new_access_info["expires"].to_i.seconds

    self.update_attributes!(:facebook_token => new_access_token,
                            :facebook_expires_at => new_access_expires_at )
  end
  @facebook ||= Koala::Facebook::API.new(self.facebook_token)
  block_given? ? yield(@facebook) : @facebook

  rescue Koala::Facebook::APIError => e
    logger.info e.to_s
    nil
end

【讨论】:

我的实验表明,这种做法实际上并没有延长过期时间,新token会和旧token同时过期。 @biomancer 我也发现了,有没有办法更新令牌? @NickGinanto 看起来如果不与用户交互就无法做到这一点。我最终向令牌已过期的用户显示了特别通知,并使用了用于登录/注册的相同omniauth 链接。用户通过标准 OAuth 流程,我在 Omniauth 回调中收到新令牌。

以上是关于Rails - 使用 Omniauth 和 Koala 的 Facebook:如何更新过期的令牌的主要内容,如果未能解决你的问题,请参考以下文章

Rails - 设计/Omniauth - 无方法错误配置

Rails Oauth 设计 Omniauth

在 Rails 应用程序中使用 Omniauth-oauth2 刷新令牌

Ruby on rails omniauth-twitter 和设计

在 Rails 3 中设置环境变量(设计 + Omniauth)

Rails omniauth Google - 如何更新个人资料数据