Lostsoul
Lostsoul

Reputation: 26057

How can I a Google Api restful endpoint using service key?

I'm using postman to memic a restful api call and trying to access google sheets API end point. When I try to access my endpoint it returns:

{
  "error": {
    "code": 403,
    "message": "The request is missing a valid API key.",
    "status": "PERMISSION_DENIED"
  }
}

which is fair enough as I did not use my API key. I created a service account and got a json file, but I plan to access using a rest endpoint so need to pass token in header but I'm not sure how.

I looked at the json file and wasn't sure what to extract in order to pass it for my rest call.

Has anyone been able to do this successfully?

Upvotes: 0

Views: 942

Answers (1)

Bertrand Martel
Bertrand Martel

Reputation: 45483

Before calling Google Services from Postman, you would need to re-create the flow for getting an access token form service account credentials :

  • build and encode the JWT payload from the data from credentials files (to populate aud, iss, sub, iat and exp)
  • request an access token using that JWT
  • make the request to the API using this access token

You can find a complete guide for this flow is located here: https://developers.google.com/identity/protocols/oauth2/service-account#authorizingrequests

Here is an example in python. You will need to install pycrypto and pyjwt to run this script :

import requests
import json
import jwt
import time

#for RS256 you may need this
#from jwt.contrib.algorithms.pycrypto import RSAAlgorithm
#jwt.register_algorithm('RS256', RSAAlgorithm(RSAAlgorithm.SHA256))

token_url = "https://oauth2.googleapis.com/token"
credentials_file_path = "./google.json"

#build and sign JWT
def build_jwt(config):
    iat = int(time.time())
    exp = iat + 3600
    payload = {
        'iss': config["client_email"],
        'sub': config["client_email"],
        'aud': token_url,
        'iat': iat,
        'exp': exp,
        'scope': 'https://www.googleapis.com/auth/spreadsheets'
    }
    jwt_headers = {
        'kid': config["private_key_id"],
        "alg": 'RS256',
        "typ": 'JWT'
    }
    signed_jwt = jwt.encode(
        payload, 
        config["private_key"], 
        headers = jwt_headers,
        algorithm = 'RS256'
    )
    return signed_jwt

with open(credentials_file_path) as conf_file:
    config = json.load(conf_file)
    # 1) build and sign JWT
    signed_jwt = build_jwt(config)
    # 2) get access token
    r = requests.post(token_url, data= {
        "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
        "assertion": signed_jwt.decode("utf-8")
    })
    token = r.json()
    print(f'token will expire in {token["expires_in"]} seconds')
    at = token["access_token"]
    print(at)

Note the value of the scope: https://www.googleapis.com/auth/spreadsheets

Probably, you can do all the above flow using Google API library depending on what programming language you prefer

The script above will print the access token :

ya29.AHES67zeEn-RDg9CA5gGKMLKuG4uVB7W4O4WjNr-NBfY6Dtad4vbIZ

Then you can use it in Postman in Authorization header as Bearer {TOKEN}.

Or using :

curl "https://sheets.googleapis.com/v4/spreadsheets/$SPREADSHEET_ID" \
     -H "Authorization: Bearer $ACCESS_TOKEN"

Note: you can find an example of using service account keys to call Google translate API here

Upvotes: 2

Related Questions