G Bisconcini
G Bisconcini

Reputation: 764

Perform Google Apps Domain-Wide Delegation of Authority

I am trying to do Domain-Wide Delegation of Authority between my Application Service Account and my organization (on admin.google.com). I followed this guide, about three times, and I cannot know where I miss, it doesn't work. My application is not able to do personification of an user inside the organization.

The response of the API says that:

 Exception in thread "main" com.google.api.client.auth.oauth2.TokenResponseException: 403 Forbidden
{
  "error" : "access_denied",
  "error_description" : "Requested client not authorized."
}
    at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:105)
    at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:287)
    at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:307)
    at com.google.api.client.googleapis.auth.oauth2.GoogleCredential.executeRefreshToken(GoogleCredential.java:268)
    at com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:489)
    at com.google.api.client.auth.oauth2.Credential.intercept(Credential.java:217)
    at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:859)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:410)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460)
    at StorageSample.main(StorageSample.java:156)

Here is my unique code, for test:

 String emailAddress = "[email protected]";
            JsonFactory JSON_FACTORY =          JacksonFactory.getDefaultInstance();
            HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();

            //scopes
            List scopes = new ArrayList();
            scopes.add(DriveScopes.DRIVE);
            scopes.add(DriveScopes.DRIVE_APPDATA);
            scopes.add(DriveScopes.DRIVE_APPS_READONLY);
            scopes.add(DriveScopes.DRIVE_FILE);

            GoogleCredential credential = new GoogleCredential.Builder()
            .setTransport(httpTransport)
            .setJsonFactory(JSON_FACTORY)
            .setServiceAccountId(emailAddress)
            .setServiceAccountPrivateKeyFromP12File(new File("valid_path_to_secrets.p12"))
            .setServiceAccountScopes(scopes)
            .setServiceAccountUser("[email protected]") // HERE THE USER I WANT TO PERSONIFICATE
            .build();

            Drive drive = new Drive.Builder(httpTransport, JSON_FACTORY, credential).setApplicationName("Test").build();

            String myName = drive.about().get().execute().getName();
            com.google.api.services.drive.Drive.Files.List files = drive.files().list();
            FileList fileList = files.execute();
            List<com.google.api.services.drive.model.File> xFiles = fileList.getItems();

            System.out.println("here");
            for (com.google.api.services.drive.model.File f : xFiles){
                System.out.println("DEBUG "+f.getOriginalFilename());
                System.out.println(f.getDownloadUrl());
                System.out.println(f.getAlternateLink());
                System.out.println(f.getOwnerNames().get(0));
                System.out.println(f.getFileSize());
            }
        }

        }

If I comment the line marked (setServiceAccountUser("[email protected]")), the application works, but I want to do the personification of this user test. That is the intention of this guide provided, to grant access to all users inside mydomain.com.br.

In the Delegate domain-wide authority to your service account section of the guide of Google, as mentioned, I followed all the steps, with attention on step number 6: To add the scope on admin.google.com under the Security section. (google admin configuration for the app) Here ir my google admin configuration for the app

Upvotes: 1

Views: 531

Answers (1)

David
David

Reputation: 5519

You have authorized the client id for 1 Drive scope :

https://www.googleapis.com/auth/drive

This scope is stored in Java under the constant DriveScopes.DRIVE.

But when you create the credential in your code you ask for 4 scopes :

scopes.add(DriveScopes.DRIVE);
scopes.add(DriveScopes.DRIVE_APPDATA);
scopes.add(DriveScopes.DRIVE_APPS_READONLY);
scopes.add(DriveScopes.DRIVE_FILE);

I agree that since DriveScopes.DRIVE is a scope that includes the other scopes in Drive, it would seem normal that getting an authorization for DriveScopes.DRIVE would imply that you get the authorization for all the other Drive scopes.

However it is not the case, and you must specify in the Security section all the scopes that you plan to use. In your case that would be :

https://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/drive.appdata
https://www.googleapis.com/auth/drive.apps.readonly
https://www.googleapis.com/auth/drive.file

But since all those scopes are already included in https://www.googleapis.com/auth/drive you can also simply remove the other scopes from the Java code. That's what I would do :

...
List scopes = new ArrayList();
scopes.add(DriveScopes.DRIVE);
//No other scope

GoogleCredential credential = new GoogleCredential.Builder()
...

Upvotes: 3

Related Questions