3
votes

I'm trying to watch for changes in Google Drive, and getting 401 Exception. Searching here, i found that people have detailed messages, why they are not unauthorized though i have nothing.

Here the code i use:

public static void main(String[] args) {
    try {


        httpTransport = GoogleNetHttpTransport.newTrustedTransport();
        dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR);

        // authorization
        GoogleCredential credential = GoogleCredential.getApplicationDefault()
                .createScoped(DriveScopes.all());

        boolean refreshed = credential.refreshToken();

        // set up the global Drive instance
        drive = new Drive.Builder(httpTransport, JSON_FACTORY, credential)
                .setApplicationName(APPLICATION_NAME)
                .build();

        Channel channel = new Channel();
        channel.setId(UUID.randomUUID().toString());
        channel.setType("web_hook");
        //my ip here
        channel.setAddress("https://com.example:");

        StartPageToken pageToken = drive.changes().getStartPageToken().execute();
        System.out.println(pageToken.getStartPageToken());
        Channel changesChannel = drive.changes().watch(pageToken.getStartPageToken(), channel).execute();
        System.out.println(changesChannel.getExpiration());

        return;
    } catch (IOException e) {
        System.err.println(e.getMessage());
        e.printStackTrace();
    } catch (Throwable t) {
        t.printStackTrace();
    }
    System.exit(1);
}

More info:

  1. This is a service account. It has Owner permissions
  2. I'm using it from local computer
  3. drive.files().list() works fine
  4. drive.about().get() works fine

And the exception i'm getting:

com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:145) at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113) at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40) at com.google.api.client.googleapis.services.AbstractGoogleClientRequest$1.interceptResponse(AbstractGoogleClientRequest.java:321) at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1065) at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:419) at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352) at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469) at main.lambda.GoogleDrive2.main(MyClass.java:142)

my pom.xml dependencies:

<dependency>
        <groupId>com.google.api-client</groupId>
        <artifactId>google-api-client</artifactId>
        <version>1.20.0</version>
    </dependency>
    <dependency>
        <groupId>com.google.oauth-client</groupId>
        <artifactId>google-oauth-client</artifactId>
        <version>1.22.0</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.google.api-client/google-api-client-extensions -->
    <dependency>
        <groupId>com.google.api-client</groupId>
        <artifactId>google-api-client-extensions</artifactId>
        <version>1.6.0-beta</version>
    </dependency>
    <dependency>
        <groupId>com.google.oauth-client</groupId>
        <artifactId>google-oauth-client-jetty</artifactId>
        <version>1.22.0</version>
    </dependency>
    <dependency>
        <groupId>com.google.apis</groupId>
        <artifactId>google-api-services-drive</artifactId>
        <version>v3-rev70-1.22.0</version>
    </dependency>
1
The code you are using looks like Oauth2 and not service account to me. Please include your auth code for service account. This is analytics but it might help as a refrence developers.google.com/analytics/devguides/reporting/core/v3/…DaImTo
hi @DaImTo It's a service account. I've used this: ➜ ~ gcloud auth activate-service-account --key-file=/path/to/my/file to activate it locally, and after that with GoogleCredential.getApplicationDefault().. it takes those credentialsSaandji
Can you try something simple like a files list. I think that's a permissions issue your service account doesn't have access to watch that file.DaImTo
@DaImTo yep, I've tried already. see "more info" section. Tried files().list() and about().get() both work great.Saandji
401 means either the access token is invalid (badly formed, expired, etc), or that the access token wasn't created with the necessary scopes to authorize the operation you are attempting.pinoyyid

1 Answers

3
votes

After spending few hours and reading more carefully the documentation, I've finally found the problem.

As written in Push Notification doc (https://developers.google.com/drive/v3/web/push):

To use push notifications, you need to do three things:

  1. Register the domain of your receiving URL. ...

  2. Set up your receiving URL, or "Webhook" callback receiver.

    This is an HTTPS server that handles the API notification messages that are triggered when a resource changes.

  3. Set up a notification channel for each resource endpoint you want to watch.

    A channel specifies routing information for notification messages. As part of the channel setup, you identify the specific URL where you want to receive notifications. Whenever a channel's resource changes, the Drive API sends a notification message as a POST request to that URL.

Which means you should have a domain and you should confirm it at google, before you can use watch API.

P.S. i still think that response GoogleJsonResponseException: 401 Unauthorized is ridiculous in this case, but hope it will help other who face the same issue.