Am coming back to building a FB app after some time away from the FB Platform and I see that the old offline_access permission has been removed and replaced with long(ish)-expiry tokens[1].
So, it now seems like any external app that needs to push data to Facebook based on, say, a schedule or some activity in the external app will need to cope with that long-access token having expired. This is made more frustrating because now a user logging out of FB will also kill any long-expiry token[2], whereas before, offline_access lived on even when the user was logged out.
I'm still in the pondering-a-solution stage, but two ideas spring to mind:
1) Whenever my app contacts a user who has FB integration, they are requested to click a link that will trigger re-auth with FB to get a new long-access token. My users are generally contacted several times within the lifespan of a long-access token, so this should effectively keep renewing the long-access token for as long as they need (even if it does add some annoying friction to my app)
2) Because I can't guarantee that 1) will always work (due to users not clicking the re-auth link in my app's email notification or them logging out of Facebook, for example) I'll also have to handle failed FB interactions by placing them in a holding queue and emailing the user to explicitly ask them to grant a long-access token again. Not cool, but I see no other option. If they don't respond to the request after X attempts to ask them to re-grant permission, I'll just have to bin the task and email them to explain that it's due to an FB limitation, not my app. Again, not cool.
Has anyone had to come up with any better solutions to maintain the ability to interact with a user's account with authentication/explicit permissions? I'd be keen to hear what you did.
(This is all pending me re-reading the FB ToS, of course - it's entirely possible that this is against the rules, which would be even more frustrating)
EDIT/UPDATE: the data I need to push is images to a photo album which will arrive at my server from various sources and will then be pushed into an appropriate user's album (with their pre-granted permission, of course). I won't be able to guarantee having any web-based end-user interaction at the point in time the images hit my server in order to get the end user to grant me a new short-lifespan token. Basically, offline_access
really would have been ideal for this IMO.
UPDATE 2: NB: it's really key to my use case that the user won't necessarily be using my app or Facebook when the token needs to be granted or extended.
[1] https://developers.facebook.com/roadmap/offline-access-removal/ [2] http://developers.facebook.com/blog/post/2011/05/13/how-to--handle-expired-access-tokens/
You've got the right two options, but I will point out a third option and a little-known-fact that may or may not be relevant for your specific scenario of "needs to push data to Facebook"
First, another option available assuming you either have mobile web or canvas implemented for your app is app to user requests or notifications. The user will get a little notification counter indicator next to your app name in the list of bookmarks. If they respond to the request or the bookmark/notification counter gets them to hit your app, you can trigger your server-side token renewal/extension process. This process is transparent to the user -- assuming they still have your app installed they see nothing.
Secondly, what a lot of people use offline_access for today is simply posting to the user's stream. If that is all you need and you don't need to do a bunch of FQL queries or hit other actions on the graph API, then you don't actually need offline_access or a current user token if you get the publish_stream permission. With publish_stream you can post while the user is offline by using your app access token.
For the specific "need to push data" scenario, facebook announced new Page object connections that allow you to create post's with a specific publication time. With these in theory you can get rid of the problem by authenticating the users when creating these and let Facebook post them instead of scheduled jobs on your side.
here comes 3rd option as a suggestion.
For each authenticated user, you have access_token and expires_in (assume that you have stored them in your db already)
1) Write a scheduled task, that checks existing tokens with their expires_in value when you find any token close to expiration time,
2) you can renew this token from the server side by HTTP GET call (sample code below)
requestUrl = "https://graph.facebook.com" + "/oauth/access_token"
+ "?" + "client_id="+facebook_appId
+ "&"+"client_secret="+facebook_appSecret
+ "&" + "grant_type=fb_exchange_token"
+ "&" + "fb_exchange_token="+currentToken;
req = WS.url( requestUrl );
Logger.info("renew token, req.url : %s", req.url);
req.timeout = 20;
resp = req.get();
// access_token=....&expires=5181096
Map<String, String> respMap = LocoUtils.decodeUrl( resp.getString() );
token = respMap.containsKey("access_token")? respMap.get("access_token") : "";
facebookToken.access_token = token;
facebookToken.expires_in = respMap.containsKey("expires")?LocoUtils.stringToLong(respMap.get("expires")) : 0L;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With