How to get offline token and refresh token and auto-refresh access to Google API
Solution 1
One thing you should be careful about: a refresh token is returned (in addition to the access token) only when the user gives consent explicitly for the requested scopes. Basically, when the approval page is shown. All subsequent flows will only return an access token.
Now, in order to test your application and make sure you receive the refresh token the first time around, you could use the approval_prompt=force parameter (builder.setApprovalPrompt("force")
) to make sure the approval page is shown in the flow and you obtain explicit consent from the user. After you sort out any issues and make sure the refresh tokens are stored properly, you can remove that flag (the default is auto
)
More information is also available in the offline access section in the developer guide.
Solution 2
To get the refresh token you have to set both accessType
= "offline" and approvalPrompt
= "force".
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
HTTP_TRANSPORT,
JSON_FACTORY,
CLIENT_ID,
CLIENT_SECRET,
SCOPE)
.setAccessType("offline")
.setApprovalPrompt("force")
.build();
![Andrew Mackenzie](https://i.stack.imgur.com/Wn0FW.jpg?s=256&g=1)
Andrew Mackenzie
Currently: VP Engineering at 3scale.net Associate Professor at Universitat Pompeu Fabra in Barcelona. President of Autelic Association. Previously: Principle Software Engineer at Tuenti. CTO at BCNTouch. Extensive experience at HP in Engineering and RD management. See http://www.linked.com/in/andrewdmackenzie
Updated on March 04, 2020Comments
-
Andrew Mackenzie over 4 years
I'm developing an app that accesses Google APIs (starting with Calendar API) using OAuth2 and the google client libraries for that (is on Appengine and GWT BTW).
I have implemented my
OAuth2Call
back servlet, extending the GoogleAbstractAppEngineAuthorizationCodeCallbackServlet
.I have it working, I get access and can look at calendars etc, but have two problems:
1) I do not get a refresh token, despite explicitly requesting offline access:
public static GoogleAuthorizationCodeFlow newFlow( String scope ) throws IOException { GoogleAuthorizationCodeFlow.Builder builder = new GoogleAuthorizationCodeFlow.Builder( HTTP_TRANSPORT, JSON_FACTORY, getClientSecrets(), Collections.singleton( scope ) ); builder.setCredentialStore( new AppEngineCredentialStore() ).setAccessType("offline"); return builder.build(); }
2) I cannot see how to set the automatic refresh functionality. These pages describe the methods:
But I can't see where to add the refresh listener. There is no such method in the
GoogleAuthorizationCodeFlow.Builder
class, unlike theCredential.Builder
classEDIT After debugging the code more, when the credential comes back (in the
onSuccess()
method) it seems to have aRefreshListener
set already.....so maybe that's their by default, and my only problem is I'm not getting arefresh_token
, despite asking for it.Maybe need to review settings in the Google API Console also?
-
Andrew Mackenzie over 11 yearsThanks for the comment, I'll check along these lines. At the moment, I do an explicit revoke of the token, and then request it again and I always go through the explicit accept screen for the user - but still don't get a refresh_token.
-
Andrew Mackenzie over 11 yearsvlatko, I was doing everything you said except the prompt force, and that seems to have fixed it! So, your answer was much appreciated! Is this a bug, or just a glaring omission from the (too extensive...) documentation?
-
Andrew Mackenzie over 11 yearsThanks Sunny. But the problem was that on the first authorization I was getting the AccessToken, but NOT the RefreshToken, despite asking for it by setting the AccessType to "offline". If you use the Google classes (once you have a RefreshToken) they they will store it and use it to automatically get a new AccessToken when it expires, all transparently to you.
-
theblackips over 10 yearsOk, thank you for this! The .setApprovalPrompt(..) must be a relatively new requirement. I had my code working about a month or two ago without this option and it was giving me refresh tokens. All of a sudden it had stopped working and I was left to wonder why.