Skip to content

Instantly share code, notes, and snippets.

@codingforentrepreneurs
Created September 12, 2024 19:49

Revisions

  1. codingforentrepreneurs created this gist Sep 12, 2024.
    13 changes: 13 additions & 0 deletions a-youtube-oauth-django-sample.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,13 @@
    # 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.
    23 changes: 23 additions & 0 deletions services.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,23 @@
    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')
    91 changes: 91 additions & 0 deletions views.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,91 @@
    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)