Authenticate chrome extension using Facebook - facebook

My extension needs to periodically send some data (in the background) to the the server with auth information about the user from FB. So I obvisouly need to send FB token with the data.
Right now I am opening https://www.facebook.com/dialog/oauth?client_id=<APP_ID>&response_type=token&redirect_uri=http://www.facebook.com/connect/login_success.html in a new tab, then retrivieng a token from a hash (using background page), then storing it in localStorage.
But lets say user closes his browser and opens it after the token expires. How should I retrieve a new one without user doing lots of additional clicks?

I'd suggest you should request long-lived token via your server and store that along with the calculated time of expiration that you can get from token debug API in the local storage. Then you refresh the token before it expires to avoid re-authentication.

Related

Should I store my refresh token in database?

I have a website in node js and react js. Whenever a user signIn on my website, they recieve a refresh token which is stored in an httpOnly cookie and an access token which is stored in the memory. When the access token expires I sent the refresh token in the request to get a new access token but I cannot understand where to store the refresh token. Should store it in my database because once the httpOnly cookie expires, there will be no way to get that back. So should I store it in the user object or in an array where all the referesh tokens are saved and whenever a request for new access token comes, I find the refresh token in that array and if it exists, I give them new access token.
Please suggest a safe way
It's better to store a refresh token locally. If the database would get hacked, the hacker would have unlimited access to the accounts using the refresh tokens. For more information, check out this post on Stack Overflow
Both access_token and refresh_token is stored on client end. This client end either could be browser or system (invoking the apis). For browser, you can store the refresh token in local storage or in other available options. For external systems, it could be secure storage which can be a database.

Storing access tokens and handling their expirations

I'm using OAuth as:
a secondary method to sign users into my web application (rather than manually providing their name, email and password)
a way to receive to receive user data throughout the website.
What would be considered best practice when storing access tokens? I have two options:
Store access tokens in cookies
Store access tokens in a database
What are the advantages and disadvantages of either choice?
Regarding token expirations, what should be done to handle this?
One way I know I could handle this is by checking whether there was an error when calling the API and so requesting a new token and then calling the API again. However when requesting a new token, will I require the user to sign back in again? I would imagine this would be a problem when a page on my website requires data from Facebook, but to retrieve it, users have to log back in.
I don't understand how other websites manage to maintain access to Facebook, Google or Twitter APIs without requiring me to log back in again, especially when I'm on another device where I haven't once logged in to Facebook, Twitter or Google. How do they do this? Thanks.
If authentication is done using Google OAuth2.0. Google provides two tokens namely, Access Token and Refresh Token.
Access tokens have limited lifetime for 3600 seconds , but refresh tokens are valid for longer period of time.
Refresh token also expire. Read "Token expiration" section of the Google OAuth2.0 link
One can obtain new access token from refresh token without re-login. ReST api
So, one can have logic implemented to check for time elapsed after access token was generated and take precautionary steps for new access token generation.
Google tokens expire in 3600 seconds, so one can get access token say after every 3500 seconds and update the older access token stored with new one for further use. Also one other way could be, to set refresh token in GoogleCredential which is passed as parameter(httpRequestInitializer) while creating the service of any api.(For example look for Drive.Builder)
If you are not storing refresh token from which access token can be regenerated, you have to authenticate again to get new token.

Should One Reuse a Facebook Token or Reuse a Facebook Session when Browser is Redirected to a New Page?

In using facebook sessions to interface from a website with a user's facebook data, when should one preserve a facebook session and when should one preserve a facebook token?
After a facebook session is established on a particular page and the browser is redirected to a new page should the session be saved and reused or should the facebook token be saved and a new facebook session created from that facebook token?
This?
$session = new FacebookSession($_SESSION['token']);
Or this?
$token = $_SESSION['session']->getToken();
You didn't specify your app's environment (canvas, website, etc), so I'm doing a lot of assuming but...
I only use canvas apps and for the most part the PHP SDK will handle all that for you when set up correctly (for instance if the user opens a new tab from within your app). If you need to make a request to another page without any login flow (like what you're asking), I just save the access token and create a session from there. Every time a user logs into my app I save their access token to my database. While they are using my app, I can use that access token on to make calls to pages user's don't interact with but still get their FB info that I need. After a while that token expires, but while a user is interacting with my app I don't need to worry about them expiring as I will acquire a new token once they log in again at some future point in time.
So just save the token and match it with a user ID. Then use that token to create a session where you need it. If you need to interact with information far beyond when a user has logged out of your app, you might need the extended life access tokens.
https://developers.facebook.com/docs/facebook-login/access-tokens/#extending

Is it possible to renew long lived access token in Facebook using an api call?

Facebook documentation states that
. At any point, you can generate a new long-lived token by sending the person back to the login flow used by your web app - note that the person will not actually need to login again, they have already authorized your app, so they will immediately redirect back to your app from the login flow with a refreshed token - how this appears to the person will vary based on the type of login flow that you are using, for example if you are using the JavaScript SDK, this will take place in the background, if you are using a server-side flow, the browser will quickly redirect to the Login Dialog and then automatically and immediately back to your app again.
What does it mean that the person does not actually need to login? Does not he have to pass his credentials again? If not how does FB is authenticating the user and getting the refreshed access token?
Yes but you need that the user visits your web app. Then you check for login status, if it is "connected" you will get a new short-lived token without even making the user login again. That's because the token has information about apps already authorized by user. If not the case or the user hasn't login in FB then you need to call the login function.
Once you have the token you can create a new long-lived token again.

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.