Is redirect to Facebook needed when the access token has expired? - facebook

Let's suppose there is a website which wants to post on Facebook in the users' name. First, when the user is linked to Facebook, he will have an access token and read access so he can log in with Facebook to the website, for instance. On a given event, the user will have write access on Facebook with the access token.
After a while, the Facebook access token expires (as it seems, but if there is a way to create Facebook access tokens which will never expire I would be glad to hear about), so on the website whenever a post to Facebook is about to be made, a request has to be sent to Facebook to check the validity of the access token. If the access token is invalid, then a redirect is needed to Facebook where a new access token is generated, then Facebook redirects back to the page.
I think there are no permanent Facebook access tokens. If there are permanent Facebook access tokens, how can one create them?
If a Facebook access token expires, is there any other solution to the problem than redirecting to Facebook for access token generation and redirecting back?
EDIT:
Here: https://developers.facebook.com/docs/opengraph/howtos/publishing-with-app-token/
I have read the section with the title of "Making API Calls to Publish with an App Access Token".
It states that I need the user's FacebookID and the publish_action privilege granted by the user to be able to post in their name on Facebook. However, I am puzzled about the way I can get the user's FacebookID and how the user grants the website publish_action privilege. Also, this section mentions that
"You will be unable to retrieve information about the status update post with the given ID using the app access token. Instead, you should use a user access token for such purposes."
I do not really understand what information is impossible to be retrieved with this possibility. I do not really understand the cause of inferiority of this strategy compared to the strategy with access tokens.

The short answer is yes, you have to redirect to Facebook (or use the Javascript SDK) to get FB to give you a new access token. If the user is already logged in to Facebook and hasn't deleted your application, then the process will be mostly invisible to your user.
You can, however, extend the length of time you're allowed to use your access token from 1-2 hours to a much longer period (I can't find the time reference, but I seem to remember it being a 3-6 month period). You can read about that process in the Access Tokens Documentation.
edit
First, you have to understand the difference between an App access token and a User access token. An app access token is a very simple token that facebook uses to verify that your app is making a request that you intended it to make. Your app access token consists of your app id and your app secret as a string and separated by a | character. This token doesn't grant you access to any user information, and isn't really usable for a whole lot of things (it's basically used for the authentication methods to ensure that when you request the token, the request is coming from you and not some 3rd party masquerading as you). Though, like you found above - you can also use it to make posts to the user's feed, providing they gave you access.
A user access token identifies an actual user, and their session, to your application. The user access token typically lasts a couple of hours and then expires. You can exchange this token for an extended access token which as I stated above, I believe to last for several months.
A user token (either the temporal 1-2 hour version, or the extended version) allows you to access the FB graph API as the user to which the user belongs. So, using these tokens you can access the user's friend list, photos, likes, interests, etc (presuming you requested permission to do so upon application install). You can check which permissions you have by using the user access token and making a request to /me/permissions on the graph api.
The Javascript SDK is unique, as it doesn't require you to redirect your user away from your application. The JS SDK allows you to use a pop-up to allow the user to authenticate with facebook, install your application, or to allow (or deny) permissions that you are requesting.
The FB.login method takes 2 parameters. Parameter 1 is the callback which is executed after the user responds to your authentication prompt (either by accepting or rejecting your application install request). Parameter 2 is for options which are passed as a javascript object, the only one of which you care about here is the scope parameter. The scope parameter is the way you ask for extended permissions (such as publish_action) so in order to acquire the publish stream permission from a user you use code that looks like this
<script type="text/javascript">
FB.login(function(response)
{
//check to see if they accepted or rejected, and do something
}, { scope: "publish_action });
</script>
Once the user accepts, any subsequent calls to the FB JS SDK will automatically include your user's access token, you don't have to manage it yourself. You can make calls to the graph API on behalf of the user without having to explicitly specify the user's user id - you can just reference them as me. So, for example, you could publish to your user's feed via the JS SDK like so:
<script type="text/javascript">
FB.api('/me/feed', 'post', { message: 'test!' }, function(response)
{
//do things
});
</script>
However, if you'd rather make calls to the Graph API from your server on behalf of the user to publish to their feed (or your needs require you to do so), you'll have to store the user's FB User ID along with your user data so you can access it later. That User ID is available in the argument that is passed to the FB.login callback (response.authResponse.userID). Once you store that, you'll be able to make Graph API calls on behalf of your user from your server simply by POSTing to /<user_id>/feed with the appropriate data:
$ curl -d "message=test&access_token=<app_access_token>" /<user_id>/feed
Finally, re-authenticating your user. THE FB JS SDK exposes 3 methods for authentication.
FB.getAuthResponse
FB.getLoginStatus
FB.login
The primary difference between FB.getAuthResponse and FB.getLoginStatus is that getAuthResponse waits for a response from Facebook before any further javascript is called (it's blocking, or synchronous). FB.getLoginStatus will allow other javascript to run and will call your supplied callback when it gets a response, allowing you to do other things while you wait for a response. Either of these methods can be used to determine if your user is currently logged in to Facebook and if the user has your application installed. You can then use FB.login (if they're not logged in to FB, or not users of your app) to prompt them to login, or install, so you can access their information. Both of these methods pass you back the user's access token if they're installed and have authorized your app (response.authResponse.accessToken).
FB.login does a check for the login status of the user, but it always will pop up a login/install dialog, regardless of the status (and if they're logged in/installed, it will hide the pop-up immediately). The FB.login method is also used if you need to request additional permissions from the user (Say you just get a "vanilla" install at first, and then later the user says they want you to post to their feed. When they initiate that option, you can then request the extended permission from them). In order to utilize that functionality, you use FB.login just as you would if they were a new user, except you add the extended permissions that you want/need in the scope property of the options variable you pass as the 2nd argument.
tl;dr
Use FB.getAuthResponse or FB.getLoginStatus to determine if your user is logged in and has your application installed. These methods can also be used to fetch new access tokens as your user is using your application.
Use FB.login to get new/unauthenticated users to install your application.
Once your user logs in, fetch their user id and store it your database somewhere. This can be used to post on their behalf with your app access token once you acquire the publish_action permission from the user
If you want to store a long-lived user access token to access the user's profile and other information, later, use the link above for exchanging your user access token for an extended access token. This is a server-side process, and you can store the resulting access token in your database with the user's other credentials.
Sorry this so long and wordy - I just wanted to provide you with some solid information about access tokens, how they're used, and how to use the JS SDK to maintain them. Hope this helps.

Related

Facebook login API: avoid user hijacking

I am using FB js SDK to allow logging in on my platform. A user permits the needed access and I save his ID in my DB. The data is sent to my server via AJAX. Since the login is with FB, I can identify the user only by his ID.
Now, lets say I know someones FB ID and I know he has an account on my platform. In runtime, I can place his ID in the auth request and obtain a legit session of that user. How could that be avoided?
First of all, those are App Scoped IDs, it is very unlikely that someone would know the ID of a user who authorized your App, because it´s not the "real" ID.
That being said, you can (and should) send the User Token to the server and confirm the ID by calling the /me endpoint with that Token. You should also use appsecret_proof for API calls, more information can be found in the docs: https://developers.facebook.com/docs/graph-api/securing-requests

Facebook login to existing user database, and access tokens

Trying to add facebook login to an existing login system on a project I am working on. Built with angular, using the FB JS SDK. This is primarily to allow frictionless login, and not currently that fussed about using the access tokens to make further calls with the FB API.
So as a new user, they hit the FB login, accept permissions etc, and it fires me back an access token etc. The new user is created in my DB, along with the accesstoken, FB userid, etc.
How do I now authenticate the user with the userid and accesstoken now stored in my DB? As far as I can see, the access token changes on virtually every page load / request, so next time the user hits the FB login, or I check the FB login status the only constant thing I have is the userid.
Have done various reading on SO and FB docs eg:
https://developers.facebook.com/docs/facebook-login/web
https://developers.facebook.com/docs/facebook-login/multiple-providers
https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow#checktoken
How should a Facebook user access token be consumed on the server-side?
... although that has only served to confuse things further.
I imagine I would take that stored accesstoken then check its validity, however due to the various instances of access tokens expiring and being invalidated, this also seems like an incomplete solution.
So my question: How do I securely authenticate my FB users with their counterpart user in my own DB?
The Facebook login request returns user id + short lived access token (client side).
Use the server side Facebook SDK to check the validity of the access token (will return user_id and app_id fields if valid).
You can trust the user_id field returned from the Facebook API to check against your existing user database.

Facebook with dotnetopenauth

I have created an App on facebook and I am using this app to authorize an user via dotnetopenauth.
Here I would pass APPID and APPSECRET and get the token which would be used to call Facebook Graph to get facebook user details.
If I'm doing this for the first time, user would be asked to enter username/passowrd on the Facebook website and then the session is created in the browser and it will redirect to my website as a Facebook user. This means that if I open a new tab in the current window and open facebook, user will see his/her page directly without asking for username/password. - this is obvious and understandable.
// code
request = WebRequest.Create("https://graph.facebook.com/me?access_token=" + Uri.EscapeDataString(strAccessToken));
response = request.GetResponse();
My query is:
After the scenario above, if user logs out from Facebook website OR I close the browser window, the facebook session is lost. However, I still have the access token (string in the above code) that I got while authenticating.
So, As of this moment I am not storing any user information from Facebook (not even cookies or anything else). I am just requesting user to authorize my application as a Facebook user. When user does that, I get the access token which I can use it to make calls to Graph and REST APIs. This access token usually remains same, so I really dont need to pass the applicaition id and secret to get the token next time onwards. Actually I can request the graph APIs and REST APIs with the stored token and request user details. I have tested this and works fine.
What I am looking for is, if user opens www.facebook.com, user should see his/her personal facebook page which obviosuly is possible only if I have a session in the current browser. Hence, my question was: how do I use my access token OR what call should I make with my access token so that I can set the browser session for the facebook user? Is it possible technically?
Regards,
AG
No. Your access token is used by your web server to call facebook. It's impossible (and undesirable) for this to impact the user's browser in a way that would set a facebook.com cookie so that the user would be implicitly logged into Facebook by your use of the access token.

How do you renew an expired Facebook access token?

I am working from this reference, and trying to implement the OAuth protocol to allow users to log into my site via Facebook. However, Facebook's documentation is pretty terrible and it unclear in a few key parts.
It says that authorization takes three steps:
User authentication (redirect the user to https://facebook.com/dialog/oauth?client_id=...&redirect_uri=..., and expect the redirect_uri page to be called back with a code). Works great!
App authorization (handled by Facebook, etc). Works great!
App authentication (On the callback page, grab the code you get and call https://graph.facebook.com/oauth/access_token?client_id=...&redirect_uri=...&client_secret=...&code=.... The body of the response will include an access_token we need to do stuff)
I understand that with the access_token, I can call the APIs and such. But, what happens when it expires? I could get a new one, but by this point it will be many HTTP requests later, and I no longer have the code I used to get it in the first place. Do I have to store the code along side the access_token? Or, do I have to tell the user to log in again so I get a new code to get a new access_token?
Or, am I missing a key part here? I don't need an offline_access token, as I will only be polling data in response to user actions .
When the access_token expires, the user will be seen as "logged out" by Facebook. Your app will go through the same process as the first time, but the user may not.
If the user hasn't revoked access to your app, and the user is logged into Facebook at the time, the App Authorization process will take care of itself, with no actions required by the user, and you will receive a new access_token.
If the user hasn't revoked access to your app, but isn't logged into Facebook, they will be presented with a Facebook login at the App Authorization step. They won't be asked to give your app permission again, as Facebook knows that your app id is authorized by that user.
Finally, if the user has revoked access, then they will be presented with the original request for App Authorization, and you'll follow the original flow.
Essentially, you should consider the access_token as volatile, and not bother storing it, but using the access_token you receive as part of the user login process, which is happening behind the scenes all the time, and only involving the user when they log out of Facebook or revoke access to your application.
This is different than Twitter's OAuth with which you can store and re-use it.
From the Facebook documentation linked in your question:
Once the token expires, you will need to re-run the steps above to
generate a new code and access_token, although if the user has already
authorized your app, they will not be prompted to do so again.
When the access_token expires you will need to get a new one by going back through the same steps. The user will have to log in again and you will have to get a new code and in turn, a new access_token.

is it possible to access user's wall info without passing his/her access token?

I wonder is it possible to access user's wall info without passing his/her access token?
for example, I will just pass my app secret token and app id. and FB user already allows to access his/her info from my app. Facebook does the checking and matching of my app and my app's user by just using my app secret token and app id.
Because I found some topics similar to that.
http://forum.developers.facebook.net/viewtopic.php?pid=9172
When I check Rest FB doc,it says like that.
http://restfb.com/javadoc/index.html
public DefaultFacebookClient()
Creates a Facebook Graph API client with no access token.
Without an access token, you can view and search public graph data but can't do much else.
I doubt that it will work or not without access token.
can everyone share me ideas or any possible similar approaches ?
Thanks.
You will need to ask the users to authorize your app for offline access. You will be able to access the user's wall even if the user is offline, but you still need the access token. It is part of Facebook's security measures.
There are two types of access tokens:
Session based: expires in a short term, are used when the user will be logged to FB every time you need to perform an operation.
Offline access: do not expire and allow the app to perform operations for the user in any moment. This requires the offline_access permission when the app is authorized.
Check here: http://developers.facebook.com/docs/authentication/ for the oauth mechanism and here: http://developers.facebook.com/docs/authentication/permissions/ for the permissions list.
The REST API is deprecated and it is strongly suggested that you don't use it anymore. Furthermore, from this October you will be allowed to use only the Oauth2 authentication (see When is Facebook turning off their session based auth?)
Without token you can only access public information.
Public data
From RestFB homepage :
// It's also possible to create a client that can only access
// publicly-visible data - no access token required.
FacebookClient publicOnlyFacebookClient = new DefaultFacebookClient();
If the user does not protect his posts, then you can access everything without token. But most of user do protect their data and then you need a valid user access token to read the data.
Private data
When you say "FB user already allows to access his/her info from my app" it means that the user has clicked on "Allow app" in the web browser and at that moment here Facebook will give you a token. You can after use that token with RestFB :
FacebookClient facebookClient = new DefaultFacebookClient(USER_ACCESS_TOKEN);
User user = facebookClient.fetchObject("me", User.class);
out.println("User name: " + user.getName());
By default, the token will expire a few hours later. If you ask for the offline_access permission, the token will be valid for ever (as long as the user does not remove the permission for your app in his settings). You should store that token in your database to be able to use it when you need.
Get the user token
You cannot get the user token with RestFB. On the RestFB homepage, you can read :
Non-goals: [...] Providing a mechanism for obtaining session keys or OAuth access tokens
Because you need a browser to do so : the user has to authenticate and authorize your app on Facebook website (the popup that shows).
What you can do is to have a PHP page on which your users have to go to authorize your app. You can read this stackoverflow answer that explains how to use the Facebook PHP SDK to do so.
Hope that helps !