Tuesday, December 3, 2013

Google Drive API - How to work with the domain-wide service account

I was trying to use the service account of my app to access to all documents of all users in my domain following this instruction:

https://developers.google.com/drive/delegation


But it didn't work.


This afternoon, my college showed me the old interface of the Google API Console which is different from the above one. So, I tried to create a service account using this page:

https://code.google.com/apis/console/b/0/?noredirect


The old interface allows me to create a service account which results in these following information:

+ A private key file (to download right after I created the service account)
+ Client ID
+ Email adress



Next, I will add the above Client ID to the Admin Console of my domain admin interface, and assign google drive api access for my app's service account with scope:

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


After that, I can use the service account (private key and email address) to access to all the documents of all users in my domain.

import httplib2

from apiclient.discovery import build
from oauth2client.client import SignedJwtAssertionCredentials


# Copy your credentials from the console
CLIENT_ID = '<my_client_id>.apps.googleusercontent.com'

"""Email of the Service Account"""
SERVICE_ACCOUNT_EMAIL = '<my_service_account_email>@developer.gserviceaccount.com'

"""Path to the Service Account's Private Key file"""
SERVICE_ACCOUNT_PKCS12_FILE = '<my private key>-privatekey.p12'

# Check https://developers.google.com/drive/scopes for all available scopes
OAUTH_SCOPE = 'https://www.googleapis.com/auth/drive'



# domain-wide
def create_drive_service(service_account_pkcs12_file, service_account_email, scope, user_email):
    """Build and returns a Drive service object authorized with the service accounts
        that act on behalf of the given user.

    Args:
        user_email: The email of the user.
    Returns:
        Drive service object.
    """
    f = file(service_account_pkcs12_file, 'rb')
    key = f.read()
    f.close()

    credentials = SignedJwtAssertionCredentials(service_account_email, key,
                            scope=scope, sub=user_email)
    http = httplib2.Http()
    http = credentials.authorize(http)

    return build('drive', 'v2', http=http)



def retrieve_all(service):
    """Retrieve a list of File resources.

    Args:
    service: Drive API service instance.
    Returns:
    List of File resources.
    """

    result = []
    page_token = None
    while True:
        try:
            param = {}
            if page_token:
                param['pageToken'] = page_token
            files = service.files().list(**param).execute()

            result.extend(files['items'])
            page_token = files.get('nextPageToken')
            if not page_token:
                break
        except errors.HttpError, error:
            print 'An error occurred: %s' % error
            break

    return result



if __name__ == "__main__":

    user_email = 'trinh@mydomain.com'
    service = create_drive_service(SERVICE_ACCOUNT_PKCS12_FILE, SERVICE_ACCOUNT_EMAIL, OAUTH_SCOPE, user_email)
    allfiles = retrieve_all(service)
    print allfiles[0]['title']



Updated source code: https://github.com/dangtrinh/gdm


Awesomenesss!!!!


References: This is google+ docs but applicable for drive: https://developers.google.com/+/domains/authentication/delegation