javahttpoauthgoogle-oauthscribe

Getting access token from refresh token failing with invalid_grant error, and Bad Request OR Token has been expired or revoked as error description


Using Java OAuth2 client library: scribe 1.2.0 (https://github.com/scribejava/scribejava)

I am able to get refresh token from the authorization code (i.e; by making POST call to https://accounts.google.com/o/oauth2/token with client_id, client_secret, code, scope, grant_type (authorization_code), redirect_uri parameters). And I have persisted the refresh token in DB. And we support drive and calendar scopes => so, I do store two refresh token per user (email)

And then clients will be invoking API to get access token (then I am making POST call to https://accounts.google.com/o/oauth2/token with refresh_token, grant_type (refresh_token), client_id and client_secret). And the call is successful. i.e; happy normal path works.

But eventually getting new access token from refresh token is failing with invalid_grant error code (with Bad Request OR Token has been expired or revoked as errors) (like in 2 days or 3 days etc)

Please do note that the refresh token is not revoked or invalidated explicitly by user or code. Password is not changed. Code is not changed. Client ID and secrets didn't change. I am kind of lost.

Questions

  1. Since refresh token supposed to be a long lasting token, why my application is not able to get new access token from refresh token? Its just failing in like in 2 to 3 days - and its happening regularly in stage and production environments.

  2. Is storing two refresh tokens based on scope (drive and calendar) - per user (email) problem (i.e; as soon as second refresh token is issued the previous refresh token expire)? [Shouldn't be the case - I do know there are limitations per user and client, per user for all clients. But, 2 is too low to reach that limit.]

Answer Finally was able to resolve it, please see the answer below comment(s) - its related to having two refresh tokens of same email for different scopes, and invalidating one of them.

Getting access token from Refresh token - PostMan

Getting access token from Refresh token - PostMan

Getting refresh token from authorization code - PostMan

Getting refresh token from authorization code - PostMan

Relevent questions: Google token refresh returns "Token has been expired or revoked." Since couple of days Refresh token has been automatically expired


Solution

  • Basically, if your app has multiple refresh tokens for the same user (Gmail) with different scopes, invalidating one of them will invalidate all the tokens.

    that turned out to be the issue as we maintain different refresh tokens based on scopes (say drive, calendar, contacts etc)