Access GSuite APIs on your domain using a service account

Will van der Leij
6 min readOct 8, 2018

--

This tutorial provides a step-by-step guide to creating a service account that has delegated domain-wide access to your GSuite domain so that you can use various APIs to access and modify settings and data for your users.

My specific example simply accesses the Gmail sendAs addresses for any of the users in the domain. You could quite easily continue and modify Gmail signatures.

Originally written in 2018, this how-to still applies today. I would love to hear from anyone if there is a better or updated way to achieve this.

Many of the online tutorials on the subject focus on using OAuth user credentials that require consent to ensure that the relevant permissions are granted. Using a service account is quite straight forward but there are one or two steps that bit me so I’ve tried to write a step-by-step guide here.

Enable the GMail API

Starting from a GCP Project (mine is a temporary one called My Project 93016) you need to enable the GMail API.

From the project, click on ENABLE APIS AND SERVICES and search for the Gmail API.

Click on ENABLE. You now have the Gmail API enabled for your project. All you need now is to create some credentials for using the API.

Create a Service Account

From here we want to create a service account so that we can write a script that can access the API and perform actions on our behalf. One way is, of course, to simply use OAuth credentials that get delegated consent as you go along but the problem here is that you would still need to delegate consent for every user in your domain. We want to delegate permissions for the entire domain so that we can update everyone’s signatures for them.

From the IAM tab click on CREATE SERVICE ACCOUNT

Give your new service account a name / ID. The identifier for my service account here is gmail-signature-updater@hazel-envoy-218810.iam.gserviceaccount.com

Click on CREATE. I don’t need to grant any other roles or permissions to the account at this stage so I simply CONTINUE through the next step.

Now we want to create a key and download it so that our code can provide credentials to the API. So click on CREATE KEY.

Choose the JSON option and click CREATE. You’ll be prompted with the JSON key file being downloaded. In my example the file is called hazel-envoy-218810–5b5a90e7bf98.json. Save this somewhere very safe (goes without saying… this contains the private key for your service account)

At the end of this simply click DONE and we’ve create a service account with a key pair as seen below.

Grant Domain Access to the Service Account

Now comes the bit that caught me the first time. You need to grant this service account domain wide access to your GSuite domain.

From that Service Accounts screen you are on, click on the account you just created (click on the “email” address). This brings up a page with the details of the account. You want to change the “Enable G Suite Domain-wide Delegation” setting so click on EDIT on the top and the select that checkbox.

When you select that checkbox, you’re prompted for the product name needed for the OAuth consent screen. A bit confusing admittedly as this is a service account, nevertheless, I simply called mine the Signature Updater and clicked SAVE at the end.

We now have a service account that has been granted Domain-Wide access. However, we haven’t told the GSuite domain yet what this account is allowed to do.

To do this we need to log into the admin console of the GSuite domain using an account that has sufficient admin permissions to make security changes.

From https://admin.google.com select Security then Advanced Settings and then Manage API client access. The page looks something like this:

We want to supply the identifier of the service account and the Scope of what it is allowed to do on the domain. For updating signatures, the scope is simply https://www.googleapis.com/auth/gmail.settings.basic. In the Client Name box we copy in the identifier for the service account we created. Referring back to some of our previous steps, the Client ID we created is 106900028520942987323. Put these in and click Authorize.

You’ll end up with an entry in the table for your client ID and the scopes granted it. This means that the service account we just created now has access to the basic settings of the Gmail settings.

The service account also has domain-wide delegation so we can use it to impersonate users on the Gmail API. We’re all set to dive into code.

Use the API

My example code uses the Python API client. There are a variety of online sources on how to use the API. This tutorial is simply demonstrating the service account concept so I focus only on how to authenticate and authorise API calls.

We start by creating the service object we want to use (the Gmail API) using the credentials we’ve created. Remember we downloaded the hazel-envoy-218810–5b5a90e7bf98.json file when we created keys for the service account, we use those credentials and then delegate access to the users in the domain that you want to access.

From these delegated credentials, you can call the API to access data and settings for that user.

The above code ends up with addresses containing the sendAs addresses for the user specified in USER_EMAIL. From here, you could simply loop over a list of the users you want or you can increase the scope of the service account and access one of the directory APIs for the domain.

Conclusion

Using a service account for accessing Google APIs has a number of benefits but is only one way of achieving your goals. My use case required me to modify the Gmail signatures of all my users so I didn’t want to grant consent user by user using OAuth credentials. I needed to grant delegated access for the account. The step-by-step guide above is what I did to create and authorise that account.

From here one can play with any of the available APIs by simply granting that scope to the domain-wide account.

Note, the accounts, credentials and details provided in the examples above don’t exist. There is no use trying to access them.

--

--