Facebook authentication and Ajax - facebook

I am building a Facebook application, and using the oAuth 2.0 protocol for authentication/authorization.
When a user first visits my app I am using the protocol and store the access token in order to make future requests to the Graph API. The problem occurs when the access token expires and the user is using ajax.
When the ajax request is sent I try to retrieve information from the Graph API using the access token, but since it expired I get a JSON saying the access token is invalid. Now, I can send a response back to the client saying the access token expired and on the client side I can redirect him to https://www.facebook.com/dialog/oauth to go through the authentication process again. However, since the whole process is in Ajax, redirecting the user will hurt the usability of the application.
Is there any other way I can use the protocol to get a new access token without needing to redirect the user's browser to get a new access token? Maybe something on the server side?

You just need to ask for the offline_access permission, then your access_token will not expire.

As Rafael notes, you can ask the user for offline_access and then the token should never expire. However, in practice, the access token does expire when a user changes their password or uninstalls/reinstalls your app, so you'll need to build a way for the user to reauthenticate themselves so you can update their token. I suggest redirecting them to a login page that should (ideally) just send them right back where you tell them to go without them having to do anything, and using deep linking to put them right back in your app where they left off.

I'm encountering this issue as well. One solution I came up with is as follows:
Create an async method called isAccessTokenValid()
Invoke isAccessTokenValid() before any method that will require FB interaction
If access_token has expired. save the current uri to the session, along with any form data entries (if any), and start the re-authentication process again.
Once the user has re-authenticated, bring up the stored uri.
This is a bit dirty, but I haven't seen a cleaner solution yet.

Related

Posting to Facebook on behalf of the user: how to handle token expiration?

I'm implementing a connect with Facebook/Twitter/... functionality on a website. The idea is that once a user connects his account with the external services our website could post messages on behalf of the user.
With Twitter there is no problem as the OAuth access_token doesn't expire. But with FB it does expire every two months, when the user logouts, changes password or explictly deauthorizes the app.
How should I handle the token expiration? For me it would be ideal if I could refresh the token automatically without bothering the user, but unless I've missed something it seems there isn't any way of doing this. So, right now I've two ideas:
The less akward way: every time the user logins to the website check if the tokens have expired and notify the user that she has too reauthorize the app.
The more akward way: every time the "post to social networks" event triggers in our website, check if the tokens have expired and ask the user to reauthorize.
The first option would be easier to implement and cleaner to the user.
So, how are you handling this situations?
Thanks!
I think that I'll trye the first option:
User logs in
The server checks if the user has already a Facebook token, if so:
Check if it's still a valid token. http://developers.facebook.com/docs/howtos/login/debugging-access-tokens/
If the token expired NOT because the user deauthorized the app BUT because the other cases we redirect the user to the OAuth endpoint.
I'll give it a try and update this answer if there is more to it.
If the user is actually interacting with your website, you should be getting a fresh access_token (read below). If you perform offline tasks related to the user using the Facebook API then you should be storing the access_token and their expiry dates. Then you need to handle expired access tokens and ask the user to interact with your app again and update your records.
You should refer to this document. Also you should be reading the Extending Access Tokens document:
Step 2. Refreshing Long-lived User Access Tokens
At any point, you can generate a new long-lived token by repeating the
original auth flow, obtaining a new short-lived token and then
performing the same exchange as above. In some cases, this newer
long-lived token can be identical to the previous one, but we do not
guarantee this will be true and your app shouldn't depend upon it.

When I should load a new access token?

My app uses Facebook Javascript SDK authorization on client side, and for authorized user app fetches access token from Facebook API, using facebook cookie with signed request and provided code, and store it into database.
Everything is working fine, but i'm wondering, when I should refresh stored access token? What if user have changes password, and have signed in/connected again.
As I understand, now she has new access token, and app should load it from Facebook. But how I can understand when I should check for a new token? Check on each request with facebook cookie doesn't work, because it's few request per second for each user (event if she didn't change a password). Or maybe i'm doing something wrong?
I mean:
I've authorized user on client side
I've cookie with signed request
Signed request is pretty enough to authorize user on server side (validate user credentials)
I can get access token by calling Facebook API, anytime when user user makes request to my app (because I need a code from signed request). So, i'm doing it when I don't have stored access token or existing access token has expired.
access token just stored in database, and can be used anytime, in different thread, maybe few minutes later (mean we don't have user request and cookie with signed request)
What if stored access token not expired, but invalidated on facebook side? I need to fetch new access token, but cookie has gone at this moment.
Currently I see only one way: store code from signed request into databse, and when we have found that we have invalid access token, try to load it. But i'm note sure that it's proper way, and not so much usable for most cases
You have client token and server token, the client one is short lived (a few hours) and the server one is long lived (60 days).
The token on the client side should not bother you too much since you can get a new one easily as it states in the "Handling Invalid and Expired Access Tokens" guide:
Desktop Web and Mobile Web apps which implement authentication with the Javascript SDK
Calling FB.getLoginStatus() or ensuring status: true is set when you
call FB.init() means that the next time a user lands on your
application and is signed into Facebook, the authResponse object you
are passed as a result of those calls will contain a fresh, valid
access token.
In this case, its simply the act of the user using your application
which implicitly generates a new access token.
The token on the server side, which you persist in the db, can not be as easily reproduced, the user has to be sent to the auth dialog again:
Desktop Web and Mobile Web apps which implement the server-side authentication flow
To obtain a fresh access token in this case you must pass the user
through the full server-side flow again: i.e. obtain a code and
exchange it for a new access token.
However, assuming the user has not de-authorized your application,
when you redirect the user into the OAuth Dialog, the user will not be
prompted to reauthorize your application, and will be immediately
redirected to your redirect_uri. This means that the re-authentication
process can appear transparent to the user.
You can of course send a client token to the server and persist that, but it's pretty pointless since it's short lived.
Another option is to use the new endpoint to extend a valid client token on the server side and then persisting that.
As for "how to know when do get a new token", on the server side when you are making api requests just check the response and see if an error returned and if so what it is (there's a list in the first url I added).
If the token has expired then just send the user to the auth dialog again (you can return some kind of code to the client side and do it from there) and then save the new token to the db.
There's no need to check cookies, those are used in the background but you should not have anything to do with them.
Edit
Don't use the cookies, they should not concern you at any time.
What you should do:
On the server side you should follow the instructions in the Server-Side auth guide, get the "code" and exchange it with a token.
That token will have 60 days.
Use that token, which you store in your db, as needed (other threads, what not) and when you are getting an error back from facebook saying that the token has expires just navigate the user back to the auth dialog page.
You can not use the "code" to get more than one token so that won't help you.
If the user session (and token) got invalidated (for various reasons) you will still get an error back from facebook when trying to make an api request, when that happens just send the user to the auth dialog again.

how do you handle realtime feed updates?

I'm working on a site that is trying to handle realtime feed updates from its users' Facebook accounts. I have the basic stuff in place: the app is subscribed to "feed", and the user's login asks for read_stream and offline_access (just in case) permissions. My test users have logged into FB and granted those permissions, and, when one of those users adds (or removes) a status update, the callback specified in my site's subscription is pinged. So far, all's well.
Now -- as I understand it -- my callback has to call up to Facebook to get the user's feed, so that the callback can do whatever it's going to do with it. That's where I'm having problems -- finding the right access token to retrieve the feed:
I've tried doing this with the app's access token. This token is able to retrieve friend information (also included in the app's subscription and user permissions), but it won't get me the feed.
I've tried all sorts of ways to get the user's access token from inside the callback, but nothing is working. I'm guessing this is because it's not "logged into Facebook" the way that a user in a browser can be, but whatever. Bottom line is I haven't found a way to get this token.
(BTW, if I cheat -- get an access token for the user from Graph API Explorer and hard-code it into the callback, the callback works properly. This is no real solution, of course, but it at least establishes that the rest of my code is working.)
So how does this work? Can the app access token be made to work somehow? Is there in fact a way for the callback to get an access token for an arbitrary authorized user? There's gotta be a way to do this, or there would be no point for realtime feed notifications. Any clues out there? This is SERIOUSLY kicking my butt... Thanks!
You might want to look into this. Instead of taking permission for offline access, facebook now gives short-lived access tokens (2 hours) when the user logs in. These can be exchanged with long-lived access tokens (2 months). Check out this article on how to go about it.
https://developers.facebook.com/roadmap/offline-access-removal/
I've found a solution, perhaps: When the user logs in, I snag their offline_access-enabled access token and save it in the app with the rest of the user's data. Then when I get notified of an update to that user's feed, I can pull the token from the database and pass it over to FB as the token part of the /feed... call. And, it works. There is no doubt some error handling to be done, but I am currently bouncing back and forth between thinking that (a) this is exactly the right way to handle this and (b) it's a terrible hack that is just asking for trouble. I guess I'll see which of these is the case...
Ask for offline_access (as you do) and store the access token. This is exactly why offline_access and access tokens are there, to make requests to facebook in the name of that user. (a) is the right way to go. (a) is the way I do it.
Good luck
When the user is authenticated via OAuth Facebook returns an access-token, but it is valid for few hours. The validity of this token comes with it as token-expiry.
However, this token can be exchanged with a new extended token which is valid for around 60 days. User the following code to get new-token:
URL url=new URL("https://graph.facebook.com/oauth/access_token?grant_type=fb_exchange_token&client_id="+appId+"&client_secret="+clientSecretId+"&fb_exchange_token="+fb_exchange_token;
InputStream Istream=url.openConnection().getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(Istream));
String new_token= br.readLine();
Hope it helps!!

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.

How to check my Facebook AccessToken? How to renew it? (.NET Desktop Application)

I've created a Facebook .NET Desktop Application. On the first run, the application opens a second window with a Web Browser directed to the authorization page for my application with the required permissions from the user.
If the user authorizes my app, Facebook is redirecting me to the static login_success.html and appends the AccessToken to the Hash (#) part of the Url of the browser rendered in my second .NET Application window.
I hand that AccessToken to my main application window and do my requests to the graph api on behalf of the respective user.
That's fine, and working so far!
But, how can I
check if the AccessToken I've stored is still valid and how
can I renew an expired AccessToken without bugging the user with the second browser window (of course assuming the user hasn't revoked the authorization for my app) and how
can I recognize that the user has revoked the authorization?
check if the AccessToken I've stored is still valid?
Try and use the token against the Graph, and if it give you an error (Something like OAuthException or OAuthError), it's not valid, else it still is.
Can I renew an expired AccessToken without bugging the user with the second browser?
No that I know of. But, AccessTokens (with the Offline Access permission) don't expire. I've received an AccessToken for one of my apps almost 2 years ago and it hasn't changed or expired, so I think you should be good. They might become invalid if your App Secret changes or if the user changes their password (I'm pretty sure on that last one, but not 100%)
Can I recognize that the user has revoked the authorization?
Yes, if you query the Graph with an AccessToken that is not authorized for that function, it will give you an OAuthException. Just check for exceptions after you receive Graph data and it will let you know, for the most part, why you weren't able to receive Facebook data.
Unfortunately, if your Access Token expires you have to get the user to go through Facebook to get a new Access Token. An offline_access token does not ever expire due to time, like joe_coolish pointed out, but it does expire if the user changes their password. So your program needs recognize when a user's access token is invalid and get the user "refresh it" by going through the oauth endpoint.
Recognizing that the user's token is invalid is the same process as recognizing that the user has revoked authorization for your application. Whenever you make a graph request with an invalid access token, Facebook will give you an OAuthException saying that you don't have access.