Reputation: 13
We have an audio blogging website which can be configured to publish links to the user's Facebook timeline whenever they make a new blog entry.
To do this, we have the user authorise our app when they set up the link to their Facebook account. We obtain the publish_stream, offline_access and manage_pages permissions (more on that later).
All the code is in C# but the principles apply to any language as it's the workings of the Facebook API we are concerned with. We're using OAuth 2 and the Graph API to achieve all of this.
So, we obtain an app access token using our app ID and secret and use that token to publish to the user's timeline, this works fine (because they have already authorised our app to do this). We can also query the Graph API and get their likes, friends and various other data.
NOW HERE IS THE PROBLEM:
Some of our users want to publish updates to their own timelime and also to the timelines of pages that they manage. In theory this is simple: you query the API for the pages that the user manages using this url: https://graph.facebook.com/{userid}/accounts?access_token={token}
The JSON returned from this call is said to contain the page IDs and the page access tokens for those pages. You then use the page access token to publish to the pages' timelines.
However, when we try to call this URL with the app access token we are getting an OAuthException 102 "A user access token is required to request this resource".
Note this is different to OAuthException 104 "An access token is required to request this resource" (which is what you'd get if you neglected to pass an access token), and also OAuthException 190 "Invalid OAuth access token signature" (which you would get if the access token was not a valid one).
So our access token is valid, but just not valid for this particular url. It seems therefore that we need a user access token and not an app access token for this particular feed (I am long past caring why this is the case, it just seems to be the way it is).
All the Facebook documentation on this subject (and I must have read all of it by now) leads to one place: http://developers.facebook.com/docs/authentication/server-side/, aka the "Server-Side Authentication Flow" page. This page describes how to get the elusive user access token by redirecting the user to the auth dialog and asking for the relevant permissions but we need to achieve this without interaction from the user and the user has already given our app all the permissions we need. All of this automated publishing happens server side in the post-processing of the audio so we cannot interact with the user at this stage anyway.
I don't get it. Why is it we can use the app access token to get almost any data we want from the user (well, whatever they have given us permission to get) but the /accounts data we need a different (user) access token for?
Can anyone shed any light on how we can get a user access token which will allow us to get the /accounts data for our users without any further interaction from the user?
Upvotes: 1
Views: 4048
Reputation: 2571
So our access token is valid, but just not valid for this particular url. It seems therefore that we need a user access token and not an app access token for this particular feed
Due to the permissions per type of access token, you do need a valid user access token in this particular case. Read all about access tokens and types. That's just the way it is.
This page describes how to get the elusive user access token by redirecting the user to the auth dialog and asking for the relevant permissions but we need to achieve this without interaction from the user and the user has already given our app all the permissions we need.
If your user already has given his/her permissions, why are you struggling then? I suggest you persist the user access token. From this endpoint:
https://www.facebook.com/dialog/oauth?client_id=..&redirect_uri=..&state=..&scope=..&response_type=..&display=.."
you retrieve a code, like this:
YOUR_REDIRECT_URI?code=OAUTH_CODE_GENERATED_BY_FACEBOOK&state=YOUR_STATE_VALUE
Use this code to generate your user access token, as explained here:
https://graph.facebook.com/oauth/access_token?client_id=..&redirect_uri=..&client_secret=..&code=..
This will result in a response like:
access_token=USER_ACCESS_TOKEN&expires=NUMBER_OF_SECONDS_UNTIL_TOKEN_EXPIRES
There it is, your user access token. Persist it. As you can see it expires after the value indicated in the response. If you are using the new API, it should indicate 60 days (that brings me back to this: offline_access is deprecated and results in short-lived - valid for 2 hours - tokens), link. Whenever your user logs in to your app and uses the Facebook integration, the tokens gets refreshed to again, 60 days. This means, that IF your user should not login to your app and use it for 60 days, it will expire.
You can check whether the user access token is expired with:
https://graph.facebook.com/debug_token?input_token=INPUT_TOKEN&access_token=ACCESS_TOKEN
If that does: renew the user access token by using your app access token, it is well documented right over here. But I'm quoting this part:
Server-side Login To obtain a fresh [user] access token in this case you must pass the user through the full server-side Login flow again. However, assuming the user has not de-authorized your app, when you redirect the user to the OAuth Dialog, they will not be prompted to reauthorize your app, and will be immediately redirected to the redirect_uri. This means that the re-authentication process can appear reasonably transparent to the user.
Bottom-line: there are no user access tokens that are valid for ever, the app access token however is. Persist your user access token and check whether it is still valid before performing API calls with it. A normal user should use your app within 60 days and should not just de-authorize your app for fun. Hence the use case in which the user should re-authorize is fairly rare, however, you need to expect it.
Upvotes: 2