Facebook token expiration and renewal, with Koala and omniauth-facebook

前端 未结 3 1898
时光取名叫无心
时光取名叫无心 2020-12-07 16:55

I\'m writing a Rails app that uses omniauth-facebook to authenticate the user against FB (and to get a FB OAuth access token for the user). The app then uses Koala to make

相关标签:
3条回答
  • 2020-12-07 17:44

    What I have is a before_filter that is triggered on every page that requires an active Facebook session. Something like this should work:

      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
    

    The token_expired? method looks like this:

    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 讨论(0)
  • 2020-12-07 17:45

    You can do something like this where you check if the access_token is expired and generate another one.

     %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
    

    You can check gorails screencast that explains this on depth.

    0 讨论(0)
  • 2020-12-07 17:50

    I came across this post which adapts code from the Railscast on Facebook to show how you can exchange the short-lived token for the 60-day one:

    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 讨论(0)
提交回复
热议问题