oAuth: request token invalidates current access token - intuit-partner-platform

Our app already implements oAuth to obtain the access token and secret from Intuit, and all works well.
The app takes into account that users may have multiple QBO companies. Consequently, when a user tries to authorize access to one company, our app checks whether this company has been already authorized, and if it has, the app lets the user know so and does not try to re-authorize the company.
The way we implemented this is as follows. When the authorization process starts, we send or app the list of companies (realm ID) which have been authorized. The user clicks the "Connect to QuickBooks" button and follows the wizard. Internally the app gets the request token and it is ready to make the access token request. The request token request gets us the realm ID so we can compare it with the list of already authorized companies. If the company has been authorized we do not request the access token and let the user know that the company has already been authorized.
Up until a week ago this used to work -i.e. in this case, because the app does not make a request for the access token, the access token the app has is still valid. However, now something seems to have changed so that when the app makes gets the request token, even though it does not ask for the access token, the existing access token is not valid anymore and the user need to re-authorize the company again.
Has something changed in the oAuth flow implementation ?
Thanks

OAuth tokens are valid for 180 days(bydefault). So, please check if existing tokens are getting more than 180 days old. If so, please use 'reconnect api'.
Ref - https://developer.intuit.com/v2/docs/0050_quickbooks_api/0020_authentication_and_authorization/oauth_management_api#Reconnect
One suggestion -
You can implement SSO( using 'sign in with intuit' wizard) in you app. That way you can relate end-user's SSO URL with OAuth tokens of his company while persisting those in your app's db. For the very first time, end user will generate tokens through C2QB flow. Next time onwards whenever the end user will sign in, your app should retrieve his oauth tokens using his SSO identifier(your app should show 'Disconnect' option instead of C2QB if he already has an established connection).
Thanks

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.

What is access token in facebook API?

What is access token in Facebook API?
why I need it ?
What is its purpose ?
Do I need to store it persistently in my website ?
For almost every request you make to facebook API you need to pass access token along to get the results. This token may expire depending on what kind it is, you might need to persist it in case your application need to access facebook API when user is offline.
PS: Access token comes from user's request to your application.
Facebook implementation of the OAuth 2.0 involves three different steps: user authentication, app authorization and app authentication. User authentication ensures that the user is who they say they are. App authorization ensures that the user knows exactly what data and capabilities they are providing to your app. App authentication ensures that the user is giving their information to your app and not someone else. Once these steps are complete, your app is issued an user access token that you enables you to access the user's information and take actions on their behalf.
access token will be expired unless the user has granted to your app the "offline_access" permission. In other word, unless you have such a perm granted, you don't need to store it persistently in your website.

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.