djangogoogle-calendar-apipython-social-auth

Get all events of user


So currently I can login and store my refresh token(if need be I can also store the access token) in a db using Google OAuth2 while using python social auth.

models.py:

from django.db import models
from django.contrib.auth.models import AbstractUser

class Profile(AbstractUser):

    refresh_token = models.CharField(max_length=255, default="")

I have a url /calendar that needs to retrieve the Google calendar events of the currently logged user. I also have a regular login that if the user has a refresh token which means that he has linked his google account to his account. How would I use get_events to just give all of the events associated with that account.

from googleapiclient.discovery import build
from google.oauth2.credentials import Credentials
def get_events(request):
    print(request.user.refresh_token)
    credentials = Credentials(get_access_token(request), scopes=SCOPES)
    service = build('calendar', 'v3', credentials=credentials)
    google_calendar_events = service.events().list(calendarId='primary', singleEvents=True,
                                          orderBy='startTime').execute()
    google_calendar_events = google_calendar_events.get('items', [])
    return google_calendar_events 

def get_access_token(request): 
    social = request.user.social_auth.get(provider='google-oauth2') 
    return social.extra_data['access_token']

views.py

def login(request):
    if request.method == 'POST':
        form = AuthenticationForm(request.POST)
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        if user:
            if user.is_active:
                auth_login(request, user)
                return redirect('home')
            else:
                messages.error(request,'User blocked')
                return redirect('login')
        else:
            messages.error(request,'username or password not correct')
            return redirect('login')
    else:
        form = AuthenticationForm()
    return render(request, 'registration/login.html',{'form':form})

Traceback:

RefreshError at /calendar
The credentials do not contain the necessary fields need to refresh the access token. You must specify refresh_token, token_uri, client_id, and client_secret.
Request Method: GET
Request URL:    http://localhost:8000/calendar
Django Version: 3.2.9
Exception Type: RefreshError
Exception Value:    
The credentials do not contain the necessary fields need to refresh the access token. You must specify refresh_token, token_uri, client_id, and client_secret.

credentials.json

{
    "web": {
        "client_id": "-.apps.googleusercontent.com",
        "project_id": "=",
        "auth_uri": "https://accounts.google.com/o/oauth2/auth",
        "token_uri": "https://oauth2.googleapis.com/token",
        "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
        "client_secret": "-",
        "redirect_uris": ["http://127.0.0.1:8000/oauth/complete/google-oauth2/", "http://localhost:8000/oauth/complete/google-oauth2/"],
        "javascript_origins": ["http://127.0.0.1:8000", "http://localhost:8000"]
    }
}

Solution

  • From your following replying,

    It's most likely credentials = Credentials(get_access_token(request), scopes=SCOPES)

    request.user_refresh_token is the value of the refresh token as well.

    I also have a credentials.json file that contains a token_uri, client_id, and client_secret if that is correct which was used for login.

    And, your question is to retrieve the access token using the refresh token. In this case, in order to retrieve the access token, how about the following sample script?

    Sample script:

    If client_id, client_secret, refresh_token and token_uri are put in a variable, you can use the following script.

    from google.auth.transport.requests import Request
    from google.oauth2.credentials import Credentials
    
    credentials = Credentials(
        token=None,
        client_id="###", # Please set the cliend ID.
        client_secret="###", # Please set client secret.
        refresh_token='###', # Please set refresh token.
        token_uri="###" # Please set token URI.
    )
    credentials.refresh(Request())
    access_token = credentials.token
    print(access_token)
    
    # If you want to use the following script, you can use it.
    # service = build('calendar', 'v3', credentials=credentials)
    

    Or, if client_id, client_secret, refresh_token and token_uri are put in a file, you can use the following script.

    tokenFile = '###' # Please set the filename with the path.
    credentials = Credentials.from_authorized_user_file(tokenFile) # or, Credentials.from_authorized_user_file(tokenFile, scopes)
    credentials.refresh(Request())
    access_token = credentials.token
    print(access_token)
    
    # If you want to use the following script, you can use it.
    # service = build('calendar', 'v3', credentials=credentials)
    

    Reference: