1
votes

I'm currently using a Google Service Account that has domain wide delegation enabled ( I followed this link https://developers.google.com/identity/protocols/oauth2/service-account, and this link https://developers.google.com/admin-sdk/reports/v1/guides/delegation), and has "https://www.googleapis.com/auth/drive scope enabled. I have downloaded the json credentials for the service account and placed them in the same directory as my python script. The problem is when I impersonate another user lets say User2 in my domain, and I try to list out the files in User2's drive. I only get the files in my service account's drive.

I have a snippet of the code doing the impersonation of User2.

def auth():
    domain = 'domain'
    # impersonate this user
    user = 'testuser' # id only (ie. without @domain)
    #scopes = ['https://www.googleapis.com/auth/drive',]
    key_file = 'service_account.json'

    subject = ''.join([user,'@',domain])
    delegated_credentials = service_account.Credentials.from_service_account_file(key_file)
    delegated_credentials.with_subject(subject)
    drive_service = googleapiclient.discovery.build('drive', 'v2', credentials=delegated_credentials)

    return drive_service

Then later I'm trying to get the list of files in a users mydrive.

children = service.children().list(folderId='root', **param).execute()

for child in children.get('items', []):
    item = service.files().get(fileId=child['id']).execute()

Above item is always the "Getting Started PDF" in the service account's my drive

Basically the whole purpose of this is to programatically change ownership of any folder(plus its contents) to anther user in the same G-Suite.

Also, I don't want to share a folder with my service account as many other posts say. This shouldn't be the case as I'm impersonating the owner.

1

1 Answers

2
votes

Answer:

There are two issues with your authentication flow: missing scopes, and a mis-assigned variable.

More Information:

  1. You are missing scopes from your delegated credentials when you assign the delegated_credentials variable.
  2. You are not assigning your newly delegated credentials when you add a subject.

As you can see in the Preparing to make an authorized API call documentation, when defining your credentials object you must specify which scopes you will be using in the request.

Then, when adding the scope to the credentials, you need to assign this to a variable which can be passed to the build of the Drive service.

Code fixes:

To fix point 1, you need to uncomment your scopes and change this line:

delegated_credentials = service_account.Credentials.from_service_account_file(key_file)

to include the scopes:

scopes = ['https://www.googleapis.com/auth/drive']
delegated_credentials = service_account.Credentials.from_service_account_file(
        key_file, scopes=scopes)

Also, you will need to assign the delegated_credentials.with_subject(subject) to itself before building the drive service:

delegated_credentials = delegated_credentials.with_subject(subject)
drive_service = googleapiclient.discovery.build(
        'drive', 'v2', credentials=delegated_credentials)

References: