Python: googleapiclient Returning "insufficient authentication scopes" When Attempting to Create Secondary Calendar with Refreshed Credentials

Viewed 134

While working with the Python googleapiclient module, I am noticing some interesting behavior that I have not been able to track down.

The Issue:

When I receive a user's credentials from Google after successfully following the OAuth2.0 flow, I am able to programmatically create a secondary calendar for the user and add events to that calendar. After these credentials expire, I am able to refresh the credentials using the offline/refresh token and can continue to lookup and add more events to the secondary calendar that was created. However, I am no longer able to create any additional secondary calendars after the credentials have been refreshed. When I attempt to do so, I receive the following error:

googleapiclient.errors.HttpError: <HttpError 403 when requesting https://www.googleapis.com/calendar/v3/calendars?alt=json returned "Request had insufficient authentication scopes.">

The authorization scopes that I am using throughout the entire process are:

SCOPES = ['https://www.googleapis.com/auth/calendar.app.created',
          'https://www.googleapis.com/auth/calendar.calendarlist.readonly']

If, after receiving this error, I then have the user successfully go through the OAuth2.0 flow again, I am able to use those credentials to create another secondary calendar as expected. That being said, this is not ideal for my application as the user's credentials expire after a few hours and it will often be days before the application needs to create new events/calendars.

Troubleshooting:

I have tried passing my developer key to the googleapiclient.discovery.build function in addition to the user's credentials to give it an additional authentication method, however when I do, I then receive the following error:

googleapiclient.errors.HttpError: <HttpError 401 when requesting https://www.googleapis.com/calendar/v3/calendars?key=[REDACTED]&alt=json returned "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.">

Researching this issue, I have found a number of sources that suggest deleting the token.pickle and refreshing the credentials.json and running through the process again. I do not use either of these files but instead store the pickled data in a DB and keep the app credentials in the environment. I have cleared out the user's credentials and made sure that my app credentials are correct.

Coding Example:

# Check to see if the credentials have expired
if not client_creds.valid:

    # If the credentials are expired and can be refreshed,
    #  then refresh the credentials
    if client_creds.expired and client_creds.refresh_token:
        client_creds.refresh(Request())
        retStatus = 0

# Use the refreshed credentials to build a Google Calendar v3 service
service = build("calendar", "v3",
                credentials=client_creds, 
                developerKey=os.environ["GCAL_APIKEY"])

# Create a body for the new calendar
newCalBody = {
    "summary": "Example Summary",
    "description": "Example Description"
}

# Attempt to create the secondary calendar for the user
created_calendar = service.calendars().insert(body=newCalBody).execute()
# At this step, the 40x error will occur

Any help would be appreciated! Thanks in advance!

1 Answers

If you check the documentation for Calendar.linsert you will notice that it requires the following scope.

enter image description here

The error message

Request had insufficient authentication scopes

Means that your applcaiton does not have the consent of the user to prform this action beouse you have only requested the following scopes

Fix your scopes and then make sure that you reauthorize the user, the consent screen must popup.

Related