We have built an app that asks for access to the YouTube API. We are not authorized yet, but are using it with our own accounts. We have the following problem:
While some of our Gmail accounts grant us access, some others fail even though on their third party security settings, you can see that they have granted us access. It seems that they have removed us from their lists, even though they haven't and we know that since these are our accounts.
Has anyone seen something like that?
Is getting our app authorized going to solve this?
Is there any other solution that you could offer?
Thanks for taking the time
my error message
status code: 400, response { data: { error: 'invalid_grant', error_description: 'Token has been expired or revoked.' } } }
Token has been expired or revoked.
Normally means that the refresh token you are using is no longer valid and you need to reauthenticate your user. The easiest way to test if i am right is to do just that force a reauth on the user.
causes for refresh token experation.
Refresh tokens while long lived they can expire for several reasons.
The user goes into their google account and revokes your applications access.
The refresh token hasn't been used in a while normally 3 -6 months google will automatically expire it.
You have reached the maximum number of outstanding refresh tokens for a user the oldest one will be expired.
It can also be related to the time on your system being out of sync with NTP (note i havent seen this error in years)
Let me try and explain number three a bit more. When a user authenticates your application you are given a refresh token. When the user authenticates your application again you are given an other refresh token. Both tokens will work as expected. You can continue this until you have up to 50 outstanding refresh tokens once you hit number 50 the first and oldest one will be expired. This is why it is important to always save new refresh tokens over the old one.
Related
I have a webapp which lets the user OAuth 2.0 to youtube & after exchanging the authorization code I can capture the access_token & refresh_token into my database .
Can these tokens be maliciously used later by me , say after 2 weeks , to delete the poor user's video using /yoube/v3/delete or some other operation like insert badly formed captions ..
& if this could be done isn't this a security breach cause the poor used who has accidentally consent ouath into my application & got his access_token & refresh_token & other info captureded by my back-end
So basically when someone consents ouath's to an application ...the user is now on the mercy of the application...like information could be stored or deleted or anything
If yes? what can the poor user do to unlink & how would the user even know that video's are getting deleted by someone else ?
Access tokens are short lived tokens which will work for one hour after that time you will need to use the refresh token to request a new access token.
Your refresh token should not expire except.
if it has not been used for six months.
If a user authenticates your application they get a new refresh token, If they authenticate your application again then will get another refresh token. You can have up to 50 outstanding refresh tokens all will continue to work until you go over that number then the first one will expire.
The user can also revoke your access though their account at any time.
Don't bother storing the access token just store the refresh token, and make sure that if your user authenticates your application again that you replace the refresh token in your database with the new one.
If a user grants your application offline access which will give you a refresh token. Yes they are at the mercy of your application which can do what ever you have been granted access when ever.
Note: it can take a while to go through the verification process with the YouTube API start early.
Application is intended to be used by the company for managment of intercompany documentation. These documents can contain valuable information, so it must be secure application. I am using Oauth2 with access and refresh tokens. Access token is valid for 15 minutes and refresh token is valid for 1 day.
I have not found any recommended lifetime for tokens.
Is 15mins for AT and 1 day for RT good? If yes, why these values are good enough OR are not good enough?
What is optimal lifetime for AT and RT for application which must be really secure.
Thanks a lot!
Gmail vs. bank accounts.
I can't tell where your business falls under. You should sit in in a meeting with your product team and explain what happens and let them decide. It's ok if it takes some try and error to get the right number.
But for Gmail the refresh token almost never expires. I can't think when was the last time I had to enter my credentials again.
For banks, the refresh token seems to be valid for only 10 minutes and if you background the bank app then you won’t be able to get a new refresh token and so you get signed out. Like my bank of America app. If I keep the app open then the app will continue to refresh the token.
And obviously refresh token expiry time should be more than your average user's session time.
I've seen this issue in a lot of questions, but so far, none seem to apply to my situation.
The problem we are having is we are getting an "invalid_grant" error when we attempt to get an access token. This only happens to some accounts, but when it does happen, in every case I looked at, the refresh token worked before, and now has stopped working. This is happening far to frequently for it to be customers revoking access (seems to be nearly 20% of the channels we manage in the last couple weeks have been invalidated).
As a note, we have a backend process that uploads the videos to our customer's YouTube channels.
We use OAuth2 to get a refresh token, here are the parameters we send...
scope = "https://www.googleapis.com/auth/youtube",
client_id = "",
response_type = "code",
access_type = "offline",
approval_prompt = "force",
redirect_uri = "http://www.us.com/OAuth/YouTube"
NOTE: for client_id we use the email address that is in the Google API manager (or was, I just looked and it is no longer there). We used to use the client ID from this page, but that caused us problems as well. Did this change? Should we be using the client ID from this page now?
We exchange the code that is returned for a refresh and access token and store the refresh token in our database.
The backend process exchanges the refresh token for an access token and this is where we seem to be getting the "invalid_grant" error.
Guaranteed only a single access token for the channel is in use at any time (25 limit doesn't apply). We don't store the access token, we get a fresh one every time we process a channel.
Any ideas what might be happening? Something to look for? See note above about client ID. This might have something to do with it, but I'm hesitant to try it since using the "Client ID" from the API manager caused problems before.
Guaranteed only a single access token for the channel is in use at any time (25 limit doesn't apply). We don't store the access token, we get a fresh one every time we process a channel.
This statement is incorrect: Access tokens can be used as many times as you need while they are still good (for an hour).
Answer:
"invalid_grant" basically means that your refresh token no longer works. The only solution to the problem is to request access again and get a new one. The question should be why is it expiring in the first place.
Assuming that the user did not revoke access, and that the refresh token has been used to request a new access token within the last six months. This is probably an issue with it being over written.
When a user authenticates your application you are given a refresh token. This refresh token is associated to the client id of your application and the user who has just authenticated. If said user then authenticates your application again you will get another refresh token. Again this refresh token is associated to the user and your projects client id. Both of these refresh tokens will work. Your user can keep doing this up to 25 (Note I think the changed it recently to 50 but I haven't tested it with all APIs yet) once they have hit this magic number the first refresh token will expired and if you try and use it you will get an invalid grant.
The only solution is then to just request authentication again. It is important to always save the most recent refresh token that your user has granted your application. In the event (like me) you have an application that is stored on a number of servers all requiring authentication. Your going to have to tell them not to refresh it to many times or they will have to go back and reauthenticate the first one that they expired.
If this is happening with ALL of your requests. You can also check that you server is sync with (NTP) and that you are sending the payload of your request in the post field. Not attached to the authentication end point like a HTTP GET (been there done that).
Here are the possible reasons why a token stops working and becomes invalid:
The user has revoked access.
The token has not been used for six months.
The user changed passwords and the token contains Gmail scopes.
The user account has exceeded a certain number of token requests.
As you can see, it's not recommended that you request a fresh one every time you process a channel. As also mentioned in Token expiration:
If you need to authorize multiple programs, machines, or devices, one workaround is to limit the number of clients that you authorize per user account to 15 or 20. If you are a Google Apps admin, you can create additional admin users and use them to authorize some of the clients.
With regards to the use of client_ID, it is usually needed to call the sign-in API as mentioned in Creating a Google API Console project and client ID.
And lastly, this Google Groups discussion - OAuth 2.0 400 - error:invalid_grant and ideas? might also help.
I have developed a rails application that allows a user to login using their google account and then the application fetches the emails and parses them for information.
All this works fine, but I am facing issues with access token become invalid, hence I have been looking into refreshing the token. I found some code at:
https://stackoverflow.com/a/14491560/718087
With this code I have been able to get a new access token that works. But I have a few questions:
How many times can I use the same refresh token I got the first time? or do I need update my refresh token as well, each time I get a new access token? note: application is setup with offline access.
Do I need to refresh the token before it expires or it will still return to me a valid token after the old access token has expired? This will allow me to decide an approach as to when I should refresh the tokens - a: right before fetching the emails, b: automatically before the token expires via delayed jobs or something (this would add quite a overhead though)
I have gone through the api docs but could not find answer to my these specific questions. Please excuse my overly detailed queries.
Thanks,
Aditya
Refresh tokens never expire, unless revoked by the user. You should store it safely and permanently. You should definitely not go back and get new refresh tokens over and over, because only a certain number can be understanding per user/app combination, and eventually the older ones will stop working.
In answer to your question: "Do I need to refresh the token before it expires or it will still return to me a valid token after the old access token has expired?"
I have a rails app, and I check for expiration & refresh token existence:
if client.authorization.expired? && client.authorization.refresh_token
#then I refresh here...
So the answer is, Yes you can (and probably should) wait until your access token expires, and then refresh it.
Facebook's deprecation of the offline_access permission is coming May 2012 and the documentation isn't giving us enough information on how to handle it.
We have an iOS app and corresponding service that powers it and integrates with Facebook in a deep way to leverage a user's friend list within out app (so if your FB friends are also using the app you can more easily connect). This is like how all social apps seem to work, so nothing special here.
Client
Our app uses Facebook iOS SDK to allow user to login, which we currently ask for offline_access. The token is persisted in our iOS app, but also sent to our server where it is saved. The client acts on behalf of user to post updates to a user's newsfeed (we also ask for publish_stream permission).
Server
Our server periodically checks to see if user's FB friends are now using our app. Next time user signs in, we expose content and relationships in a certain way to promote that user's friends. The server also acts on behalf of the user to periodically connect to the graph API and get the user's current friends list. This is so we can account for changes in a user's relationships and have them reflected in our app. We do this when the user isn't currently using the app so they have the best experience the next time they do use it. To enable this, our iOS app sends the access token to our server which it uses and why we ask for offline_access.
Note: If user signs out of our app explicitly, we delete the access tokens from both client and server.
Problems
Now that there is no longer a perpetual access token we can use, I'm trying to figure out the best practice for still enabling our scenarios while leveraging facebook's new intended way of handling and extending access tokens. The documentation is unfortunately not totally helpful.
Questions
A. When you authenticate through the newest Facebook iOS SDK, what is the default lifetime of the access token you get? This document says an extended token request will give you one that lasts 60 days. This other document talks about the first access token request and mentions varying validities but it's unclear and does it talk about specific validity times:
(emphasis is mine)
When you obtain an access token from Facebook, it will be valid
immediately and usable in requests to the API for some time period
defined by Facebook. After that period has elapsed, the access token
is considered to have expired and the user will need to be
authenticated again in order for your app to obtain a fresh access
token. The duration for which a given access token is valid depends on
how it was generated.
There are also events which may cause an access token to become
invalid before its expected expiry time. Such events include the user
changing their password, an application refreshing it's App Secret.
Dealing with varying access token expiry times, and handling the case
when an access token becomes invalid before its expected expiry time
is essential for building robust social experiences.
B. For the client, now that the access token isn't necessarily long lived, is the right approach for us to:
Let use login through FB, then detect whenever the access token is expired. If it is, then call into FB iOS SDK to re-authentication/re-authorize? (this should just trigger user to bounce out to FB iOS app, and in most cases come immediately back to our app with a new access token).
C. According to this blog post I found, you can only extend an access token once:
Can I exchange my 60 day access token for a new 60 day access token?
No, sorry you cannot. You can only exchange a valid (meaning current)
user access token for an extended one. You cannot extend an already
extended access token.
On the client, I can just handle this by prompting a re-authentication/re-authorization as I mentioned in Question B. However, this doesn't work on our server. We could certainly have the server renew it once to 60 days, but what happens on the 61st day? The server just stops being able to sync the friend's list?
D. It seems to make sense to check the validity of the FB access token every time the app starts or re-hydrates from sleep. What is the best way for our iOS app to check this? Is there a recommended endpoint to call to validate a token? Should we just call into https://graph.facebook.com/me passing the access token and checking the response?
Note: we can certainly record the expires time when we get the initially extended token, but this isn't reliable since the user could revoke our app's permission anytime which makes the expires time an unreliable data point on validity
Overview
I believe that the root of what facebook is trying to achieve is to prevent an app from having perpetual ever-lasting access to a user's account. So, with the new migration an app can only access an account for 60 days unless the user signs in again.
I don't work for facebook, but here are my findings from playing around with the facebook graph api.
General Solution
Whenever a user signs in, take their access token and immediately extend/refresh it, and save it
Record the expiration date of the access token
When an access token expires (either from the recorded date, or a graph API exception telling you so), then notify the user that you don't have access, and ask them to sign in again.
Answers
A. When you authenticate through the newest Facebook iOS SDK, what is the default lifetime of the access token you get? This document says an extended token request will give you one that lasts 60 days. This other document talks about the first access token request and mentions varying validities but it's unclear and does it talk about specific validity times:
Here's how it works:
The first sign-in grants you approximately two hours
By refreshing the access token, you can get up to 60 days
If the user doesn't sign in to those 60 days, there is no way to get access for longer without having them sign in.
If the user de-authorizes your app, that 60 day windows ends immediately, and you will no longer have access.
B. For the client, now that the access token isn't necessarily long lived, is the right approach for us to: Let use login through FB, then detect whenever the access token is expired. If it is, then call into FB iOS SDK to re-authentication/re-authorize? (this should just trigger user to bounce out to FB iOS app, and in most cases come immediately back to our app with a new access token).
If the users access token is expired, your only option is to have them go through a login loop like you are talking about.
C. According to this blog post I found, you can only extend an access token once. On the client, I can just handle this by prompting a re-authentication/re-authorization as I mentioned in Question B. However, this doesn't work on our server. We could certainly have the server renew it once to 60 days, but what happens on the 61st day? The server just stops being able to sync the friend's list?
You can only extend an access token once. On the 61st day, you are out of luck. Best notify the user and let them know that unless they sign in, you won't be able to do anything.
D. It seems to make sense to check the validity of the FB access token every time the app starts or re-hydrates from sleep. What is the best way for our iOS app to check this? Is there a recommended endpoint to call to validate a token? Should we just call into https://graph.facebook.com/me passing the access token and checking the response?
I haven't be able to find an API equivalent of the Debug Console. This FB blog article talks about invalidated access tokens, but doesn't mention any API methods in particular meant to test the API.
I your suggestion of hitting https://graph.facebook.com/me would work just fine is exactly what they recommend in their example. In fact, I might use this approach in my app as a pro-active way of checking an access token.
Tid Bits
When you "refresh" an access token, a new access token will be returned. The response looks like: access_token=TOKEN&expires=5183912
You can only "refresh" an access token once. If you try to "refresh" the long-lived token returned from a previous call, it will return the same token, but doesn't throw an exception unless the token has expired. (in other words, you can safely try to refresh your token)
The default access token length seems to be around 2 hours
If you "refresh" an access token, that new access tokens seems to be the one that you'll get from the facebook API afterwards (instead of returning the original, short-lived access token)
Also, if you want to play around, these tools make it easy to test out your use case in a browser before burying it in your code:
Graph API Explorer - For creating and getting access tokens
Debug Console - For checking the expiry date of tokens before/after refresh
Refresh Endpoint - For manually testing extending your tokens
Great answer, one important addition : the default token lasts between 1 and 2 hours. You get the remaining of the hour during which the user signs up, plus 1 full hour. For example if a user signs up at 3:45pm, the access token will expire at 5pm. To be safe developers should assume it only lasts 1hour.