Renew Facebook access token with Koala
Asked Answered
E

2

19

I'm using Koala gem on on Ruby on Rails application

And I have the following code on the model I'm using to the the data through Koala:

@graph = Koala::Facebook::GraphAPI.new(token_secret)
friends = @graph.get_connections("me", "friends")

where token_secret comes from a field of my users table, saved on the login.

It works fine but after a couple minutes I get:

Koala::Facebook::APIError (OAuthException: Error validating access token: Session has expired at unix time 1327438800. The current unix time is 1327442037.):

I found the way to renew this token in the front with the methods from the Facebook JS SDK but this method where I'm getting the list of friends is called on the controller.

How can I renew the token_secret using Koala? is this possible?

Electronics answered 24/1, 2012 at 22:13 Comment(1)
See this question #6710925Pollywog
H
22

I thought I'd answer this because it's something I just came across the need to do.

Koala added support for exchanging access tokens some time ago, here: https://github.com/arsduo/koala/pull/166

So my User model now has something like the following:

def refresh_facebook_token
  # Checks the saved expiry time against the current time
  if facebook_token_expired? 

    # Get the new token
    new_token = facebook_oauth.exchange_access_token_info(token_secret)

    # Save the new token and its expiry over the old one
    self.token_secret = new_token['access_token']
    self.token_expiry = new_token['expires']
    save
  end
end

# Connect to Facebook via Koala's oauth
def facebook_oauth
  # Insert your own Facebook client ID and secret here
  @facebook_oauth ||= Koala::Facebook::OAuth.new(client_id, client_secret)
end
Heteromorphic answered 28/5, 2013 at 2:51 Comment(14)
I'll try that one, looks really good. But before I try I still have a couple questions: 1. I'm using Graph API @graph = Koala::Facebook::API.new(accessToken)... can I use exchange_access_token_info there or should I have to use Koala::Facebook::OAuth instead?Electronics
exhange_access_token_info is defined on Koala::Facebook::OAuth, so yes you must use it there.Heteromorphic
I'd like to point out that in the above code (when I ran it just now with koala 1.6.0), new_token['expiry'] is a String of an integer number of seconds until the token expires ... you might want to convert it to a time when the token will expire if you're saving it. Something like (Time.now + new_token['expires'].to_i) HTHGilles
Could you explain to me where you're getting token_secret from? I save the auth.credentials.token into a user field and tried passing it in but I'm fairly certain your token_secret is a different thingHastate
@MichaelLiu it's not - it's the same token.Heteromorphic
I was being silly :P was trying to exchange an expired access token.Hastate
@MichaelLiu Oooh yeah that could be a problem. I actually run a check on any access to Facebook that will call this method to refresh the token if the expiry is within a week, just to make sure it never expires.Heteromorphic
When I execute exchange_access_token_info, I only get this as a response: Refreshed token info: {"access_token"=>"CAADCTfxcFqgBACDfL..."}. Why is there no 'expires' data field?Hastate
Are you sure that this methods works as intended? I receive new token but the 'expires' value decreases with time, so that Time.now + new_token['expires'].to_i actually points to the same initial token expire date... Do you have different behavior?Ad
Something may have changed in Facebook's API if it no longer returns an expires field. It did work when I wrote it - there's no reason to assume that the token you get back is different than the one you have, if the one you have is sufficiently valid (ie. it expires in a decent length of time).Heteromorphic
I'm a bit confused. Isn't the point to exchange the expired token... ? In this line facebook_oauth.exchange_access_token_info(oauth_token) I am getting the expired error type: OAuthException, code: 190, error_subcode: 467 with this setup. it doesn't like me use my old oauth_token to exchange? (same as your facebook_token)Proprietress
No. If the token is expired, the user must manually reauthorize it, by logging in again typically. The trick is to refresh tokens when theyre near expiry.Heteromorphic
I think @Proprietress is referring to facebook_token_expired? which implies the token expires before renewal. Perhaps facebook_token_expiring? would be better unless I misunderstand.Stempien
Did you defined facebook_token_expired or it's some default method?Ellary
C
0

If you are trying to get the oauth_token for a Facebook website application, you need to use the redirect-based Oauth process. It's a little complicated. For a canvas app, it's simpler. You can still use the redirect-based process for a canvas app, but it's better to parse it from the signed_request.

Every time a user loads your app in Facebook, they will land on your first page with a "signed_request" parameter. This encrypted string must be parsed in your controller with a Koala object. From the result, you can get a new oauth_token which should be valid for about two hours. Here's how I do it.

 #Create a new koala Oauth object.
 oauth = Koala::Facebook::OAuth.new(APP_ID, APP_SECRET) 

 #Get the new oauth_token from the signed request.
 your_new_oauth_token = oauth.parse_signed_request(params[:signed_request])["oauth_token"]
Chibcha answered 18/2, 2012 at 21:55 Comment(1)
That's the problem, the application is not loading inside Facebook, It's just a web application using Facebook login, and at some point I use koala to retrieve the list of friends but if I don't load any other page on my app but the friends page the token is not updated, because I do this via JS on FB.getLoginStatus(...)Electronics

© 2022 - 2024 — McMap. All rights reserved.