Google token refresh returns "Token has been expired or revoked." - google-api

I have a Google OAuth2 client approved by Google, which provides offline access to user's account with required scopes. My backend application stores and uses the refresh token to refresh the access tokens as and when needed.
Lately, we are seeing that our token refresh attempt is met with an error from Google with:
{
"error" : "invalid_grant",
"error_description" : "Token has been expired or revoked."
}
There is no additional information.
Nothing has changed in my Google OAuth client. The user has not changed account password. The user has not revoked access to my client.
What could be the reason for suddenly getting such errors for token refresh? And how do I avoid this in future (if possible)?

Are you inadvertently asking for the refresh token multiple times? There is a limit of approx. 25 refresh tokens that an account can have extant.

I had same issue, because I run my code in 2 different files and what I did remove token.pickle file, re-run it again.

Related

my app is not able to receive refresh token from Google anymore

i have a very weird problem. I'm using the Google authentication API since moree than one month now and all working perfect. But now out of the sudden, my users can't get refresh token anymore. My app is on testing state, so i thought the refreesh token my testing user was having is expired after 7 days, but then i tried to get another refresh token by doing thee authorization from the beginning to receive a code that i use to get a refresh tokn. But no chance i'm only receiving this response back: Status code 400 { "error": "invalid_grant", "error_description": "Bad Request" }
Thank you very much for your help!
A Google Cloud Platform project with an OAuth consent screen configured for an external user type and a publishing status of "Testing" is issued a refresh token expiring in 7 days.
To stop your refresh tokens from expiring set it to production.
Why cant you refresh after seven days
What i am writing here is my opinion only from experience. There is no documented proof of any of this from googles side.
After seven days your refresh token will expire, but the question is how is google expiring these refresh tokens. From what i can see they are not using the normal method of expiring the refresh token. They are in fact revoking the users granted access on the google account. So the all of the refresh tokens granted will stop working at once.
So why are you having issues with the client library. Normally the way the client libraries were originally designed. if the refresh token expired it would prompt the user to authorize the app again. This does not happen with the seven day revoke method. IMO because the error message is different, and the libraries have not been updated to take this into account, and prompt for access again. The only way to fix it is to delete the old stored refresh token and request a new one.
So your not able to receive new refresh tokens because your code is stuck with the old one. Make sure to hard delete any old refresh tokens you have stored. They wont work and the library doesnt understand how to delete them on its own.

How do I refresh my google_oauth2 access token and refresh token?

I have an app that uses the Google Calendar API and I seem to have a corrupt/defunct access token and/or refresh token which is resulting in the following error:
Signet::AuthorizationError
Authorization failed. Server message: { "error": "invalid_grant", "error_description": "Bad Request" }
Code for the authorization:
client_id = Google::Auth::ClientId.new(CLIENT_ID, CLIENT_SECRET)
token_store = EncryptingTokenStore.new(TokenStore.new)
scope = "https://www.googleapis.com/auth/calendar"
authorizer = Google::Auth::UserAuthorizer.new(client_id, scope, token_store, callback_url)
authorizer.get_credentials(CALENDAR_ID)
On investigation the UserRefreshCredentials we get back from authorizer object has an expires_at date in the past (11/01/2021).
I deleted the offending refresh token that we have stored, revoked access via the google account settings, then reauthenticated the user account with the app to reapprove offline access to Google Calendar again. This did not give me a new access and refresh token as expected. The expires_at is still 11/01/2021. We have valid refresh tokens in storage but for some reason Google is still picking up the old details despite that refresh token no longer existing. So I need to find a way to refresh or overwrite the UserRefreshCredentials that the Google API is using.
Other steps I have tried:
I tried to refresh the token from within a production console with some methods that come with the ruby google client gem but this fails with the same invalid_grant/Bad request error that is at the root of this issue.
I also tried to refresh the token with a POST request to the oauth2 endpoint:
https://oauth2.googleapis.com/token?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&refresh_token=REFRESH_TOKEN&grant_type=refresh_token
but this also fails with the same invalid_grant/Bad request error.
If anyone can shed any light that would be much appreciated.

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 ?

VSTS API Refresh Token Expires

I'm using the VSTS REST API. I use the refresh token, as instructed, to refresh the access token. This morning, the refresh tokens stopped working. Do they expire? If the access token and refresh token have both expired, how do I proceed? I can't find anything on this.
For reference: https://www.visualstudio.com/en-us/docs/integrate/get-started/auth/oauth#refresh-an-expired-access-token
Yes, the refresh token will be expired, you need to send request to re-authorize to get access token and refresh token again (your previous steps to authorize).
The previous access token and refresh token have been expired after get new access token.
I manage the team that implements this flow. The answer from #starain is correct and this flow is described in detail in the OAuth 2 specification. Your observation that the refresh token is invalidated so frequently #scottndecker is not consistent with the implementation. A refresh token in our system has a default lifetime of one year. The token can also be invalidated manually by users. We obviously must honor the user's right to revoke a previously granted authorization. If you want to share some more information we can certainly look into this behavior.
Seems that when the auth.token expires (after one hour), the auth.refreshtoken become invalid too? What is the auth.refreshtoken purpose then? When I decode the auth.refreshtoken on jwt.io, it should expire sometime in 2020. (Now it's 2019).
While the auth.token is valid, I can refresh and get a new token. So is the idea that I should setup a job that refreshes the token within one hour?
The documentation claims:
If a user's access token expires, you can use the refresh token acquired in the authorization flow to get a new access token. This process is similar to the original process for exchanging the authorization code for an access token and refresh token.

Invalid Credentials - Google plus access token error

I have an issue with Google plus access token. It is giving me "Invalid Credentials" error message sometimes, sometimes the same token show as active.
Following are the steps
The user confirms permission to access Google account with selected scopes.
The refresh token and access token is retrieved and saved to long time storage.
Used to refresh the token when ever needed by using stored refresh token
But sometimes I've experienced strange behaviour:
Requests to Google APIs return Invalid Credentials (401) error. Refreshing the access token (using the stored refresh token) does not work.
Access token refresh method
Using googleapis npm module to refresh token
https://www.npmjs.com/package/googleapis
oauth2Client.refreshAccessToken(function (err, tokens) {
if (err) {
console.log('error', err);
}
console.log('access tokens', tokens.access_token); // Access token
console.log('refresh tokens', tokens.refresh_token); // Refresh token
});
Questions:
What can be the reason for this behaviour?
Does this behaviour related to with any google api rate limit? because the same token works sometimes and not other-times.
Is there a way to validate the refresh token?
Every time you refresh your access token using refresh token, you will given by new access token.The refresh token has no expiry. You can use the refresh token as many as possible for refreshing the access token

Resources