Reputation: 646
I am authenticating using domain-wide delegation.
I am getting back the google drive service that looks like this: com.google.api.services.drive.Drive@6ebd27b9
This is the link to the file I'm trying to retrieve: https://docs.google.com/a/rmi.org/document/d/1JRS8SLzaAD2U4cG-GbDMbVN25Dp6f_uUYyl6ERMPAno/edit
I am passing in this value as the file ID: 1JRS8SLzaAD2U4cG-GbDMbVN25Dp6f_uUYyl6ERMPAno
.
When the code gets to this line: File file = service.files().get(fileId).execute();
I get this error:
An error occured: com.google.api.client.googleapis.json.GoogleJsonResponseException: 404 OK
{
"code" : 404,
"errors" : [ {
"domain" : "global",
"message" : "File not found: 1JRS8SLzaAD2U4cG-GbDMbVN25Dp6f_uUYyl6ERMPAno",
"reason" : "notFound"
} ],
When I try to find the file in question using the tool at the bottom of this page, if I turn on Oauth 2.0, I get back a 200 response code and information about the file in question.
I've looked at many similar questions on here including this question, but I can't see anything wrong in the way that I've set up my permissions:
Here is where I get the drive service:
public static Drive getDriveService() throws GeneralSecurityException,
IOException, URISyntaxException {
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
//.setServiceAccountScopes(DriveScopes.DRIVE)
.setServiceAccountScopes(SCOPE)
.setServiceAccountPrivateKeyFromP12File(
new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))
.build();
Drive service = new Drive.Builder(httpTransport, jsonFactory, null)
.setHttpRequestInitializer(credential).build();
return service;
I have these variables defined as follows:
/** Email of the Service Account */
private static final String SERVICE_ACCOUNT_EMAIL = "[email protected]";
/** Path to the Service Account's Private Key file */
private static final String SERVICE_ACCOUNT_PKCS12_FILE_PATH = "/actualpathhere/HowToListing/war/resources/actualpd12filename.p12";
private static final List<String> SCOPE = Arrays.asList("https://www.googleapis.com/auth/drive.readonly");
Here is where I am trying to get the file metadata:
private static List<File> retrieveAllFiles(Drive service) throws IOException {
List<File> result = null;
try {
String fileId = "1JRS8SLzaAD2U4cG-GbDMbVN25Dp6f_uUYyl6ERMPAno";
File file = service.files().get(fileId).execute();
System.out.println("Title: " + file.getTitle());
System.out.println("Description: " + file.getDescription());
System.out.println("MIME type: " + file.getMimeType());
} catch (IOException e) {
System.out.println("An error occured: " + e);
}
return result;
}
Can anyone give me any hints as to what might be going on?
Upvotes: 2
Views: 2520
Reputation:
EDITED
All the security was a red herring, it turns out. The key thing missing was a valid user's email address. First, functioning code:
import java.io.IOException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.File;
public class DriveCommandLine {
private static String SERVICE_ACCOUNT_EMAIL = "[email protected]";
private static final String SERVICE_ACCOUNT_PKCS12_FILE_NAME = "a_file_name.p12";
private static String SERVICE_ACCOUNT_PKCS12_FILE_PATH;
public static void main(String[] args) throws IOException {
try {
//I did this stuff for the p12 file b/c I was having trouble doing this all from command line (first time)
URL location = DriveCommandLine.class.getProtectionDomain().getCodeSource().getLocation();
SERVICE_ACCOUNT_PKCS12_FILE_PATH = location.getFile() + SERVICE_ACCOUNT_PKCS12_FILE_NAME;
Drive drive = DriveCommandLine.getDriveService("[email protected]");
DriveCommandLine.printFile(drive, "THE_ID_OF_THE_FILE");
} catch (GeneralSecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//From https://developers.google.com/drive/web/delegation#instantiate_a_drive_service_object
/**
* Build and returns a Drive service object authorized with the service accounts
* that act on behalf of the given user.
*
* @param userEmail The email of the user.
* @return Drive service object that is ready to make requests.
*/
public static Drive getDriveService(String userEmail) throws GeneralSecurityException, IOException {
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
GoogleCredential credential = new GoogleCredential.Builder().setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(Arrays.asList(new String[] {DriveScopes.DRIVE}))
.setServiceAccountUser(userEmail)
.setServiceAccountPrivateKeyFromP12File(new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))
.build();
Drive service = new Drive.Builder(httpTransport, jsonFactory, null).setHttpRequestInitializer(credential).build();
return service;
}
// From the code box at https://developers.google.com/drive/v2/reference/files/get
/**
* Print a file's metadata.
*
* @param service Drive API service instance.
* @param fileId ID of the file to print metadata for.
*/
private static void printFile(Drive service, String fileId) {
try {
File file = service.files().get(fileId).execute();
System.out.println("Title: " + file.getTitle());
System.out.println("Description: " + file.getDescription());
System.out.println("MIME type: " + file.getMimeType());
} catch (IOException e) {
System.out.println("An error occured: " + e);
}
}
}
The missing line was setServiceAccountUser(userEmail)
which is for a valid system user.
With a valid user, I got the file details.
With an invalid user, I got
An error occured: com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
{
"error" : "invalid_grant",
"error_description" : "Not a valid email."
}
And, with a user who did not have access or when the line was not set, I got
An error occured: com.google.api.client.googleapis.json.GoogleJsonResponseException: 404 Not Found
{
"code" : 404,
"errors" : [ {
"domain" : "global",
"message" : "File not found: THE_FILE_ID",
"reason" : "notFound"
} ],
"message" : "File not found: THE_FILE_ID"
}
NOTE: Just be sure you follow each little step at Perform Google Apps Domain-Wide Delegation of Authority since that is where I ended up getting the solution and all the right keys (didn't need as many as I initially thought!)
Upvotes: 1