1
votes

I am trying to get events from a Google Calendar without prompting consent page to the user. I have used a service account for this (json file with all the data)

But when I ran the script I am getting this

from google.oauth2 import service_account
import googleapiclient.discovery
import time
import jwt

SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
SERVICE_ACCOUNT_FILE = '/Users/user/Downloads/XXXXXXXX.json'

credentials = service_account.Credentials.from_service_account_file(
        SERVICE_ACCOUNT_FILE, scopes=SCOPES)

service = googleapiclient.discovery.build('calendar', 'v3', credentials=credentials)

page_token = None
calendar_list_entry = service.calendarList().get(calendarId='[email protected]').execute()

Traceback (most recent call last): File "/Users/user/Downloads/blender.py", line 16, in calendar_list_entry = service.calendarList().get(calendarId='[email protected]').execute() File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/googleapiclient/_helpers.py", line 131, in positional_wrapper return wrapped(*args, **kwargs) File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/googleapiclient/http.py", line 937, in execute raise HttpError(resp, content, uri=self.uri) googleapiclient.errors.HttpError: <HttpError 404 when requesting https://www.googleapis.com/calendar/v3/users/me/calendarList/XXXXXXXX%40group.calendar.google.com?alt=json returned "Not Found". Details: "[{'domain': 'global', 'reason': 'notFound', 'message': 'Not Found'}]">`

1

1 Answers

1
votes

In order to use Google Calendar with a serice account you must have set up domain wide deligation to your workspace account

you are getting a HttpError 404 when requesting error message because you have not properly delegated the service account to a user on your domain with access to that calendar so the service account doesnt have access.

In the code sample below take a close look at the line credentials = credentials.create_delegated(user_email) this is the user on your domain which you would like to delegate the service accounts permissions to

from googleapiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials

# Email of the Service Account
SERVICE_ACCOUNT_EMAIL = '<some-id>@developer.gserviceaccount.com'

# Path to the Service Account's Private Key file
SERVICE_ACCOUNT_PKCS12_FILE_PATH = '/path/to/<public_key_fingerprint>-privatekey.p12'

def create_directory_service(user_email):
    """Build and returns an Calendar service object authorized with the service accounts
    that act on behalf of the given user.

    Args:
      user_email: The email of the user. Needs permissions to access the calendar APIs.
    Returns:
      Calendar service object.
    """

    credentials = ServiceAccountCredentials.from_p12_keyfile(
        SERVICE_ACCOUNT_EMAIL,
        SERVICE_ACCOUNT_PKCS12_FILE_PATH,
        'notasecret',
        scopes=['https://www.googleapis.com/auth/calendar'])

    credentials = credentials.create_delegated(user_email)

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

Json key file. There is a sample for the library using the json key file here it just doesnt include the delegation you will need to add that line.

Remember service accounts only work with google workspace domains. It will not work with a standard Google calendar account.