Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

When using service account impersonation, when calling export on Google Docs using v3 API, viewedByMeTime timestamp is updated

Open
#3,160 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
25/100
Issue type
Bug
Clarity
Needs clarification
Activity status
Stale
Tech stack
java
Domain
api

Research direction

Start with the Java example's drive.files().export(fileId, "application/vnd.google-apps.document") call and review the linked Google Drive OAuth and download documentation. Reproduce the export while impersonating a user and verify whether viewedByMeTime changes. Done would require an identified supported way to export the document without updating that timestamp, or a documented limitation if the behavior is controlled by the Drive API.

Written by the indexing model from the issue text.

Description

priority: p4 type: feature request

I am using a service account to access google doc files of users in my enterprise google account.

See:

https://developers.google.com/drive/api/v3/about-auth#OAuth2Authorizing

So far so good.

Then, I need to download contents of Google Docs.

When calling Google Drive API to download the contents of a Google Doc, the documentation says to run the following:

https://developers.google.com/drive/api/v3/manage-downloads

Here is an example of my java code line that does this:

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.SecurityUtils;
import com.google.api.services.drive.Drive;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.List;

public class FetchGoogleDocContentsWithServiceAccount {
  static int readTimeout = 60000;
  static int connectTimeout = 60000;
  static String serviceAccountId = "";
  static String serviceAccountEmail = "";
  static String serviceAccountPrivateKeyFile = "";
  static String serviceAccountPrivateKeyFilePassword = "";
  static String fileId = "";
  static JacksonFactory jacksonFactory = new JacksonFactory();
  static NetHttpTransport httpTransport = new NetHttpTransport();
  static List<String> googleScopeList = Arrays.asList("https://www.googleapis.com/auth/drive.readonly",
      "https://www.googleapis.com/auth/admin.directory.group.readonly",
      "https://www.googleapis.com/auth/admin.directory.user.alias.readonly",
      "https://www.googleapis.com/auth/admin.directory.group", "https://www.googleapis.com/auth/admin.directory.user",
      "https://www.googleapis.com/auth/drive");

  public static void main(String[] args) throws Exception {
    Drive drive = (new Drive.Builder(httpTransport,
        jacksonFactory,
        getRequestInitializer(getGoogleCredentials())))
        .setApplicationName("Sample app").build();

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    drive.files().export(fileId, "application/vnd.google-apps.document")
        .executeMediaAndDownloadTo(baos);
    
    System.out.println(baos.toString("UTF-8"));
  }

  public static HttpRequestInitializer getRequestInitializer(final GoogleCredential requestInitializer) {
    return httpRequest -> {
      requestInitializer.initialize(httpRequest);
      httpRequest.setConnectTimeout(readTimeout);
      httpRequest.setReadTimeout(connectTimeout);
    };
  }

  public static GoogleCredential getGoogleCredentials() {
    GoogleCredential credential;

    try {
      GoogleCredential.Builder b = new GoogleCredential.Builder().setTransport(httpTransport)
          .setJsonFactory(jacksonFactory).setServiceAccountId(serviceAccountId)
          .setServiceAccountPrivateKey(SecurityUtils.loadPrivateKeyFromKeyStore(SecurityUtils.getPkcs12KeyStore(),
              new FileInputStream(new File(serviceAccountPrivateKeyFile)), serviceAccountPrivateKeyFilePassword,
              "privatekey", serviceAccountPrivateKeyFilePassword))
          .setServiceAccountScopes(googleScopeList);
      if (serviceAccountEmail != null) {
        b = b.setServiceAccountUser(serviceAccountEmail);
      }
      credential = b.build();
    } catch (IOException | GeneralSecurityException e1) {
      throw new RuntimeException("Could not build client secrets", e1);
    }
    return credential;
  }
}

When I have performed this operation, we are seeing that the viewedByMeTime field is actually being updated as the impersonated user.

This is not good, because now people think someone might have stolen access to their account. They are going to open tickets with the security team.

There needs to be a way to download the contents of a Google Doc file while not updating this timestamp.

Dominant language
Java
Stars
725
Forks
394
Avg merge
45m
Merged PRs (30d)
240

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from googleapis/google-api-java-client-services

All issues in googleapis/google-api-java-client-services

Similar issues

More Java issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.