Java Google Docs API - User Impersonation for File Export

I’m working with the Google Docs Java API in a Google Apps environment and running into an issue. My code can successfully authenticate and impersonate a user to fetch document metadata, but when I try to actually download the file content, I get a ServiceForbiddenException.

The strange part is that the authentication seems to work fine. I can retrieve file information like the document title without any problems. But the download process fails every time.

Has anyone encountered this before? Is there a workaround using direct HTTP calls with the Protocol API instead?

public class DocumentManager {
    
    private static DocsService service = new DocsService("Document Manager");
    
    public static void main(String[] args) throws Exception {
        String domainAdmin = args[0];
        String password = args[1];
        String token = args[2];
        String targetUser = args[3];
        
        authenticateService(domainAdmin, password, token);
        
        URL feedUrl = new URL("https://docs.google.com/feeds/" + targetUser + "/private/full");
        DocumentListFeed docFeed = service.getFeed(feedUrl, DocumentListFeed.class);
        
        DocumentListEntry document = docFeed.getEntries().get(0);
        
        String docTitle = document.getTitle().getPlainText();
        System.out.println(docTitle);
        
        String docType = document.getType();
        if (docType.equals("document")) {
            String encodedUser = URLEncoder.encode(domainAdmin);
            String resId = document.getResourceId();
            String cleanId = resId.substring(resId.indexOf(':') + 1);
            
            String exportUrl = "https://docs.google.com/feeds/download/documents/Export" +
                    "?xoauth_requestor=" + encodedUser +
                    "&docId=" + cleanId +
                    "&exportFormat=doc";
            
            exportDocument(exportUrl, docTitle + ".doc");
        }
    }
    
    private static void authenticateService(String admin, String pwd, String authToken)
            throws OAuthException, AuthenticationException {
        String domainName = admin.substring(admin.indexOf('@') + 1);
        
        GoogleOAuthParameters params = new GoogleOAuthParameters();
        params.setOAuthConsumerKey(domainName);
        params.setOAuthConsumerSecret(authToken);
        params.setOAuthType(OAuthType.TWO_LEGGED_OAUTH);
        params.setScope("https://docs.google.com/feeds/ http://spreadsheets.google.com/feeds/ http://docs.googleusercontent.com/");
        
        service.useSsl();
        service.setOAuthCredentials(params, new OAuthHmacSha1Signer());
        service.setUserCredentials(admin, pwd);
    }
    
    public static void exportDocument(String url, String filename)
            throws IOException, ServiceException {
        System.out.println("Downloading from: " + url);
        
        MediaContent content = new MediaContent();
        content.setUri(url);
        MediaSource source = service.getMedia(content);
        
        InputStream input = null;
        FileOutputStream output = null;
        
        try {
            input = source.getInputStream();
            output = new FileOutputStream(filename);
            
            int data;
            while ((data = input.read()) != -1) {
                output.write(data);
            }
        } finally {
            if (input != null) input.close();
            if (output != null) {
                output.flush();
                output.close();
            }
        }
    }
}

I encountered a similar issue recently while working with the Google Docs API. Initially, I could access document metadata without any trouble, but I faced a ServiceForbiddenException during downloads. The root of the problem was indeed related to OAuth scopes. Ensure that your OAuth scopes are correctly set up; any trailing spaces or unnecessary parts can definitely cause issues.

Moreover, I noticed you have a mix of authentication methods in your service instance. Since you’re using two-legged OAuth, consider removing the user credentials to simplify the process. Lastly, it’s crucial to verify that the targetUser’s email matches the one in your Google Apps domain precisely. Good luck!

This is a classic permissions mismatch between OAuth auth and file access rights. I’ve hit this exact issue with legacy Google Apps setups. The problem’s usually in how you’re building the export URL - you’re using the domain admin in xoauth_requestor but trying to grab a different user’s document.

Switch your export URL to use targetUser instead of encodedUser (the domain admin). Your xoauth_requestor needs to match the user whose docs you’re accessing, not the admin doing the impersonation. Also check that your service account has proper delegation rights in Google Admin console for document exports, not just read access. Google handles permissions for metadata vs actual file downloads completely differently.

Check if ur domain admin has download permissions for that user’s docs. Sometimes impersonation works for reading metadata but file exports need different privileges. Try adding the target user’s email to ur xoauth_requestor param instead of the domain admin - worked for me in a similar situation.