0
votes

I used Service Account key with scope (https://www.googleapis.com/auth/admin.directory.user.readonly) to access Google Directory API Users.

With the same setup as below, I can access Users List API (link).

But when trying to make request to Users Watch API (link), Status 403 returned.

These 2 APIs required the same scope user.readonly that my SA key has.

My domain has already been verified and added into Domain verification screen on GCP Console.

val httpTransport = GoogleNetHttpTransport.newTrustedTransport()
val jsonFactory = JacksonFactory()
val inputStream = HealthController::class.java.getResourceAsStream("/credentials.json")
        ?: throw FileNotFoundException("/credentials.json")
val credential = GoogleCredential.fromStream(inputStream, httpTransport, jsonFactory)
        .toBuilder()
        .setServiceAccountScopes(listOf(DirectoryScopes.ADMIN_DIRECTORY_USER_READONLY))
        .setServiceAccountUser("[email protected]")
        .build()
service = Directory.Builder(httpTransport, jsonFactory, credential)
        .setApplicationName("Some Name")
        .build()

val channel = Channel()
channel.address = "https://example.com/webhook/v1/google/users"
channel.expiration = Instant.now().toEpochMilli() + 6 * 60 * 60 * 1000
channel.id = "webhook001"
channel.token = "abcxyz"
channel.type = "web_hook"
channel.payload = false

val result = service.users().watch(channel)
        .setDomain("example.com")
        .setViewType("domain_public")
        .execute()

I logged the issue to Google issue tracker: https://issuetracker.google.com/issues/171300784

1
Have you tried with https://www.googleapis.com/auth/admin.directory.user scope in your token? - Jose Vasquez
@JoseVasquez No I haven't, should I try it? - NDC00629
Which JVM version is your Kotlin compiling for execution? This might be affecting your code since Google doesn't directly support Kotlin for Directory API, take a look to your version and confirm this is one of the following here. - Jose Vasquez
I used kotlin-maven-plugin with jvmTarget to be 1.8 - NDC00629
but JVM version on my local machine is 11 - NDC00629

1 Answers

0
votes

Google Directory API doesn't support Kotlin directly it depends on the target compilation

Prerequisites

Make sure that you have Delegating domain-wide authority to the service account activated.

Workaround

As an approach in JAVA (you can transpile this code to Kotlin if needed) first of all use the watch method of the official documentation as well as the Channel class, I'll put the package dependency in a comment:

JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
NetHttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();

// com.google.auth.oauth2.ServiceAccountCredentials
GoogleCredentials credentials = ServiceAccountCredentials.fromStream(new FileInputStream(SERVICE_ACCOUNT_CREDENTIALS_FILE_PATH))
            .createScoped(SCOPES)
            .createDelegated("[email protected]");

// com.google.api.client.http
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(credentials);

// com.google.api.services.admin.directory.Directory.Builder
Directory service = new Directory.Builder(httpTransport, jsonFactory, requestInitializer)
                .setApplicationName(APPLICATION_NAME)
                .build();

// com.google.api.services.admin.directory.model.Channel
Channel channel = new Channel();
channel.setAddress("https://example.com/webhook/v1/google/users");
channel.setExpiration(Instant.now().toEpochMilli() + 6 * 60 * 60 * 1000);
channel.setId("webhook001");
channel.setToken("abcxyz");
channel.setType("web_hook");
channel.setPayload(false);

System.out.println(service.users().watch(channel)
                .setDomain("example.com")
                .setViewType("domain_public")
                .execute());

Reference

Javadoc Directory API