dannypernik
dannypernik

Reputation: 302

Generate persistent token for personal use app that connects to Google Calendar API

I'm trying to set up an app for personal use to send reminder emails to Google Calendar event attendees. According to Google's app verification exceptions, I should not need to verify an app for personal use. However, my access token keeps expiring after 7 days, and my attempts to refresh the token have been in vain. I realize that apps with publishing status of "Testing" expire after 7 days, but the only other option is to submit for verification. Perhaps the fact that Google Calendar API is defined as a sensitive scope means that I have to submit for verification even though I will be the only one using it?

Running the code below returns the error google.auth.exceptions.RefreshError: ('invalid_grant: Token has been expired or revoked.' My token.json file contains values for token and refresh_token.

reminders.py:

basedir = os.path.abspath(os.path.dirname(__file__))
load_dotenv(os.path.join(basedir, '.env'))

# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']

def main():
    """Shows basic usage of the Google Calendar API.
    Prints the start and name of the next 10 events on the user's calendar.
    """
    flow = Flow.from_client_secrets_file(
                os.path.join(basedir, 'credentials.json'), SCOPES)

    authorization_url, state = flow.authorization_url(
    # Enable offline access so that you can refresh an access token without
    # re-prompting the user for permission. Recommended for web server apps.
    access_type='offline',
    # Enable incremental authorization. Recommended as a best practice.
    include_granted_scopes='true')

    creds = None
    # The file token.json stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.json'):
        creds = Credentials.from_authorized_user_file('token.json', SCOPES)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                os.path.join(basedir, 'credentials.json'), SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.json', 'w') as token:
            token.write(creds.to_json())

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

Upvotes: 2

Views: 1481

Answers (3)

Matthias Mairleitner
Matthias Mairleitner

Reputation: 81

Just for the sake of completeness, google verification of your production-app is not mandatory, there are exceptions, see: https://support.google.com/cloud/answer/10311615?hl=en#zippy=%2Cin-production%2Cverification-not-required%2Cneeds-verification

Google verifies projects configured for a user type of External and a publishing status of In production if they meet one or more of the OAuth verification criteria:

  • You want to display an icon or display name for your project on the OAuth consent screen.
  • Your project's OAuth clients request authorization of any sensitive or restricted scopes.
  • The number of authorized domains for your project exceeds the domain count limit.
  • There are changes to your project's OAuth consent screen configuration after a previous published, verified configuration.

I had the same problem with my python app accessing gdrive-api, the solution was to set the app to production state and remove the logo/icon from oauth consent screen for bypassing verification.

Upvotes: 1

Linda Lawton - DaImTo
Linda Lawton - DaImTo

Reputation: 117186

Your tokens are Expireing after seven days because your application is still in testing.

A Google Cloud Platform project with an OAuth consent screen configured for an external user type and a publishing status of "Testing" is issued a refresh token expiring in 7 days.

Solution would be to just set your project to production rather than testing. This should stop your tokens from expiring. You should not need to send it for verification just switch it to production. Nothing in the documentation nor testing by myself and others has shown that you "Must" go though verification to stop the refresh token expiration.

enter image description here

Internal

Internal projects only work for Google workspace accounts. So unless you have a workspace account then you cant set the project to internal. If you do have a workspace account and this user is on the workspace domain then you should consider using a service account instead. However if you choose to stick with oauth2 your refresh token should work for more then seven days if its internal however there is currently a bug that google is looking into which may cause the refresh token to expire on internal workspace projects. Last i heard they were looking into it.

Upvotes: 1

dannypernik
dannypernik

Reputation: 302

After contacting Google regarding this issue, I learned that the only way to obtain a persistent token for the Google Calendar API while circumventing the app verification process is to purchase a Google Workspace account for $6 per month (at the time of this writing). You then have the option to mark the app as "Internal", which enables a persistent token. Initially it seemed that a free Google Cloud Identity account would be sufficient, but Google Calendar is disabled for the free tier.

Upvotes: 0

Related Questions