Question

My Google Drive-integrated web application works fine with the drive scope, but using such a broad scope is bad practice unless necessary. I would like to restrict the scope to drive.file so that I can only access files created by the application and files opened using Google Picker, but I cannot get it to work.

Files created by the application can be opened without problem. Files opened using Google Picker, however, are not accessible; attempting to download such a file results in a 404 error. When I right-click the file in Google Drive and select "View authorized apps", my application is not listed as one of the authorized apps.

The code works fine if the scope is expanded to drive.

I have written a minimal test page that should download a file selected by the user in Google Picker. The process can be started by calling auth() followed by showPicker(). The key parts of the code are as follows:

gapi.auth.authorize({
    client_id: '123456789012.apps.googleusercontent.com',
    scope: 'https://www.googleapis.com/auth/drive.file',
    immediate: false
});

...

var picker = new google.picker.PickerBuilder()
    .setAppId('123456789012')
    .addView(new google.picker.DocsView(google.picker.ViewId.DOCS_IMAGES))
    .setOAuthToken(gapi.auth.getToken().access_token)
    .setCallback(onPickerAction)
    .build();
picker.setVisible(true);

...

function onPickerAction(data) {
    if ( data.action === google.picker.Action.PICKED ) {
        var id = data.docs[0].id;
        var request = new XMLHttpRequest();
        request.open('GET', 'https://www.googleapis.com/drive/v2/files/' + id);
        request.setRequestHeader('Authorization', 'Bearer ' + gapi.auth.getToken().access_token);

        request.addEventListener('load', function() {
            var item = JSON.parse(request.responseText);
            console.log(item);
        });

        request.send();
    }
}

A related question concluded that the app ID was improperly set. That does not seem to affect me; I have tested all combinations I can think of without any luck.

Was it helpful?

Solution 2

As first suggested in a Google+ conversation, the problem can be solved as follows:

  1. Make sure that the Drive SDK is enabled in the Google developer console (the Drive API is something else, and only having that enabled is not enough).
  2. Specify an "Open URL" for your application.

OTHER TIPS

The Google+ plus conversation mentioned in OP's answer held the keys for me. There are a number of things that have to be configured correctly to get this to work:

  1. Drive API and Drive SDK are both enabled for your developer account.
  2. The appId set on the picker matches the first portion of the clientId, e.g. ('1932384883' in '1932384883-qI99fef9f9ghh9n99vvsqa9zxczx8cz8xcc.googleusercontent.com')
  3. In the Drive SDK configuration, define an Open URL. The URL doesn't have to exactly match the URL from which the picker is opened, but the origin (e.g. https://domain.com) does.
  4. In the "Client ID for web applications" section, the Open URL above must also be in the list of redirect URIs. The origin must be in the list of javascript origins.
  5. You may also have to require the user to have 'installed' your app into Google Drive, or requested the 'drive.install' scope as well as 'drive.file'

A subset of the above may work, but this is what I needed to set up in order for a simple REST request for the picked file to come back with a 200 rather than a 404.

In addition to setting the app ID, make sure the page you're serving the picker on is listed in your javascript origins in the APIs console. Both the app ID and the origin need to match for files to be authorized.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top