Marius
Marius

Reputation: 94

401 Error - Google API with service account

Hello fellow User.

I'm trying to write to a Google sheets document via a Google service account. The account has writing permission the the document, so that's not the issue.

The reason I'm using a service account is to avoid having to constantly refresh access tokens. I think there lies the issue. Because this is the response from the API:

{
  "error": {
    "code": 401,
    "message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. 
See https://developers.google.com/identity/sign-in/web/devconsole-project.",
    "status": "UNAUTHENTICATED"
  }
}

This occurs when I try sending a put request to the spreadsheet to edit data. I previously connected the service account to the sheets API, aquired the credentials from there and used them in the request.

If anyone knows, where the error might be, I'd be very thankful.

Here is the Python code that triggered the error:

        iat = time.time()
        exp = iat + 3600
        payload = {'iss': <SERVICE ACCOUNT EMAIL>,
                   'sub': <SERVICE ACCOUNT EMAIL>,
                   'aud': f'https://sheets.googleapis.com/v4/spreadsheets/<SHEETID>/values/Sheet1!A2:B5',
                   'iat': iat,
                   'exp': exp}
        additional_headers = {'kid': <PRIVATE KEY ID>}
        signed_jwt = jwt.encode(payload, key=<PRIVATE KEY>, 
                                headers=additional_headers, algorithm='RS256')

        headers = {'authorization': f'Bearer {signed_jwt}'}
        params = {'range': f'Sheet1!A2B5',
                  'majorDimension':'ROWS',
                  'values':[
                      <LISTS OF ENTRIES>
                  ]}
        spreadsheetId = <SHEETID>
        resp = requests.put(url=f'https://sheets.googleapis.com/v4/spreadsheets/{spreadsheetId}/
                                  values/Sheet1!A2:B5?valueInputOption=USER_ENTERED',
                                  data = params, headers = headers)

For anyone interested, I was following these guides:

How to use service account for authentication: https://developers.google.com/identity/protocols/oauth2/service-account#python_1

How to issue correct put request: https://developers.google.com/sheets/api/samples/writing

How to get correct endpoint for jwt-encoded credentials: https://developers.google.com/sheets/api/reference/rest

Upvotes: 1

Views: 1533

Answers (1)

Linda Lawton - DaImTo
Linda Lawton - DaImTo

Reputation: 117244

Expected OAuth 2 access token, login cookie or other valid authentication credential.

The coded used for accessing APIs with a service account is not the same as the code used for Oauth2. The code you are using appears to be trying to authenticate using Oauth2.

You should be using something like this.

credentials = ServiceAccountCredentials.from_json_keyfile_name(
  KEY_FILE_LOCATION, SCOPES)

service = build('calendar', 'v3', credentials=credentials)

Reference:

Upvotes: 2

Related Questions