Search code examples
javagoogle-drive-apiresttemplate

Authorization for Google Drive Push Notifications for Java


I am trying to get push notifications from a resource on Google Drive to my server. I have been looking at this example:

https://developers.google.com/drive/v3/web/push

And I have tried translating that to Java into something like this:

    RestTemplate restTemplate = new RestTemplate();

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
    map.add("id", "36d00d08-000d-4723-91bc-a1a6ec302e59");
    map.add("type", "web_hook");
    map.add("address", "https://mydomain.appspot.com/rest/drive");
    HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
    ResponseEntity<String> response = restTemplate.postForEntity(uri, request, String.class);

I have previously been using Googles libs for Drive to access files. In those cases I didn't need to create the request in such a "manual" way. I have used the class GoogleAuthorizationCodeFlow with a token to authorize my requests. I'm not sure how I should do that with RestTemplate. I am guessing that I need to do something like:

headers.set("Authorization", X);

What should X be here? Is that even the right way to approach authorization?

Edit:

Here is my attempt by reading a secret. The result is HTTP 401:

 @Override
    public String startListening() throws IOException {
        final String fileId = "omitted";
        String uri = "https://www.googleapis.com/drive/v3/files/" + fileId + "/watch";
        HttpHeaders headers = getHeaders(getSecret());
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(getProperties(), headers);
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> response = restTemplate.postForEntity(uri, request, String.class);
        return response.getStatusCode() + " " + response.getBody() + " " + response.getHeaders();
    }

    private static HttpHeaders getHeaders(String theString) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("Authorization", "Bearer " + theString);
        return headers;
    }

    private static MultiValueMap<String, String> getProperties() {
        MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
        map.add("id", "some uid");
        map.add("type", "web_hook");
        map.add("address", "https://mydomain.appspot.com/rest/drive");
        return map;
    }

    private static String getSecret() throws IOException {
        InputStream in =
                ConcreteDriveListenerFactory.class.getResourceAsStream("/drive_secret.json");
        StringWriter writer = new StringWriter();
        IOUtils.copy(in, writer, "UTF-8");
        return writer.toString();
    }

Solution

  • As @DalmTo has mentioned, X is for token. With regard to sample POST request for Drive API try this code snippet from this SO thread. It also uses a POST method.

    public static void main(String argv[]) throws Exception {
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost post = new HttpPost(
                "https://www.googleapis.com/drive/v2/files");
        post.addHeader("Content-Type", "application/json");
        post.addHeader("Authorization",
                "Bearer XXXXXXXXXXXXXXXXXXXXXXXXX");
    
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("title", "Test folder");
        jsonObject
                .addProperty("mimeType", "application/vnd.google-apps.folder");
    
        post.setEntity(new StringEntity(jsonObject.toString()));
        httpClient.execute(post);
    }