Refreshing user facebook tokens - ruby

I have an application in rails which is heavily based on facebook oauth2. At a glance - user signs in with FB connect and can list it's pages (and do some stuff with that data but that's not important right now. Let's just focus on signing-in and getting pages list).
After a sign-in, i'm saving user access_token and expires_at in the db. Then, each time i need to make a request to facebook api as a user (to obtain his pages list), i'm checking if expires_at is not past and if it is, i'm renewing user token using a following snippet:
def refresh_facebook_token
# Checks the saved expiry time against the current time
return unless facebook_token_expired?
# Get the new token
new_token = facebook_oauth.exchange_access_token_info(
old_access_token)
# Save the new token and its expiry over the old one
self.facebook_auth = {
uid: uid,
access_token: new_token['access_token'],
expires_at: Time.now + new_token['expires'].to_i
}
save
end
This works most of the times but, from time to time, my code throws:
type: OAuthException, code: 190, error_subcode: 460, message: Error validating access token: Session does not match current stored session. This may be because the user changed the password since the time the session was created or Facebook has changed the session for security reasons. [HTTP 400]
in line with exchange_access_token_info.
That error is thrown fo my own user and i can say that i didn't changed the password so i'm not sure what's that caused by nor how can i deal with refreshing the tokens by backend in a bullet-proof way.
Any help much appreciated!

First of all, I would recommend you go through this link and decide which configuration makes sense for your application - using short-lived or long-lived or what.
Now, am not too sure but I think that you are considering the method exchange_access_token_info as the token refresher. If so, this is NOT the case! Once a token is expired, it's useless.
exchange_access_token_info method simply takes the short-lived token (which is currently active) and convert it into the long-lived token using app id and secret.
Just understand that-
The user access token cannot be extended infinitely again and again without any user's interaction with your app for 60 days.
So the flow is very simple-
you get the short-lived token when user authenticates your app (user engagement on front-end)
on server-side you extend the token's validity to 60 days.
want to extend the token validity again? - repeat the steps.
Hope that helps!

Related

I want to use Google API refresh tokens forever

There is a process to obtain a refresh token via OAuth authentication for Google API, and then obtain an access token from the refresh token to validate the receipt.
The other day the refresh token suddenly expired and the receipt validation failed. Our service stopped processing billing.
Below is the error when it failed.
{
"error": "invalid_grant",
"error_description": "Token has been expired or revoked."
}
I thought refresh tokens reset their expiration date each time they are used, so why did they expire?
I don't think the following rules apply.
You must write your code to anticipate the possibility that a granted refresh token might no longer work. these reasons:
The user has revoked your app's access.
The refresh token has not been used for six months.
The user changed passwords and the refresh token contains Gmail scopes.
The user account has exceeded a maximum number of granted (live) refresh tokens.
The user belongs to a Google Cloud Platform organization that has session control policies in effect.
(https://developers.google.com/identity/protocols/oauth2)
I want to use the refresh token forever.
Thank you in advance.
Refresh tokens do not expire by design there are a few things that can cause them to expire as you have listed. However there is one you have not listed.
If you check the docs for Experation you will find it also says.
If your app is in testing set it to production and your refresh token will stop expiring.
So as long as your app is in production, the user does not revoke your access, and they have less then 50 outstanding refresh tokens for that user, and you have used it at least once in the last six months. (gmail scope the user does not change their password). The refresh token should not be expiring.
That being said your system should be designed to handle a refresh token expiring and request access of the user again. or notifying the admin if this is a backend system.
Thank you for this interesting conversation. It looks like in my case, after having got an access_token and a refresh_token, which I use regulary to invoke the Gmail API, it no longer works after 6 months.
Could someone point me to a code example in Node, showing how to update the tokens on a regular basis? (I store them in a database, and wonder how to update the record appropriately via the google.auth.OAuth2 API).
I have made hundreds of searches but could not find anything else than "you should refresh your tokens" :)
It looks like
oauth2Client.on('tokens', (tokens) => {
logger.info("tokens=%o", tokens)
})
is only invoked once when establishing the connection, so it will not help.
I have also tried:
let x = await oauth2Client.refreshToken(database_refresh_token)
let refreshedToken = x.tokens.access_token
To store the new refreshed token in the database, but this does not help after 6 months. FYI, thanks to oauth2Client.getTokenInfo(refreshedToken) I can see that refreshedToken expires in 1 hour.
Finally, is there a way to test, without having to wait for 6 months?
Many thanks!
By last answer...
It means we can used one refresh token for 6 month. right ?
And after 6 month we have to update refresh token. right ?

Server-to-server Facebook Access Token expires

I am building an Integration that allows users to schedule creation of Custom Audiences on the Facebook Ads platform. Once the user authenticates, we pass the client side token to the server from the client and then exchange their short lived token with the ads_management permission for a long-lived token, but that token only lasts 60 days?
The idea of the integration is that the user can set it and forget it (but disconnect any time). Now it seems like they need to visit the app at least once every 60 days. Is there any way around this? In my app, the person who turns on the Integration might not necessarily visit the app, or could leave the company and the integration would then break in 60 days.
You can simply ask Facebook for a new access token by passing your current access token.
It's as easy as exchanging the long-lived token, just re-call the same operation (using the current long-lived token). You will get a new one.
I suggest doing so some days before it expires (say, 10 days). This will ensure your system is going to have a spare time if any error occurs (e.g. Facebook's server down, User rejected permissions on your app, ...).
Just like Michael Hirschler said in his answer, you can simply use the old (non-expired) access token to fetch a new one. You should save the expiry date returned on every request when getting an access token: (This property is called expires_in)
{
"access_token":"{long-lived-user-access-token}",
"token_type": "bearer",
"expires_in": 5183944 //The number of seconds until the token expires
}
When expiration date is almost reached, you can use the same api endpoint for that with some changed query params. Insert your old access token as the user-access-token.
curl -i -X GET "https://graph.facebook.com/{graph-api-version}/oauth/access_token?
grant_type=fb_exchange_token
client_id={app-id}&
client_secret={app-secret}&
fb_exchange_token={user-access-token}"
As you can see, you will also need your app-id and app-secret for doing so.
Further reading: https://developers.facebook.com/docs/facebook-login/access-tokens/refreshing/

How to increase the expiry date of access token + Spring boot + OAuth?

We have a restful API developed on spring-boot V1.5.7 and it is secured by OAuth with "password" grant type. We are using only access token, the refresh token is not being used. The validity of access token is set to 15 mins. Initially, we hit the token endpoint and get the token and consuming the services. Though the services are being consumed very frequently the access token is getting expired after 15 mins. What we are expected to do is, when the services are not being called for 15 mins only then the token should be expired.
Can anyone please help me on this?
Looks, First we need to know Why we used access token?
Access token is used for accessing protected resource. It has a validity periods say for example 1min, 10min etc. After that time, token becomes invalid. To get a new valid token you should use refresh token.Though you can get a completely new token using your username and password. Even if you invoke any api within the expiry time though, the token invalid after the expiry time. If you don't invoke any api within the expiry time, token becomes also invalid. This is expected behavior.
Why this is expected?
Suppose you get an access token from server and access protected resource from server with access token. Somehow man in the middle get the token by sniffing packet. Then intruders can get easily access the resource as you can and as much time he want's. So technically we can say that, your account is being hacked.
To prevent this attack, you should define a token validity periods that would be suit for your use case. So this is more secure than previous.
I would strongly recommended that allow refresh token for your system.
However You can also configure your system to reuse the token. This link may be a help.
You can use OauthRestTemplate (if you don't want to write your own logic) which will fetch a new the access token (using refresh token) after it is expired. There is no reason to not use refresh token if you are planning on using OAuth in your application.

Validate whether Google API Client's OAuth2 access token is still valid before using it

Starting from the point where an user has given permissions to the app, and the access token is stored in session. Following Google's web server app example, I'm just checking whether an access token exist.
However, the token might expire, or the user might remove it manually on his account page. How do I check that the token is still valid, before executing a request?
Or maybe that approach is wrong, and the correct design includes that I should handle the error after executing the action, and if it's an authorization error then show the user a way to authorize it once again?
The latter is the recommended approach. By assuming failure and dealing with it routinely, your app is much more robust. The only downside is that an access attempt takes a bit longer because of the need to fetch a new Access Token and retry. If that's a problem (it shouldn't be normally), then you can always note the expiration time of the new Access Token and set up a background process to renew it with say 5 minutes to spare.

Refresh Tokens - Server Side Storage And Revoking For Multiple Clients

I'm getting started with token based authentication using the ASOS (AspNet.Security.OpenIdConnect.Server) framework.
I've got the access token generation and retrieval done and am now moving on to the refresh token bit.
My questions are:
How should I store the refresh token server side?
Should I just store the clientID and the hashed and salted refresh token in a database (Along with utility fields, such as an expiration date)?
What is the expected behaviour if a user of my API has a single clientID and secret, but performs many calls concurrently (Suppose they want to scale out the client on their end across multiple machines to get better throughput for example).
Specifically, I mean what if 1 of the client's access tokens expires, but their refresh token has also expired?
Of course they can go to the token endpoint to get a new access token and refresh token at the same time, but then what about the other instances for that clientID? Assuming that their code is identical (i.e. they don't share knowledge of the refresh token), each instance will also go on to request a new access and refresh token.
If you store a single refresh token for a clientID, you'll end up excessively requesting refresh tokens, potentially every time the access token expires, which would be undesirable.
If you store multiple refresh tokens for a client, how many is a sensible number?
Also, what is the common process of revoking the refresh tokens?
Is it as simple as just deleting it from wherever you're storing it?
Thanks.
Should I just store the clientID and the hashed and salted refresh token in a database (Along with utility fields, such as an expiration date)?
The approach I recommend is to use the ticket identifier attached by ASOS to all the tokens it creates. You can retrieve the refresh token identifier and the expiration date from the SerializeRefreshToken event via context.Ticket.GetTokenId() and context.Ticket.ExpiresUtc.
Note: the default identifier is a GUID but you can replace it using context.Ticket.SetTokenId("token identifier").
Specifically, I mean what if 1 of the client's access tokens expires, but their refresh token has also expired? Of course they can go to the token endpoint to get a new access token and refresh token at the same time, but then what about the other instances for that clientID?
It really depends on your application requirements and how you implement that. You're free to consider refresh tokens as completely independent or, conversely, interdependent. This logic would usually take place into HandleTokenRequest.
Also, what is the common process of revoking the refresh tokens? Is it as simple as just deleting it from wherever you're storing it?
If you use the default token format (more than recommended), refresh tokens will be considered valid until they expire. It's up to you to check whether the token has been revoked from HandleTokenRequest by making a DB lookup (you can get the refresh token identifier using context.Ticket.GetTokenId())

Resources