Search code examples
pythongoogle-cloud-platformgoogle-apigoogle-workspace

Google API call using service account returns 400 "Invalid Input" error


I am trying to create a Google service account to make user account changes in our Google Workspace instance. I have followed the instructions on the page "Perform Google Workspace Domain-Wide Delegation of Authority". That is, I have

  1. Created a service account in our Google Cloud Project.

  2. Created a key for that service account and downloaded the JSON string version of that key.

  3. Added the service account to "Security > API Controls > Domain-wide Delegation" in the admin panel for our instance.

  4. Added the scope https://www.googleapis.com/auth/admin.directory.user to that service account in the Domain-wide Delegation section.

The code I am running is this:

import os.path

from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from google.oauth2 import service_account

SCOPES = ['https://www.googleapis.com/auth/admin.directory.user']

def main():
    creds = service_account.Credentials.from_service_account_file(
        'credentials.json', scopes=SCOPES)
    service = build('admin', 'directory_v1', credentials=creds)
    results = service.users().list(customer='my_customer', maxResults=10,
                                   orderBy='email').execute()
    users = results.get('users', [])

    if not users:
        print('No users in the domain.')
    else:
        print('Users:')
        for user in users:
            print(u'{0} ({1})'.format(user['primaryEmail'],
                                      user['name']['fullName']))

if __name__ == '__main__':
    main()

The file credentials.json (after some redacting) looks like this:

{
  "type": "service_account",
  "project_id": "myproject-uat1",
  "private_key_id": "f19f6e738923406283302659fbdde8abdsbeb2fd",
  "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvg...Wo\n-----END PRIVATE KEY-----\n",
  "client_email": "myproject-uat-a@myproject-uat1.iam.gserviceaccount.com",
  "client_id": "116674234874240871478",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/myproject-uat-a%40myproject-uat1.iam.gserviceaccount.com"
}

When I run the above I get this result:

Traceback (most recent call last):
  File "/root/test.py", line 31, in <module>
    main()
  File "/root/test.py", line 17, in main
    results = service.users().list(customer='my_customer', maxResults=10,
  File "/usr/local/lib/python3.9/dist-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/usr/local/lib/python3.9/dist-packages/googleapiclient/http.py", line 938, in execute
    raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 400 when requesting https://admin.googleapis.com/admin/directory/v1/users?customer=my_customer&maxResults=10&orderBy=email&alt=json returned "Invalid Input". Details: "[{'message': 'Invalid Input', 'domain': 'global', 'reason': 'invalid'}]">

This question is similar to this StackOverflow question but the answers to that question, unfortunately, did not help me.


Solution

  • I think you need to use create_delegated to create credentials (using the Service Account) delegated to operate on behalf of an admin user that is permitted to use the Workspace Admin APIs.

    See: example