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:
- create and download all the necessary credentials, such as Client ID;
- 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;
- in my script, create the credentials with the .json and make requests on behalf of G Suite admin;
- 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