Google Service Account Authentication For Python API Calls: A Simple Example

This example is going to target the DV360 Google API.

Preparation

We need to gather the following credential, account and service information before we can make any API calls.

Scope

In short for the DV360 service it has the following authentication scope.

"scopes": ["https://www.googleapis.com/auth/display-video"]

Each google service has a scope. You can find the required scopes from the “Discovery Document” for a particular service. If you read the DV360 Google API docs you will find a link to the DV360 Discovery Document.

It is a JSON document and can be found at the following location,

https://displayvideo.googleapis.com/$discovery/rest?version=v1

it is a specification for describing and consuming the DV360 REST API.

If you want to write more involved client libraries, or any other tools to interact with Google APIs, your code should reference the Discovery Document.

We’re going to just make a note of the scope value for this service and discard the rest of the Discovery Document to keep this example simple.

Service Endpoint

The base URL for the DV360 REST API is the following,

https://displayvideo.googleapis.com

Service Credentials JSON File

You can generate a service account json file by visiting,

https://console.developers.google.com/iam-admin/iam/

while logged in to your google service account.

  1. Select your project.
  2. Select “service accounts”.
  3. Create a new one. I recommend selecting the role as “viewer”.
{
  "type": "service_account",
  "project_id": <your project id>,
  "private_key_id": <your private key id> ,
  "private_key": <your private key> ,  
  "client_email": <your client email> ,
  "client_id": <your client id> ,
  "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": <your client_x509_cert_url >
}

Save this file. I suggest calling it 360servicecreds.json

Account Info JSON File

You’ll need to create this file yourself with your account details for your particular Google API. For the DV360 API we need the keys advertiser_id, partner_id, service_endpoint, and the scope list we took note of earlier.

{
    "advertiser_id": <your advertisers id>,
    "partner_id": <your partner id>,
    "service_endpoint": "https://displayvideo.googleapis.com/",
    "scopelist" : [ "https://www.googleapis.com/auth/display-video"]
}

Save this file. I suggest calling it 360accountinfo.json

Making API Calls

First set the following ENV, environment, variables.

  • GOOGLE_APPLICATION_CREDENTIALS
  • GOOGLE_DV360_ACCOUNT_INFO

These should point to the location of the two JSON files we created above.

export GOOGLE_APPLICATION_CREDENTIALS=/home/ubuntu/.creds/.google/360servicecreds.json
export GOOGLE_DV360_ACCOUNT_INFO=/home/ubuntu/.creds/.google/360accountinfo.json

Make Requests Using A Google AuthorizedSession

The Google AuthorizedSession class inherits from requests.Session, it handles all of the authorization for you, adds all of the authorization headers, and allows you to make all of the same method calls you would expect with a standard session.

#!/usr/bin/env python3

# Python module to interact with the operating system
import os

# A super simple JSON based settings (jettings) manager for all your python application needs
from jettings import Jettings

# Google authentication
import google.auth
from google.auth.transport.requests import AuthorizedSession

# Get the location of the 360accountinfo.json file from your environment variable.
accountinfo = os.getenv("GOOGLE_DV360_ACCOUNT_INFO")
# Read in your account information
jaccountinfo = Jettings(accountinfo)

# Retrieve DV360 account information.
advertiser_id = jaccountinfo.gets(["advertiser_id"])
partner_id = jaccountinfo.gets(["partner_id"])
service_endpoint = jaccountinfo.gets(["service_endpoint"])
scopes_list = jaccountinfo.gets(["scopelist"])

# Authenticate against google.
# google.auth.default references the environment variable GOOGLE_APPLICATION_CREDENTIALS
credentials, project = google.auth.default(scopes=scopes_list)

# Create a Google AuthorizedSession
authorized_session = AuthorizedSession(credentials)

# Carry out an AuthorizedSession request
# Here we carry out a GET request
response = authorized_session.get(
    f"{service_endpoint}/v1/advertisers", params={"partnerId": partner_id}
)

# You can output the text of the response.
print(response.text)

# You can output the raw byte string of the response.
print(response.content)

# You could decode the byte content yourself in to text.
# Get the encoding.  Most likely it is UTF-8.
encoding = response.encoding
# Decode the content
content_decoded = response.content.decode(encoding)

# Output the response content
print(content_decoded)

Make A Prepared Request

To create a prepared request you need to avoid using the Google AuthorizedSession completely and fall back on to standard python Session().

You do need to extract an authentication token using google.auth though.

The following python code extracts an authentication token, prepares a standard request with authentication headers, and finally sends the prepared request using a standard Session().

Read the comments in the code for guidance.

#!/usr/bin/env python3

# Python module to interact with the operating system
import os

# Import Request and Session classes from the python requests module
from requests import Request, Session

# A super simple JSON based settings (jettings) manager for all your python application needs
from jettings import Jettings

# Google authentication
import google.auth
import google.auth.transport.requests

# Get the location of the 360accountinfo.json file from your environment variable.
accountinfo = os.getenv("GOOGLE_DV360_ACCOUNT_INFO")
# Read in your account information
jaccountinfo = Jettings(accountinfo)

# Retrieve DV360 account information.
advertiser_id = jaccountinfo.gets(["advertiser_id"])
partner_id = jaccountinfo.gets(["partner_id"])
service_endpoint = jaccountinfo.gets(["service_endpoint"])
scopes_list = jaccountinfo.gets(["scopelist"])

# Authenticate against google.
# google.auth.default references the environment variable GOOGLE_APPLICATION_CREDENTIALS
credentials, project = google.auth.default(scopes=scopes_list)

# Using the credentials we just obtained, and the google request adapter
# we can extract an authorization token.
google_request_adapter = google.auth.transport.requests.Request()
credentials.refresh(google_request_adapter)

# The token can be found in credentials.token
# Print it out if you like
print(credentials.token)
# We no longer need to use any google authentication libraries unless
# you want to refresh the token.


## PREPARE A REQUEST

# Much like any prepared request you have ever made before.

# First we build a standard request object.

# Here is our complete endpoint api url
url = f"{service_endpoint}/v1/advertisers"

# Here we build  a request object complete with our credential.token
# in the authorization headers, and also required parameters to make
# a call to /v1/advertisers.
myrequest = Request(
    "GET",
    url,
    headers={"Authorization": f"Bearer {credentials.token}"},
    params={"partnerId": partner_id},
)

# We use a standard python requests Session() to create a prepared request.
standard_session = Session()
prepared_request = standard_session.prepare_request(myrequest)
# Using a standard session with send our prepared request.
response = standard_session.send(prepared_request)
print(response.content)
%d bloggers like this: