4
votes

My Python script retrieves infos about users and groups from a G Suite (testing, for now, with the 14 days free account). I'm using domain-wide delegation and OAuth 2.0 for server to server applications because I don't want to display a pop window where users from hosted domains would allow me to see their groups and users.

These are the steps I followed in order to get users and groups:

  1. create and download all the necessary credentials, such as Client ID;
  2. from my G Suite admin console, allow access to my Client ID and give it the rights to access to users and groups API with the same scopes of my script;
  3. in my script, create the credentials with the .json and make requests on behalf of G Suite admin;
  4. start calling APIs.

Now, the G Suite admin has to allow, in its Security settings, to a certain Client ID some scopes: this I made by hand, manually entering Client ID and scopes. In the OAuth 2.0 for Server to Server Applications tutorial it reads:

If you have delegated domain-wide access to the service account and you want to impersonate a user account, use the with_subject method of an existing service_account.Credentials object.

So: I gave myself access from G suite admin panel to some APIs, my script creates credentials for using that APIs but the .json I downloaded is not enough: it seems that with domain-wide delegation my script still have to make requests on behalf of a user from that hosted domain, in my case the admin of the hosted domain. I tried to create the credentials wihtout impersonating a user, but I did not have enough permissions to do so and the call to APIs returns me 401 or 403.

I thought that a delegated access did not need to act on behalf of a user, since the service account is not associated to any user.

Can I create credentials for a service account without impersonating a user belonging to the hosted domain I'm working with? Are my Client ID and .json file containing my private key and other stuff not enough?

Here's my code:

from google.oauth2 import service_account
import googleapiclient.discovery
import json

""" CONSTANTS AND GLOBAL VARIABLES
"""
# The API we request to use
SCOPES = ['https://www.googleapis.com/auth/admin.directory.group.readonly',
        'https://www.googleapis.com/auth/admin.directory.user.readonly']
# json containing keys, account service email, id client and other stuff
SERVICE_ACCOUNT_FILE = 'my_file.json'
# The hosted domain we want to work with
DOMAIN = 'some_hd.it'
# The user I'm using to create credentials
USER_EMAIL = 'name.surname@some_hd.it'


""" SETTING AND GETTING CREDENTIALS
"""
credentials = service_account.Credentials.from_service_account_file(
        SERVICE_ACCOUNT_FILE, scopes=SCOPES)

if credentials is None:
        print "BAD CREDENTIALS"

delegated_credentials = credentials.with_subject(USER_EMAIL)

"""
        build('api_name', 'api_version', ...)
        https://developers.google.com/api-client-library/python/apis/
"""
service = googleapiclient.discovery.build('admin', 'directory_v1',
        credentials=delegated_credentials)


""" GETTING GROUPS AND USERS
"""
request = service.groups().list(domain=DOMAIN)
response = request.execute()
groups = response.get('groups', [])
if not groups:
        print "No groups in %s" % (DOMAIN)
print

request = service.users().list(domain=DOMAIN)
response = request.execute()
users = response.get('users', [])
if not users:
        print "No users in %s" % (DOMAIN)
else:
        for user in users:
                for email in user['emails']:
                        print email['address']
                print 'User ID: %s' % (user['id'])
                print 'Is admin? %s' % (str(user['isAdmin']))
                print
1

1 Answers

2
votes

I've been working with Google API for a while and we have the same scenario and no, as far as i know, you'll need to impersonate.

Note that simply allowing the API, download the credential and give scopes permissions to the client ID isnt enough.

For certain services like Directory API, you need to give specifc read and write permissions to the user that you're going to impersonate from the admin gsuite panel to be able to access your groups and users.