Skip to content

Instantly share code, notes, and snippets.

@codingforentrepreneurs
Created September 12, 2024 19:49
Show Gist options
  • Save codingforentrepreneurs/1924bf6211e3f2cb420615e3cf48c2f4 to your computer and use it in GitHub Desktop.
Save codingforentrepreneurs/1924bf6211e3f2cb420615e3cf48c2f4 to your computer and use it in GitHub Desktop.
YouTube OAuth Workflow for Basic API Calls for Django Views

YouTube OAuth Workflow for Basic API Calls

Claude says:

This code handles YouTube OAuth2 authentication in a Django application. Here's what's happening: The youtube_connect function initiates the OAuth2 flow. It creates a Flow object with the necessary client configuration, scopes, and redirect URI. It then generates an authorization URL and redirects the user to Google's authentication page. The youtube_callback function handles the callback after user authentication. It retrieves the authorization code from the query parameters, creates another Flow object, and attempts to exchange the code for an access token. If successful, it fetches the user's email and channel ID using the token. The function returns an HTTP response indicating success or failure of the authentication process. Both functions use environment variables for client credentials and implement security measures like HTTPS enforcement and state verification. The code also includes error handling and logging for debugging purposes.

This requires the YouTube Data API enabled on your google cloud account. You also need to enable enough quotas.

If you find a better solution, please let me know. I put this as a gist to maybe use in a project in the futre. Right now, the quotas are not ideal so I have opted for Google Drive + Google Scripts.

from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
def get_user_email(user_token):
# using 'https://www.googleapis.com/auth/userinfo.email',
# to get user's email
credentials = Credentials(token=user_token.get('access_token'))
userinfo_service = build('oauth2', 'v2', credentials=credentials)
userinfo = userinfo_service.userinfo().get().execute()
return userinfo.get('email')
def get_user_channel_id(user_token):
# using 'https://www.googleapis.com/auth/youtube.readonly',
# to get user's channel id
credentials = Credentials(token=user_token.get('access_token'))
youtube_service = build('youtube', 'v3', credentials=credentials)
request = youtube_service.channels().list(
part='snippet', mine=True, maxResults=1
)
response = request.execute()
return response.get('items', [{}])[0].get('snippet', {}).get('channelId')
import os
from django.http import HttpResponse
from django.shortcuts import redirect
from google_auth_oauthlib.flow import Flow
from . import services
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '0'
# Replace these with your actual client ID and secret
CLIENT_ID = os.environ('GOOGLE_OAUTH2_KEY')
CLIENT_SECRET = os.environ('SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET')
SCOPES = [
'https://www.googleapis.com/auth/youtube.force-ssl',
'https://www.googleapis.com/auth/youtube.readonly',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
'openid',
]
API_SERVICE_NAME = 'youtube'
API_VERSION = 'v3'
def youtube_callback(request):
"""Requires quota"""
base_url = request.build_absolute_uri('/connect/youtube/').replace(
'http:', 'https:', 1
)
redirect_uri = base_url.split('?')[0] # Remove any query parameters
query_params = request.GET
if 'code' in query_params:
code = query_params.get('code')
state = query_params.get('state')
flow = Flow.from_client_config(
{
'web': {
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'auth_uri': 'https://accounts.google.com/o/oauth2/auth',
'token_uri': 'https://oauth2.googleapis.com/token',
}
},
scopes=SCOPES,
state=state,
redirect_uri=redirect_uri,
)
message = 'success'
status = 200
try:
token = flow.fetch_token(code=code)
print(f'Token: {token}')
message = 'Authentication successful!'
status = 200
except Exception as e:
print(f'Error fetching token: {str(e)}')
message = f'Authentication failed: {str(e)}'
status = 400
email = services.get_user_email(token)
channel_id = services.get_user_channel_id(token)
print(f'Profile: {email}, {channel_id}')
return HttpResponse(message, status=status)
def youtube_connect(request):
base_url = request.build_absolute_uri('/connect/youtube/').replace(
'http:', 'https:', 1
)
redirect_uri = base_url.split('?')[0] # Remove any query parameters
flow = Flow.from_client_config(
{
'web': {
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'auth_uri': 'https://accounts.google.com/o/oauth2/auth',
'token_uri': 'https://oauth2.googleapis.com/token',
}
},
scopes=SCOPES,
redirect_uri=redirect_uri,
)
authorization_url, state = flow.authorization_url(
access_type='offline', include_granted_scopes='true'
)
request.session['state'] = state
return redirect(authorization_url)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment