4

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.

Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
kanekane
  • 43
  • 1
  • 3
  • Refresh tokens do not last forever - typically days. You cannot change that. There are several reasons they can expire or become invalid. You must write code that can handle that event no matter the reason. – John Hanley Apr 07 '22 at 07:15
  • 1
    Thanks John! Our apologies. I forgot to write important information. Our refresh token was successfully generating access tokens for 6 months without renewal, and then suddenly became unusable. – kanekane Apr 07 '22 at 10:30
  • The fact that your refresh token lasted for six months does not matter. The important detail is that they will become invalid. Google is shortening the time between authorizations for security reasons. User-based OAuth refresh tokens will become invalid at an unspecified time in the future. Design to meet that requirement. – John Hanley Apr 07 '22 at 17:48
  • Thanks! I guess we expected too much from the "The refresh token has not been used for six months." spec. We will try to update it regularly. – kanekane Apr 11 '22 at 08:46
  • @DaImTo If a refresh token expires, what is the procedure to get a new one? Would forcing them to log back in yield a new valid refresh token? Or is there a specific way to obtain a new one? – reese Oct 30 '22 at 22:42
  • @reese that depends upon how and why the refresh token expired, and your code. Most of the client libraries will prompt the user to authorize the application again if the refresh token expires, with the exception if the refresh token was revoked due to the application being in testing. They haven't updated a number of the libraries to take into account that error. – Linda Lawton - DaImTo Oct 31 '22 at 07:25

3 Answers3

10

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.

enter image description here

If your app is in testing set it to production and your refresh token will stop expiring.

enter image description here

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.

Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
  • Thanks DaImTo for the answer. Our OAuth application is configured for production. Also, we created an access token successfully for 6 months and the service was up and running, but then all of a sudden the refresh token is no longer available. Is this behavior in accordance with the specifications? – kanekane Apr 07 '22 at 10:21
  • 1
    My advice to you is to ensure that you are always storing the most resent refresh token. If you use the refresh token to request a new access token. If a refresh token is return ensure that this is stored so that you are using that in the future. If this occurred during the time change for (spring fall) this can cause an issue with expiration. – Linda Lawton - DaImTo Apr 07 '22 at 10:31
  • Thanks DaImTo! So the approach of trying to use refresh tokens for a long time is not a good one. We will change the refresh tokens so that they are updated on a regular basis. – kanekane Apr 07 '22 at 10:39
  • The thing is that you can have max 50 outstanding refresh tokens. So if your not storing the latest one then the older ones can expire on you. – Linda Lawton - DaImTo Apr 07 '22 at 10:53
  • If this answer helped you please remember to accept it. it will increase your rep as well – Linda Lawton - DaImTo Apr 07 '22 at 16:21
  • 1
    Thanks for being so kind DaImTo! We will make sure that our refresh tokens are updated regularly. – kanekane Apr 11 '22 at 08:44
2

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!

bfredo123
  • 462
  • 1
  • 8
  • 20
0

By last answer...

  1. It means we can used one refresh token for 6 month. right ?
  2. And after 6 month we have to update refresh token. right ?