googleapis / google-api-java-client-services

Generated Java code for Google APIs
Apache License 2.0
603 stars 340 forks source link

Directory API: Not Authorized to access this resource/api #4279

Open somejavadev opened 4 years ago

somejavadev commented 4 years ago

Hi,

I am trying to list users within my gSuite domain from a gke cluster using a service account. I have done the following to test the service account with the google-api-services-admin-directory api:

Within my Google Cloud Account I have enabled the Admin SDK. I then created a domain-wide service account in the project as described here https://developers.google.com/admin-sdk/directory/v1/guides/delegation, then downloaded the JSON key file and gave it authorization to the following scopes in the Admin Console:

https://www.googleapis.com/auth/admin.directory.group.member.readonly 
https://www.googleapis.com/auth/admin.directory.group.readonly 
https://www.googleapis.com/auth/admin.directory.user.readonly 
https://www.googleapis.com/auth/admin.directory.user.security 

I then setup a very basic Java application to test listing groups:

Test.java

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.directory.Directory;
import com.google.api.services.directory.DirectoryScopes;
import com.google.api.services.directory.model.Groups;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.List;

public class Test {

    private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
    private static final List<String> SCOPES = new ArrayList<>();

    private static Credential getCredentials(NetHttpTransport netHttpTransport) throws IOException {
        SCOPES.add(DirectoryScopes.ADMIN_DIRECTORY_USER_READONLY);
        SCOPES.add(DirectoryScopes.ADMIN_DIRECTORY_GROUP_READONLY);
        SCOPES.add(DirectoryScopes.ADMIN_DIRECTORY_USER_SECURITY);
        GoogleCredential credential = GoogleCredential.getApplicationDefault(netHttpTransport, JSON_FACTORY).createScoped(SCOPES);
        return credential;
    }

    public static void main(String... args) throws IOException, GeneralSecurityException {
        final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
        Directory directory = new Directory.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT)).setApplicationName("test").build();
        Directory.Groups.List list = directory.groups().list();
        list.setDomain("mydomain.com");
        Groups users = list.execute();
        users.getGroups().forEach(g -> System.out.println(g.getName()));
    }
}

pom.xml

    <dependencies>
        <dependency>
            <groupId>com.google.apis</groupId>
            <artifactId>google-api-services-admin-directory</artifactId>
            <version>directory_v1-rev20191003-1.30.8</version>
        </dependency>
        <dependency>
            <groupId>com.google.api-client</groupId>
            <artifactId>google-api-client</artifactId>
            <version>1.30.8</version>
        </dependency>
    </dependencies>

Before running the java file I set the GOOGLE_APPLICATION_CREDENTIALS environment variable to point to my json service account file.

When running this no matter whether I am trying to access users or groups I keep getting the following error message from the API:

{
  "code" : 403,
  "errors" : [ {
    "domain" : "global",
    "message" : "Not Authorized to access this resource/api",
    "reason" : "forbidden"
  } ],
  "message" : "Not Authorized to access this resource/api"
}

Stack trace:

at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:150)
    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:444)
    at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1108)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:542)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:475)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:592)

I believe this issue might be related to the issue mentioned in the google-api-nodejs-client project:
https://github.com/googleapis/google-api-nodejs-client/issues/1884

Adding the scope https://www.googleapis.com/auth/admin.directory.user.security does not resolve the problem.

Regards

melamber commented 4 years ago

The same for me. I created service account with full access. And added all necessary scopes.

https://www.googleapis.com/auth/admin.directory.user
https://www.googleapis.com/auth/admin.directory.user.security
and etc.

But can't get any user. Get this error every time Directory API: Not Authorized to access this resource/api

portlek commented 6 days ago

I've solved this problem by setting the serviceAccountUser to my admin email address to impersonate it.

val googleServiceAccountKey =
  javaClass.classLoader.getResourceAsStream("google_service_account_key.json")!!
val credential =
  GoogleCredential.fromStream(googleServiceAccountKey)
    .createScoped(
      listOf(
        DirectoryScopes.ADMIN_DIRECTORY_USER,
        DirectoryScopes.CLOUD_PLATFORM
      )
    )
FieldUtils.writeDeclaredField(credential, "serviceAccountUser", "ADMIN_EMAIL_ADDRSES", true)