Search code examples
pythondjangogoogle-oauthgoogle-calendar-apigoogle-signin

How to get Google-Calendar events using access token


I have built a django app, which it includes google Oauth2.0 login. I want to get google calendar events of every users when they login with Oauth2.0 and I wrote the following code. I saved the access token into UserAuth table and fetched it, then used it to get google calendar.

def get_events_server(request):
    user = User.objects.get(username=request.user)
    creds = UserAuth.objects.get(user=user).google_id_token

    credentials = AccessTokenCredentials(creds, "")
    http = httplib2.Http()
    http = credentials.authorize(http)

    service = build('calendar', 'v3', http=http)
    return service

When I run the code, the following error has happened.

HttpError at /calendar/
<HttpError 403 when requesting https://www.googleapis.com/calendar/v3/calendars/primary/events?timeMin=2021-10-28T04%3A33%3A08.956703Z&timeMax=2021-11-04T04%3A33%3A08.956712Z&singleEvents=true&timeZone=GMT%2B9%3A00&orderBy=startTime&alt=json returned "Request had insufficient authentication scopes.". Details: "[{'message': 'Insufficient Permission', 'domain': 'global', 'reason': 'insufficientPermissions'}]">

Is there a solution to skip this issue? enter image description here enter image description here


Solution

  • You are a little confused here lets start by looking at the difference between authentication and authorization.

    Authentication or Open Id connect is signin your letting a user signin to their google account and you get an id token back and you are able to access their profile information because the user signed in. You are authentication that the user who is behind the machine owns the account. In your code see the id_token you are using Open id connect to authentication the user.

    creds = UserAuth.objects.get(user=user).google_id_token
    

    In order to access a users private data your application needs to be authorized to access that data. Authorization is defined by scopes, or the scope of access you need. In order to use the google calendar api you will need an access token with a scope that will give you permission to access the users google calendar events

    You should have a look at the Python quickstart for google calendar it will show you how to use Oauth2 to have your application request authorization from the user to access their google calendar data.

    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.
        """
        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(
                    '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)
    
        # Call the Calendar API
        now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
        print('Getting the upcoming 10 events')
        events_result = service.events().list(calendarId='primary', timeMin=now,
                                            maxResults=10, singleEvents=True,
                                            orderBy='startTime').execute()
        events = events_result.get('items', [])
    

    from comments

    Your link consent screen request is returning an error. This is the redirect uri miss match errror and its one of the most common Errors you can get when you are setting up oauth2.

    enter image description here

    If you check the error it is telling you that there is an issue with this url redirect_uri: http://localhost:61668/ you are sending your request from that url. which means you need to go to google cloud console and add that redirect uri to your list of accepted redirect uris. Remember it must match exactly so the port number and trailing slash must be included.

    These are your current redirect uris you need to add http://localhost:61668/

    enter image description here

    try setting

    flow.run_local_server(port=0)
    

    to

    flow.run_local_server(port=8000)
    

    then add

    http://localhost:8000/
    

    as your redirect uri.

    If you don't know how this Video will show you how to fix it. Google OAuth2: How the fix redirect_uri_mismatch error. Part 2 server sided web applications.