title: Google Sheets java sdk oAuth unauthorized after some hours (spring boot)
body: <p>I successfully created a spring boot Serviceclass in order to write on google sheets, following the <a href="https://developers.google.com/sheets/api/quickstart/java" rel="nofollow noreferrer">Java Quistart Tutorial for Sheets API</a></p>
  
  <p>My problem is that the authorization is not renewing, so after the first successful authentication via browser, after some hours I get 401 unauthorized.
  How can I automatically renew the token without re-issuing the browser login?</p>
  
  <p>Below the code, thanks in advance</p>
  
  <pre><code>import com.google.api.client.auth.oauth2.Credential;
  import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
  import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
  import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver.Builder;
  import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
  import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
  import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
  import com.google.api.client.http.HttpTransport;
  import com.google.api.client.json.JsonFactory;
  import com.google.api.client.json.jackson2.JacksonFactory;
  import com.google.api.client.util.store.FileDataStoreFactory;
  import com.google.api.services.sheets.v4.Sheets;
  import com.google.api.services.sheets.v4.SheetsScopes;
  import com.google.api.services.sheets.v4.model.AppendValuesResponse;
  import com.google.api.services.sheets.v4.model.ValueRange;
  
  @Service
  public class GoogleSheetsServiceImpl implements GoogleSheetsService {
  
      private static final Log LOGGER = LogFactory.getLog(GoogleSheetsServiceImpl.class);
  
      /** Application name. */
      @Value("${google-sheets.application-name}")
      private String applicationName;
  
      /** Directory to store user credentials for this application. */
      private static final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("user.home"),
              ".credentials/sheets.googleapis.com-orders");
  
      /** Global instance of the {@link FileDataStoreFactory}. */
      private FileDataStoreFactory dataStoreFactory;
  
      /** Global instance of the JSON factory. */
      private JsonFactory jsonFactory;
  
      /** Global instance of the HTTP transport. */
      private HttpTransport httpTransport;
  
      /**
       * Global instance of the scopes required by this quickstart.
       *
       * If modifying these scopes, delete your previously saved credentials at
       * ~/.credentials/sheets.googleapis.com-java-quickstart
       */
      private List&lt;String&gt; scopes;
  
      /** Sheet service. */
      private Sheets sheetsService;
  
      public GoogleSheetsServiceImpl() throws Throwable {
          // init
          try {
              this.jsonFactory = JacksonFactory.getDefaultInstance();
              this.scopes = Arrays.asList(SheetsScopes.SPREADSHEETS);
              this.httpTransport = GoogleNetHttpTransport.newTrustedTransport();
              this.dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR);
          } catch (Throwable t) {
              LOGGER.error("Error on init Google Sheets Service: " + t.getMessage());
              throw t;
          }
  
          // get sheet service
          Credential credential = this.authorize();
          this.sheetsService = new Sheets.Builder(this.httpTransport, this.jsonFactory, credential)
                  .setApplicationName(this.applicationName).build();
      }
  
      public void appendValueRangeToGoogleSheet(String spreadsheetId, String range, ValueRange valueRange)
              throws IOException {
  
          // append line
          Sheets.Spreadsheets.Values.Append request = sheetsService.spreadsheets().values()
                  .append(spreadsheetId, range, valueRange).setValueInputOption("RAW");
          AppendValuesResponse response = request.execute();
      }
  
      /**
       * Creates an authorized Credential object.
       * 
       * @return an authorized Credential object.
       * @throws IOException
       */
      private Credential authorize() throws IOException {
          // Load client secrets.
          InputStream in = GoogleSheetsServiceImpl.class.getResourceAsStream("/google_sheets/client_secret.json");
          GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(this.jsonFactory, new InputStreamReader(in));
  
          // Build flow and trigger user authorization request.
          GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(this.httpTransport, this.jsonFactory,
                  clientSecrets, this.scopes).setDataStoreFactory(this.dataStoreFactory).setAccessType("online").build();
          LocalServerReceiver.Builder localServerReceiverBuilder = new Builder();
          localServerReceiverBuilder.setHost("localhost");
          localServerReceiverBuilder.setPort(46228);
          Credential credential = new AuthorizationCodeInstalledApp(flow, localServerReceiverBuilder.build())
                  .authorize("user");
          LOGGER.info("Credentials saved to " + DATA_STORE_DIR.getAbsolutePath());
          return credential;
      }
  
  }
  </code></pre>
  
  <p>Edit:</p>
  
  <p>Solved modifying the build of GoogleAuthorizationCodeFlow object as follow:</p>
  
  <pre><code>GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(this.httpTransport, this.jsonFactory,
              clientSecrets, this.scopes).setDataStoreFactory(this.dataStoreFactory).setAccessType("offline")
                      .setApprovalPrompt("force")
                      .addRefreshListener(
                              new DataStoreCredentialRefreshListener(credentialUserId, this.dataStoreFactory))
                      .build();
  </code></pre>