Fraser
Fraser

Reputation: 1010

Oauth2 timeout with google API

I'm using Oauth2 for authentication on Google Calendar API based based on the introductory quick start guide

I'm now running this on a web server and have set the callback port to 9999, which I have also entered in the GCP console.

I get the link in the log file and I am able to authenticate on the server and the application works fine. However, this seems timeout after around 20 mins and when I access the site the log file then gives me another URL to authenticate against. I am creating a calendar widget so once this is live I obviously do not want this to expire and I just want to set this up once.

The StoredCredential file is being created correctly on the server. I am running tomcat 7 so this file is user /usr/share/tomcat7/.credentials/

The app works fine when accessed from different IP addresses before it appears to 'timeout'

The code I am using for authenticating is below. According to the docs, the creation of the GoogleAuthorizationCodeFlow object with the DataStoreFactory for the FileCredentials should pick up that we have already authenticated.

The docs also state that "An access token typically has an expiration date of 1 hour, after which you will get an error if you try to use it. GoogleCredential takes care of automatically 'refreshing' the token, which simply means getting a new access token."

I have also tried setting the timeout manually on the credential object. Google docs state that setExpiresInSeconds() "Sets the lifetime in seconds of the access token (for example 3600 for an hour) or null for none." I have tried this both null, LONG.MAX, and 1 year. All of these result in the message "Please open the following address in your browser:" being shown in the logs after a period of about 45 minutes. Using the getExpiresInSeconds() method I can confirm that the timeout was set to my expected value.

The documentation also states that access_type should be set to offline in the GoogleAuthorizationCodeFlow, which I have shown I am doing below.

    public static Credential authorize() throws IOException {
    InputStream in = GoogleCalendarService.class.getClassLoader().getResourceAsStream("/client_secret.json");
    GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));


    GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
            .setDataStoreFactory(new FileDataStoreFactory(DATA_STORE_DIR))
            .setAccessType("offline")
            .build();


    Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver.Builder().setHost(REDIRECT_URI).setPort(9999).build()).authorize("user");

    return credential;
}

Upvotes: 1

Views: 5986

Answers (1)

Fraser
Fraser

Reputation: 1010

For anyone who comes across this, my refresh token was actually Null. I revoked my token and had to set the approval prompt to be 'force' as below:

        GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
            .setDataStoreFactory(new FileDataStoreFactory(DATA_STORE_DIR))
            .setAccessType("offline")
            .setApprovalPrompt("force")
            .build();

After creating the Credential using:

        Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver.Builder().setHost(REDIRECT_URI).setPort(9999).build()).authorize("user");

I was then able to do:

credential.getRefreshToken()

Which showed that the token was non-null. The expiration time as default seems to be 3600 seconds and when the token has <60s left then the API automatically refreshes this. The app has now been running for 24 hours and the token has been refreshed successfully

Upvotes: 2

Related Questions