Not receiving Google OAuth refresh token

The refresh_token is only provided on the first authorization from the user. Subsequent authorizations, such as the kind you make while testing an OAuth2 integration, will not return the refresh_token again. :)

  1. Go to the page showing Apps with access to your account: https://myaccount.google.com/u/0/permissions.
  2. Under the Third-party apps menu, choose your app.
  3. Click Remove access and then click Ok to confirm
  4. The next OAuth2 request you make will return a refresh_token (providing that it also includes the 'access_type=offline' query parameter.

Alternatively, you can add the query parameters prompt=consent&access_type=offline to the OAuth redirect (see Google's OAuth 2.0 for Web Server Applications page).

This will prompt the user to authorize the application again and will always return a refresh_token.


In order to get the refresh token you have to add both approval_prompt=force and access_type="offline" If you are using the java client provided by Google it will look like this:

GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
            HTTP_TRANSPORT, JSON_FACTORY, getClientSecrets(), scopes)
            .build();

AuthorizationCodeRequestUrl authorizationUrl =
            flow.newAuthorizationUrl().setRedirectUri(callBackUrl)
                    .setApprovalPrompt("force")
                    .setAccessType("offline");

I'd like to add a bit more info on this subject for those frustrated souls who encounter this issue. The key to getting a refresh token for an offline app is to make sure you are presenting the consent screen. The refresh_token is only returned immediately after a user grants authorization by clicking "Allow".

enter image description here

The issue came up for me (and I suspect many others) after I'd been doing some testing in a development environment and therefore already authorized my application on a given account. I then moved to production and attempted to authenticate again using an account which was already authorized. In this case, the consent screen will not come up again and the api will not return a new refresh token. To make this work, you must force the consent screen to appear again by either:

prompt=consent

or

approval_prompt=force

Either one will work but you should not use both. As of 2021, I'd recommend using prompt=consent since it replaces the older parameter approval_prompt and in some api versions, the latter was actually broken (https://github.com/googleapis/oauth2client/issues/453). Also, prompt is a space delimited list so you can set it as prompt=select_account%20consent if you want both.

Of course you also need:

access_type=offline

Additional reading:

  • Docs: https://developers.google.com/identity/protocols/oauth2/web-server#request-parameter-prompt
  • Docs: https://developers.google.com/identity/protocols/oauth2/openid-connect#re-consent
  • Discussion about this issue: https://github.com/googleapis/google-api-python-client/issues/213