【问题标题】:Facebook token expiration and renewal, with Koala and omniauth-facebookFacebook 令牌到期和更新,与 Koala 和omniauth-facebook
【发布时间】:2012-05-02 05:57:56
【问题描述】:

我正在编写一个 Rails 应用程序,该应用程序使用 omniauth-facebook 对 FB 用户进行身份验证(并为用户获取 FB OAuth 访问令牌)。然后,该应用使用 Koala 使用保存的 OAuth 令牌对 FB Graph API 进行各种调用。

每次用户重新进行身份验证(通常是在他们登录我的应用程序时)时,我都会更新保存的令牌。即便如此,该保存的令牌仍会不时过期(或以其他方式变为无效)。

在使用 Koala 时防止身份验证失败和更新令牌的最佳做法是什么?

是否应该将所有调用都包装在开始/救援块中,并使用异常处理程序重新对 FB 用户进行身份验证?

是否有某种方式(使用 Koala)来利用 here 描述的“扩展访问令牌”过程?如果没有,是否有编写自己的代码以自己从 Koala 调用中提取新令牌的最佳实践?

【问题讨论】:

    标签: ruby-on-rails omniauth koala


    【解决方案1】:

    我所拥有的是一个 before_filter,它在每个需要活动 Facebook 会话的页面上触发。这样的事情应该可以工作:

      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
    

    【讨论】:

    • 感谢您的回答。 session[:fb]["expires"] 在哪里/如何设置?您在上面的 reconnect_with_facebook 方法中使用它。
    • 我设置了有人第一次成功登录以创建会话。所有其他连接都被视为“重新连接”
    • 谢谢。我的实现方式有所不同,但这有助于我走上正确的道路。
    • 如何处理令牌过早过期的情况,例如当用户更改他们的 Facebook 密码或删除应用程序时?
    【解决方案2】:

    我遇到了this post,它改编自 Railscast 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
    

    【讨论】:

    • 感谢这是一个不错的方法。我花了一段时间才弄清楚为什么我的测试抱怨Koala::Facebook::OAuthTokenRequestError: type: OAuthException, code: 101, message: Missing client_id parameter. [HTTP 400]。最终,我意识到我没有在secrets.yml 中为我的测试环境定义ENV["FACEBOOK_APP_ID"]ENV["FACEBOOK_SECRET"]
    【解决方案3】:

    您可以执行类似的操作来检查 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,它详细解释了这一点。

    【讨论】:

      猜你喜欢
      • 2012-04-28
      • 2012-05-27
      • 2013-02-14
      • 2011-11-29
      • 1970-01-01
      • 2015-03-09
      • 1970-01-01
      • 2013-09-21
      • 1970-01-01
      相关资源
      最近更新 更多