My app running on Django with Django allauth allows signup/login only via Google OAuth. Therefore when a user is registered, his social oauth details are saved to All-auth Social Accounts model and the token data saved in Social Application Tokens model.
We want the users to be logged-in as long as possible, without granting/revoking access regularly.
Question 1: The default expiry is set as 1 hour from the registration time. How can I extend this programmatically and for how long (can it be never-expire?)
Currently, a user logged in at 5:00 and I get the following data from credentials.to_json():
{
"token": "ya29.A0ARrdaM8YXPM35RXPv7UK-pXLZvWG49T-MgCZ5wMse2ADMXOZJOWFJKMaq1PkobADLptM5YX5mnrliS2yCCESqCk0NTaZJkfe6inK94j6WQMFZWIT_xRyBTOX4W3dUEiuLhHFpQcD5vS-x_Y22pUzxwgI23pp",
"refresh_token": "1//0gYC8oucHhTBVCgYIARAAGBASNwF-L9IrCG7c5IJCBMVznUrytGEFsJbsObAFvmNBoQbHHGA1KESyBWgmudEVogbes8ski87q_5g",
"client_id": "blablabla.apps.googleusercontent.com",
"client_secret": "xyzsecret"}
No other data is returned.
At 6:05, the credentials.to_json() is exactly the SAME AS ABOVE.
But to fetch any Google/Youtube API data, I get the following error in server logs:
google.auth.exceptions.RefreshError: The credentials do not contain the necessary fields need to refresh the access token.
Question 02: When there's a Refresh Token available already, why the error? As per the docs, it refreshes the token automatically few minutes before the expiry. What am I missing?
I already had "access_type": "offline" in the providers settings. I also tried adding "prompt": "consent", but no effect.
Django Settings:
INSTALLED_APPS = [
"allauth",
"allauth.account",
"allauth.socialaccount",
"allauth.socialaccount.providers.google",
...
]
AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.ModelBackend",
"allauth.account.auth_backends.AuthenticationBackend",
]
SOCIALACCOUNT_PROVIDERS = {
"google": {
"SCOPE": [
"profile",
"email",
"https://www.googleapis.com/auth/youtube",
"https://www.googleapis.com/auth/youtube.readonly",
"https://www.googleapis.com/auth/youtube.upload",
"https://www.googleapis.com/auth/youtube.force-ssl",
],
"AUTH_PARAMS": {
"access_type": "offline",
"prompt": "consent",
},
},
}
And the Django Views snippet related to OAuth:
import googleapiclient.discovery
import googleapiclient.errors
from allauth.socialaccount.models import SocialAccount, SocialApp
from google.oauth2.credentials import Credentials
def get_credentials_google(user):
app_google = SocialApp.objects.get(provider="google")
account = SocialAccount.objects.get(user=user)
user_tokens = account.socialtoken_set.first()
creds = Credentials(
token=user_tokens.token,
refresh_token=user_tokens.token_secret,
client_id=app_google.client_id,
client_secret=app_google.secret,
)
return creds
def get_youtube_account(user):
api_service_name = "youtube"
api_version = "v3"
credentials = get_credentials_google(user)
youtube = googleapiclient.discovery.build(
api_service_name, api_version, credentials=credentials
)
return youtube
def get_youtube_videos(request):
youtube = get_youtube_account(request.user)
request = youtube.liveBroadcasts().list(
part="id, snippet, contentDetails, status",
broadcastStatus="completed",
broadcastType="all"
)
response = request.execute()
return response
Note: There's no front-end framework I'm using django with django template UI.